@batalabs/virlow-crypto 3.11.11 → 3.11.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/notes.js CHANGED
@@ -25,17 +25,25 @@ async function encryptNoteFields(key, title, content) {
25
25
  }
26
26
  async function decryptNoteFields(key, encryptedTitle, encryptedContent, ivBase64) {
27
27
  const ivTitle = (0, base64_js_1.base64ToBytes)(ivBase64);
28
- // v2 content carries its own IV ("v2:<ivB64>:<ctB64>"); v1 content is plain
29
- // base64 and shares the column IV with the title. base64 never contains ':',
30
- // so detection is unambiguous.
31
- let ivContent = ivTitle;
32
- let contentCipher = encryptedContent;
33
- if (encryptedContent.startsWith('v2:')) {
34
- const rest = encryptedContent.slice(3);
35
- const sep = rest.indexOf(':');
36
- ivContent = (0, base64_js_1.base64ToBytes)(rest.slice(0, sep));
37
- contentCipher = rest.slice(sep + 1);
28
+ // Content must be v2: "v2:<ivB64>:<ctB64>", carrying its own IV. base64 never
29
+ // contains ':', so the prefix is unambiguous.
30
+ //
31
+ // v1 content was plain base64 sharing the column IV with the title, which
32
+ // made the two a two-time pad — XOR the ciphertexts and the keystream
33
+ // cancels, exposing title XOR content to anyone holding the database (TYP-275).
34
+ // Those rows were re-encrypted and the reader goes with them: a v1 blob is now
35
+ // refused rather than quietly decrypted, so the broken format cannot come back
36
+ // by being readable.
37
+ if (!encryptedContent.startsWith('v2:')) {
38
+ throw new Error('Unsupported note ciphertext: expected the v2 format ("v2:<iv>:<ciphertext>")');
38
39
  }
40
+ const rest = encryptedContent.slice(3);
41
+ const sep = rest.indexOf(':');
42
+ if (sep === -1) {
43
+ throw new Error('Malformed v2 note ciphertext: missing the IV separator');
44
+ }
45
+ const ivContent = (0, base64_js_1.base64ToBytes)(rest.slice(0, sep));
46
+ const contentCipher = rest.slice(sep + 1);
39
47
  const decryptedTitleBuffer = await crypto.subtle.decrypt({ name: constants_js_1.ENCRYPTION_CONFIG.ALGORITHM, iv: ivTitle }, key, (0, base64_js_1.base64ToArrayBuffer)(encryptedTitle));
40
48
  const decryptedContentBuffer = await crypto.subtle.decrypt({ name: constants_js_1.ENCRYPTION_CONFIG.ALGORITHM, iv: ivContent }, key, (0, base64_js_1.base64ToArrayBuffer)(contentCipher));
41
49
  const decoder = new TextDecoder();
@@ -1 +1 @@
1
- {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CAgC9B;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA+B7C;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAQjB"}
1
+ {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CAgC9B;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyC7C;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAQjB"}
package/dist/notes.js CHANGED
@@ -20,17 +20,25 @@ export async function encryptNoteFields(key, title, content) {
20
20
  }
21
21
  export async function decryptNoteFields(key, encryptedTitle, encryptedContent, ivBase64) {
22
22
  const ivTitle = base64ToBytes(ivBase64);
23
- // v2 content carries its own IV ("v2:<ivB64>:<ctB64>"); v1 content is plain
24
- // base64 and shares the column IV with the title. base64 never contains ':',
25
- // so detection is unambiguous.
26
- let ivContent = ivTitle;
27
- let contentCipher = encryptedContent;
28
- if (encryptedContent.startsWith('v2:')) {
29
- const rest = encryptedContent.slice(3);
30
- const sep = rest.indexOf(':');
31
- ivContent = base64ToBytes(rest.slice(0, sep));
32
- contentCipher = rest.slice(sep + 1);
23
+ // Content must be v2: "v2:<ivB64>:<ctB64>", carrying its own IV. base64 never
24
+ // contains ':', so the prefix is unambiguous.
25
+ //
26
+ // v1 content was plain base64 sharing the column IV with the title, which
27
+ // made the two a two-time pad — XOR the ciphertexts and the keystream
28
+ // cancels, exposing title XOR content to anyone holding the database (TYP-275).
29
+ // Those rows were re-encrypted and the reader goes with them: a v1 blob is now
30
+ // refused rather than quietly decrypted, so the broken format cannot come back
31
+ // by being readable.
32
+ if (!encryptedContent.startsWith('v2:')) {
33
+ throw new Error('Unsupported note ciphertext: expected the v2 format ("v2:<iv>:<ciphertext>")');
33
34
  }
35
+ const rest = encryptedContent.slice(3);
36
+ const sep = rest.indexOf(':');
37
+ if (sep === -1) {
38
+ throw new Error('Malformed v2 note ciphertext: missing the IV separator');
39
+ }
40
+ const ivContent = base64ToBytes(rest.slice(0, sep));
41
+ const contentCipher = rest.slice(sep + 1);
34
42
  const decryptedTitleBuffer = await crypto.subtle.decrypt({ name: ENCRYPTION_CONFIG.ALGORITHM, iv: ivTitle }, key, base64ToArrayBuffer(encryptedTitle));
35
43
  const decryptedContentBuffer = await crypto.subtle.decrypt({ name: ENCRYPTION_CONFIG.ALGORITHM, iv: ivContent }, key, base64ToArrayBuffer(contentCipher));
36
44
  const decoder = new TextDecoder();
package/dist/notes.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"notes.js","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notes.js","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@batalabs/virlow-crypto",
3
- "version": "3.11.11",
3
+ "version": "3.11.13",
4
4
  "type": "module",
5
5
  "description": "Virlow client-side encryption primitives (PBKDF2 + AES-256-GCM). Framework-free; browser and Node 20+.",
6
6
  "license": "MIT",