@polkadot-apps/crypto 0.1.3 → 0.2.0

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/aes.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Encrypt binary data with AES-256-GCM.
3
+ * Generates a random 12-byte nonce.
4
+ */
5
+ export declare function aesGcmEncrypt(data: Uint8Array, key: Uint8Array): Promise<{
6
+ ciphertext: Uint8Array;
7
+ nonce: Uint8Array;
8
+ }>;
9
+ /**
10
+ * Decrypt binary data with AES-256-GCM.
11
+ */
12
+ export declare function aesGcmDecrypt(ciphertext: Uint8Array, key: Uint8Array, nonce: Uint8Array): Promise<Uint8Array>;
13
+ /**
14
+ * Encrypt a string with AES-256-GCM.
15
+ * Handles UTF-8 encoding.
16
+ */
17
+ export declare function aesGcmEncryptText(plaintext: string, key: Uint8Array): Promise<{
18
+ ciphertext: Uint8Array;
19
+ nonce: Uint8Array;
20
+ }>;
21
+ /**
22
+ * Decrypt to a string with AES-256-GCM.
23
+ * Handles UTF-8 decoding.
24
+ */
25
+ export declare function aesGcmDecryptText(ciphertext: Uint8Array, key: Uint8Array, nonce: Uint8Array): Promise<string>;
26
+ //# sourceMappingURL=aes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aes.d.ts","sourceRoot":"","sources":["../src/aes.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,wBAAsB,aAAa,CAC/B,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CASxD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAC/B,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAQrB;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACnC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,UAAU,GAChB,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CAExD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACnC,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
package/dist/aes.js ADDED
@@ -0,0 +1,76 @@
1
+ const NONCE_LENGTH = 12;
2
+ const AES_KEY_LENGTH = 32;
3
+ async function importKey(key, usage) {
4
+ if (key.length !== AES_KEY_LENGTH) {
5
+ throw new Error(`AES-256-GCM requires a 32-byte key, got ${key.length}`);
6
+ }
7
+ return crypto.subtle.importKey("raw", key, { name: "AES-GCM" }, false, [usage]);
8
+ }
9
+ /**
10
+ * Encrypt binary data with AES-256-GCM.
11
+ * Generates a random 12-byte nonce.
12
+ */
13
+ export async function aesGcmEncrypt(data, key) {
14
+ const nonce = crypto.getRandomValues(new Uint8Array(NONCE_LENGTH));
15
+ const imported = await importKey(key, "encrypt");
16
+ const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, imported, data);
17
+ return { ciphertext: new Uint8Array(ciphertext), nonce };
18
+ }
19
+ /**
20
+ * Decrypt binary data with AES-256-GCM.
21
+ */
22
+ export async function aesGcmDecrypt(ciphertext, key, nonce) {
23
+ const imported = await importKey(key, "decrypt");
24
+ const plaintext = await crypto.subtle.decrypt({ name: "AES-GCM", iv: nonce }, imported, ciphertext);
25
+ return new Uint8Array(plaintext);
26
+ }
27
+ /**
28
+ * Encrypt a string with AES-256-GCM.
29
+ * Handles UTF-8 encoding.
30
+ */
31
+ export async function aesGcmEncryptText(plaintext, key) {
32
+ return aesGcmEncrypt(new TextEncoder().encode(plaintext), key);
33
+ }
34
+ /**
35
+ * Decrypt to a string with AES-256-GCM.
36
+ * Handles UTF-8 decoding.
37
+ */
38
+ export async function aesGcmDecryptText(ciphertext, key, nonce) {
39
+ const data = await aesGcmDecrypt(ciphertext, key, nonce);
40
+ return new TextDecoder().decode(data);
41
+ }
42
+ if (import.meta.vitest) {
43
+ const { test, expect } = import.meta.vitest;
44
+ const { randomBytes } = await import("@noble/hashes/utils.js");
45
+ test("text round-trip", async () => {
46
+ const key = randomBytes(32);
47
+ const message = "hello world";
48
+ const { ciphertext, nonce } = await aesGcmEncryptText(message, key);
49
+ const decrypted = await aesGcmDecryptText(ciphertext, key, nonce);
50
+ expect(decrypted).toBe(message);
51
+ });
52
+ test("binary round-trip", async () => {
53
+ const key = randomBytes(32);
54
+ const data = randomBytes(64);
55
+ const { ciphertext, nonce } = await aesGcmEncrypt(data, key);
56
+ const decrypted = await aesGcmDecrypt(ciphertext, key, nonce);
57
+ expect(decrypted).toEqual(data);
58
+ });
59
+ test("wrong key fails", async () => {
60
+ const key = randomBytes(32);
61
+ const wrongKey = randomBytes(32);
62
+ const { ciphertext, nonce } = await aesGcmEncryptText("secret", key);
63
+ await expect(aesGcmDecryptText(ciphertext, wrongKey, nonce)).rejects.toThrow();
64
+ });
65
+ test("rejects non-32-byte key", async () => {
66
+ await expect(aesGcmEncryptText("test", randomBytes(16))).rejects.toThrow("32-byte key");
67
+ await expect(aesGcmEncryptText("test", randomBytes(64))).rejects.toThrow("32-byte key");
68
+ });
69
+ test("unique nonces per encryption", async () => {
70
+ const key = randomBytes(32);
71
+ const a = await aesGcmEncryptText("test", key);
72
+ const b = await aesGcmEncryptText("test", key);
73
+ expect(a.nonce).not.toEqual(b.nonce);
74
+ });
75
+ }
76
+ //# sourceMappingURL=aes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aes.js","sourceRoot":"","sources":["../src/aes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { randomBytes, bytesToHex, hexToBytes, utf8ToBytes, concatBytes, } from "@noble/hashes/utils.js";
2
+ //# sourceMappingURL=encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,GACd,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { randomBytes, bytesToHex, hexToBytes, utf8ToBytes, concatBytes, } from "@noble/hashes/utils.js";
2
+ //# sourceMappingURL=encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,GACd,MAAM,wBAAwB,CAAC"}
package/dist/hkdf.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export { hkdf, extract, expand } from "@noble/hashes/hkdf.js";
2
+ /**
3
+ * HKDF-SHA256 key derivation.
4
+ * Returns a 32-byte derived key. Accepts string or Uint8Array for salt and info.
5
+ */
6
+ export declare function deriveKey(ikm: Uint8Array, salt: Uint8Array | string, info: Uint8Array | string): Uint8Array;
7
+ //# sourceMappingURL=hkdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hkdf.d.ts","sourceRoot":"","sources":["../src/hkdf.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,SAAS,CACrB,GAAG,EAAE,UAAU,EACf,IAAI,EAAE,UAAU,GAAG,MAAM,EACzB,IAAI,EAAE,UAAU,GAAG,MAAM,GAC1B,UAAU,CAIZ"}
package/dist/hkdf.js ADDED
@@ -0,0 +1,31 @@
1
+ import { hkdf } from "@noble/hashes/hkdf.js";
2
+ import { sha256 } from "@noble/hashes/sha2.js";
3
+ export { hkdf, extract, expand } from "@noble/hashes/hkdf.js";
4
+ /**
5
+ * HKDF-SHA256 key derivation.
6
+ * Returns a 32-byte derived key. Accepts string or Uint8Array for salt and info.
7
+ */
8
+ export function deriveKey(ikm, salt, info) {
9
+ const saltBytes = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
10
+ const infoBytes = typeof info === "string" ? new TextEncoder().encode(info) : info;
11
+ return hkdf(sha256, ikm, saltBytes, infoBytes, 32);
12
+ }
13
+ if (import.meta.vitest) {
14
+ const { test, expect } = import.meta.vitest;
15
+ test("deriveKey is deterministic with 32-byte output", () => {
16
+ const ikm = new Uint8Array(32).fill(0xab);
17
+ const a = deriveKey(ikm, "salt", "info");
18
+ const b = deriveKey(ikm, "salt", "info");
19
+ expect(a).toEqual(b);
20
+ expect(a.length).toBe(32);
21
+ });
22
+ test("deriveKey accepts string and Uint8Array params", () => {
23
+ const ikm = new Uint8Array(32).fill(0xcd);
24
+ const saltBytes = new TextEncoder().encode("salt");
25
+ const infoBytes = new TextEncoder().encode("info");
26
+ const fromStrings = deriveKey(ikm, "salt", "info");
27
+ const fromBytes = deriveKey(ikm, saltBytes, infoBytes);
28
+ expect(fromStrings).toEqual(fromBytes);
29
+ });
30
+ }
31
+ //# sourceMappingURL=hkdf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hkdf.js","sourceRoot":"","sources":["../src/hkdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;GAGG;AACH,MAAM,UAAU,SAAS,CACrB,GAAe,EACf,IAAyB,EACzB,IAAyB;IAEzB,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnF,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnF,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;IAE5C,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACvD,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACP,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,5 @@
1
- export declare const foo = "crypto";
1
+ export * from "./aes.js";
2
+ export * from "./hkdf.js";
3
+ export * from "./nacl.js";
4
+ export * from "./encoding.js";
2
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,GAAG,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,5 @@
1
- export const foo = "crypto";
2
- if (import.meta.vitest) {
3
- const { test, expect } = import.meta.vitest;
4
- test("foo is crypto", () => {
5
- expect(foo).toBe("crypto");
6
- });
7
- }
1
+ export * from "./aes.js";
2
+ export * from "./hkdf.js";
3
+ export * from "./nacl.js";
4
+ export * from "./encoding.js";
8
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,GAAG,GAAG,QAAQ,CAAC;AAE5B,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;IAE5C,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE;QACvB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC"}
package/dist/nacl.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export { default as nacl } from "tweetnacl";
2
+ /**
3
+ * Sealed box encrypt: uses an ephemeral keypair so the recipient cannot identify the sender.
4
+ * Output format: ephemeralPubKey(32) || nonce(24) || ciphertext
5
+ */
6
+ export declare function sealedBoxEncrypt(message: Uint8Array, recipientPublicKey: Uint8Array): Uint8Array;
7
+ /**
8
+ * Sealed box decrypt: extract ephemeral public key and nonce, then open with recipient's secret key.
9
+ * Input format: ephemeralPubKey(32) || nonce(24) || ciphertext
10
+ */
11
+ export declare function sealedBoxDecrypt(sealed: Uint8Array, recipientSecretKey: Uint8Array): Uint8Array;
12
+ //# sourceMappingURL=nacl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nacl.d.ts","sourceRoot":"","sources":["../src/nacl.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAM5C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,GAAG,UAAU,CAehG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,UAAU,GAAG,UAAU,CAe/F"}
package/dist/nacl.js ADDED
@@ -0,0 +1,60 @@
1
+ import nacl from "tweetnacl";
2
+ export { default as nacl } from "tweetnacl";
3
+ const PUBKEY_LEN = 32;
4
+ const NONCE_LEN = 24;
5
+ const OVERHEAD = PUBKEY_LEN + NONCE_LEN;
6
+ /**
7
+ * Sealed box encrypt: uses an ephemeral keypair so the recipient cannot identify the sender.
8
+ * Output format: ephemeralPubKey(32) || nonce(24) || ciphertext
9
+ */
10
+ export function sealedBoxEncrypt(message, recipientPublicKey) {
11
+ const ephemeral = nacl.box.keyPair();
12
+ const nonce = nacl.randomBytes(NONCE_LEN);
13
+ const encrypted = nacl.box(message, nonce, recipientPublicKey, ephemeral.secretKey);
14
+ if (!encrypted) {
15
+ throw new Error("Encryption failed");
16
+ }
17
+ const result = new Uint8Array(OVERHEAD + encrypted.length);
18
+ result.set(ephemeral.publicKey, 0);
19
+ result.set(nonce, PUBKEY_LEN);
20
+ result.set(encrypted, OVERHEAD);
21
+ return result;
22
+ }
23
+ /**
24
+ * Sealed box decrypt: extract ephemeral public key and nonce, then open with recipient's secret key.
25
+ * Input format: ephemeralPubKey(32) || nonce(24) || ciphertext
26
+ */
27
+ export function sealedBoxDecrypt(sealed, recipientSecretKey) {
28
+ if (sealed.length < OVERHEAD + nacl.box.overheadLength) {
29
+ throw new Error("Sealed data too short");
30
+ }
31
+ const ephemeralPubKey = sealed.subarray(0, PUBKEY_LEN);
32
+ const nonce = sealed.subarray(PUBKEY_LEN, OVERHEAD);
33
+ const ciphertext = sealed.subarray(OVERHEAD);
34
+ const decrypted = nacl.box.open(ciphertext, nonce, ephemeralPubKey, recipientSecretKey);
35
+ if (!decrypted) {
36
+ throw new Error("Decryption failed - invalid key or corrupted data");
37
+ }
38
+ return decrypted;
39
+ }
40
+ if (import.meta.vitest) {
41
+ const { test, expect } = import.meta.vitest;
42
+ test("sealed box round-trip", () => {
43
+ const recipient = nacl.box.keyPair();
44
+ const message = new TextEncoder().encode("hello sealed box");
45
+ const sealed = sealedBoxEncrypt(message, recipient.publicKey);
46
+ const decrypted = sealedBoxDecrypt(sealed, recipient.secretKey);
47
+ expect(new TextDecoder().decode(decrypted)).toBe("hello sealed box");
48
+ });
49
+ test("sealed box wrong key fails", () => {
50
+ const recipient = nacl.box.keyPair();
51
+ const wrongRecipient = nacl.box.keyPair();
52
+ const message = new TextEncoder().encode("secret");
53
+ const sealed = sealedBoxEncrypt(message, recipient.publicKey);
54
+ expect(() => sealedBoxDecrypt(sealed, wrongRecipient.secretKey)).toThrow();
55
+ });
56
+ test("sealed box rejects truncated data", () => {
57
+ expect(() => sealedBoxDecrypt(new Uint8Array(10), nacl.box.keyPair().secretKey)).toThrow("Sealed data too short");
58
+ });
59
+ }
60
+ //# sourceMappingURL=nacl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nacl.js","sourceRoot":"","sources":["../src/nacl.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polkadot-apps/crypto",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,6 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
+ "@noble/hashes": "^2.0.1",
20
21
  "tweetnacl": "^1.0.3"
21
22
  },
22
23
  "devDependencies": {