@metamask-previews/cryptography 0.0.0-preview-e45297452 → 0.0.0-preview-635748c9f

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/CHANGELOG.md CHANGED
@@ -9,10 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Added
11
11
 
12
- - Initial release ([#10282](https://github.com/MetaMask/core/pull/10282), [#10431](https://github.com/MetaMask/core/pull/10431), [#10403](https://github.com/MetaMask/core/pull/10403), [#10468](https://github.com/MetaMask/core/pull/10468))
12
+ - Initial release ([#10282](https://github.com/MetaMask/core/pull/10282), [#10431](https://github.com/MetaMask/core/pull/10431), [#10403](https://github.com/MetaMask/core/pull/10403), [#10468](https://github.com/MetaMask/core/pull/10468), [#10503](https://github.com/MetaMask/core/pull/10503), [#10563](https://github.com/MetaMask/core/pull/10563), [#10506](https://github.com/MetaMask/core/pull/10506))
13
13
  - Add `sha256`, `sha384`, and `sha512` functions for computing SHA digests
14
14
  - Add `hmacSha256`, `hmacSha384`, and `hmacSha512` functions for computing HMAC digests
15
15
  - Add `pbkdf2Sha256`, `pbkdf2Sha384`, and `pbkdf2Sha512` functions for key derivation
16
16
  - Add `hkdfSha256`, `hkdfSha384`, and `hkdfSha512` functions for key derivation
17
+ - Add `getPublicKey` and `getSharedSecret` functions for X25519 key derivation exported via `@metamask/cryptography/x25519`
18
+ - Add `getRandomBytes` function for generating cryptographically secure random bytes
19
+ - Add `getPublicKey`, `sign`, and `verify` functions for Ed25519 exported via `@metamask/cryptography/ed25519`
17
20
 
18
21
  [Unreleased]: https://github.com/MetaMask/core/
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Derive the Ed25519 public key corresponding to the given private key.
3
+ *
4
+ * @param privateKey - The 32-byte Ed25519 private key.
5
+ * @returns The 32-byte Ed25519 public key.
6
+ */
7
+ export declare function getPublicKey(privateKey: BufferSource): Promise<Uint8Array>;
8
+ /**
9
+ * Sign the given data using the given Ed25519 private key.
10
+ *
11
+ * @param privateKey - The 32-byte Ed25519 private key seed.
12
+ * @param data - The data to sign.
13
+ * @returns The 64-byte Ed25519 signature.
14
+ */
15
+ export declare function sign(privateKey: BufferSource, data: BufferSource): Promise<Uint8Array>;
16
+ /**
17
+ * Verify an Ed25519 signature.
18
+ *
19
+ * @param publicKey - The 32-byte Ed25519 public key.
20
+ * @param signature - The 64-byte signature to verify.
21
+ * @param data - The signed data.
22
+ * @returns `true` if the signature is valid, `false` otherwise.
23
+ */
24
+ export declare function verify(publicKey: BufferSource, signature: BufferSource, data: BufferSource): Promise<boolean>;
25
+ //# sourceMappingURL=ed25519.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ed25519.d.ts","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,YAAY,GACvB,OAAO,CAAC,UAAU,CAAC,CAiCrB;AAED;;;;;;GAMG;AACH,wBAAsB,IAAI,CACxB,UAAU,EAAE,YAAY,EACxB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAED;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAC1B,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,YAAY,EACvB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,OAAO,CAAC,CA2BlB"}
@@ -0,0 +1,60 @@
1
+ import { buildPKCS8Header, toPKCS8 } from './utils.js';
2
+ // https://www.rfc-editor.org/rfc/rfc8032
3
+ const ED25519_KEY_LENGTH = 32;
4
+ const ED25519_SIGNATURE_LENGTH = 64;
5
+ // https://www.rfc-editor.org/rfc/rfc8410#section-7
6
+ // https://github.com/nodejs/node/blob/main/test/parallel/test-webcrypto-export-import-cfrg.js
7
+ const ED25519_PKCS8_HEADER = buildPKCS8Header([0x2b, 0x65, 0x70]);
8
+ /**
9
+ * Derive the Ed25519 public key corresponding to the given private key.
10
+ *
11
+ * @param privateKey - The 32-byte Ed25519 private key.
12
+ * @returns The 32-byte Ed25519 public key.
13
+ */
14
+ export async function getPublicKey(privateKey) {
15
+ if (privateKey.byteLength !== ED25519_KEY_LENGTH) {
16
+ throw new Error(`Invalid private key length: Private key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`);
17
+ }
18
+ // The WebCrypto API expects private keys to be in PKCS8 format.
19
+ const subtlePrivateKey = await globalThis.crypto.subtle.importKey('pkcs8', toPKCS8(ED25519_PKCS8_HEADER, privateKey), { name: 'Ed25519' }, true, ['sign']);
20
+ const jwk = await globalThis.crypto.subtle.exportKey('jwk', subtlePrivateKey);
21
+ // Intentionally discarding private key from JWK (`d`).
22
+ const subtlePublicKey = await globalThis.crypto.subtle.importKey('jwk', { kty: jwk.kty, crv: jwk.crv, x: jwk.x }, { name: 'Ed25519' }, true, ['verify']);
23
+ const publicKey = await globalThis.crypto.subtle.exportKey('raw', subtlePublicKey);
24
+ return new Uint8Array(publicKey);
25
+ }
26
+ /**
27
+ * Sign the given data using the given Ed25519 private key.
28
+ *
29
+ * @param privateKey - The 32-byte Ed25519 private key seed.
30
+ * @param data - The data to sign.
31
+ * @returns The 64-byte Ed25519 signature.
32
+ */
33
+ export async function sign(privateKey, data) {
34
+ if (privateKey.byteLength !== ED25519_KEY_LENGTH) {
35
+ throw new Error(`Invalid private key length: Private key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`);
36
+ }
37
+ // The WebCrypto API expects private keys to be in PKCS8 format.
38
+ const subtleKey = await globalThis.crypto.subtle.importKey('pkcs8', toPKCS8(ED25519_PKCS8_HEADER, privateKey), { name: 'Ed25519' }, false, ['sign']);
39
+ const signature = await globalThis.crypto.subtle.sign({ name: 'Ed25519' }, subtleKey, data);
40
+ return new Uint8Array(signature);
41
+ }
42
+ /**
43
+ * Verify an Ed25519 signature.
44
+ *
45
+ * @param publicKey - The 32-byte Ed25519 public key.
46
+ * @param signature - The 64-byte signature to verify.
47
+ * @param data - The signed data.
48
+ * @returns `true` if the signature is valid, `false` otherwise.
49
+ */
50
+ export async function verify(publicKey, signature, data) {
51
+ if (publicKey.byteLength !== ED25519_KEY_LENGTH) {
52
+ throw new Error(`Invalid public key length: Public key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`);
53
+ }
54
+ if (signature.byteLength !== ED25519_SIGNATURE_LENGTH) {
55
+ throw new Error(`Invalid signature length: Signature must be exactly ${ED25519_SIGNATURE_LENGTH} bytes for Ed25519.`);
56
+ }
57
+ const subtleKey = await globalThis.crypto.subtle.importKey('raw', publicKey, { name: 'Ed25519' }, false, ['verify']);
58
+ return globalThis.crypto.subtle.verify({ name: 'Ed25519' }, subtleKey, signature, data);
59
+ }
60
+ //# sourceMappingURL=ed25519.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ed25519.js","sourceRoot":"","sources":["../src/ed25519.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvD,yCAAyC;AACzC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAC9B,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAEpC,mDAAmD;AACnD,8FAA8F;AAC9F,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAElE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAwB;IAExB,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2DAA2D,kBAAkB,qBAAqB,CACnG,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC/D,OAAO,EACP,OAAO,CAAC,oBAAoB,EAAE,UAAU,CAAC,EACzC,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,IAAI,EACJ,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAE9E,uDAAuD;IACvD,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC9D,KAAK,EACL,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EACxC,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,IAAI,EACJ,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CACxD,KAAK,EACL,eAAe,CAChB,CAAC;IAEF,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,UAAwB,EACxB,IAAkB;IAElB,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,2DAA2D,kBAAkB,qBAAqB,CACnG,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CACxD,OAAO,EACP,OAAO,CAAC,oBAAoB,EAAE,UAAU,CAAC,EACzC,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CACnD,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,SAAS,EACT,IAAI,CACL,CAAC;IAEF,OAAO,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,SAAuB,EACvB,SAAuB,EACvB,IAAkB;IAElB,IAAI,SAAS,CAAC,UAAU,KAAK,kBAAkB,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,yDAAyD,kBAAkB,qBAAqB,CACjG,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,CAAC,UAAU,KAAK,wBAAwB,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CACb,uDAAuD,wBAAwB,qBAAqB,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CACxD,KAAK,EACL,SAAS,EACT,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,KAAK,EACL,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,OAAO,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CACpC,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,SAAS,EACT,SAAS,EACT,IAAI,CACL,CAAC;AACJ,CAAC","sourcesContent":["import { buildPKCS8Header, toPKCS8 } from './utils.js';\n\n// https://www.rfc-editor.org/rfc/rfc8032\nconst ED25519_KEY_LENGTH = 32;\nconst ED25519_SIGNATURE_LENGTH = 64;\n\n// https://www.rfc-editor.org/rfc/rfc8410#section-7\n// https://github.com/nodejs/node/blob/main/test/parallel/test-webcrypto-export-import-cfrg.js\nconst ED25519_PKCS8_HEADER = buildPKCS8Header([0x2b, 0x65, 0x70]);\n\n/**\n * Derive the Ed25519 public key corresponding to the given private key.\n *\n * @param privateKey - The 32-byte Ed25519 private key.\n * @returns The 32-byte Ed25519 public key.\n */\nexport async function getPublicKey(\n privateKey: BufferSource,\n): Promise<Uint8Array> {\n if (privateKey.byteLength !== ED25519_KEY_LENGTH) {\n throw new Error(\n `Invalid private key length: Private key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`,\n );\n }\n\n // The WebCrypto API expects private keys to be in PKCS8 format.\n const subtlePrivateKey = await globalThis.crypto.subtle.importKey(\n 'pkcs8',\n toPKCS8(ED25519_PKCS8_HEADER, privateKey),\n { name: 'Ed25519' },\n true,\n ['sign'],\n );\n\n const jwk = await globalThis.crypto.subtle.exportKey('jwk', subtlePrivateKey);\n\n // Intentionally discarding private key from JWK (`d`).\n const subtlePublicKey = await globalThis.crypto.subtle.importKey(\n 'jwk',\n { kty: jwk.kty, crv: jwk.crv, x: jwk.x },\n { name: 'Ed25519' },\n true,\n ['verify'],\n );\n\n const publicKey = await globalThis.crypto.subtle.exportKey(\n 'raw',\n subtlePublicKey,\n );\n\n return new Uint8Array(publicKey);\n}\n\n/**\n * Sign the given data using the given Ed25519 private key.\n *\n * @param privateKey - The 32-byte Ed25519 private key seed.\n * @param data - The data to sign.\n * @returns The 64-byte Ed25519 signature.\n */\nexport async function sign(\n privateKey: BufferSource,\n data: BufferSource,\n): Promise<Uint8Array> {\n if (privateKey.byteLength !== ED25519_KEY_LENGTH) {\n throw new Error(\n `Invalid private key length: Private key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`,\n );\n }\n\n // The WebCrypto API expects private keys to be in PKCS8 format.\n const subtleKey = await globalThis.crypto.subtle.importKey(\n 'pkcs8',\n toPKCS8(ED25519_PKCS8_HEADER, privateKey),\n { name: 'Ed25519' },\n false,\n ['sign'],\n );\n\n const signature = await globalThis.crypto.subtle.sign(\n { name: 'Ed25519' },\n subtleKey,\n data,\n );\n\n return new Uint8Array(signature);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @param publicKey - The 32-byte Ed25519 public key.\n * @param signature - The 64-byte signature to verify.\n * @param data - The signed data.\n * @returns `true` if the signature is valid, `false` otherwise.\n */\nexport async function verify(\n publicKey: BufferSource,\n signature: BufferSource,\n data: BufferSource,\n): Promise<boolean> {\n if (publicKey.byteLength !== ED25519_KEY_LENGTH) {\n throw new Error(\n `Invalid public key length: Public key must be exactly ${ED25519_KEY_LENGTH} bytes for Ed25519.`,\n );\n }\n\n if (signature.byteLength !== ED25519_SIGNATURE_LENGTH) {\n throw new Error(\n `Invalid signature length: Signature must be exactly ${ED25519_SIGNATURE_LENGTH} bytes for Ed25519.`,\n );\n }\n\n const subtleKey = await globalThis.crypto.subtle.importKey(\n 'raw',\n publicKey,\n { name: 'Ed25519' },\n false,\n ['verify'],\n );\n\n return globalThis.crypto.subtle.verify(\n { name: 'Ed25519' },\n subtleKey,\n signature,\n data,\n );\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './hkdf.js';
2
2
  export * from './hmac.js';
3
3
  export * from './pbkdf2.js';
4
+ export * from './random.js';
4
5
  export * from './sha.js';
5
6
  export type * from './types.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,mBAAmB,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './hkdf.js';
2
2
  export * from './hmac.js';
3
3
  export * from './pbkdf2.js';
4
+ export * from './random.js';
4
5
  export * from './sha.js';
5
6
  //# 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,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC","sourcesContent":["export * from './hkdf.js';\nexport * from './hmac.js';\nexport * from './pbkdf2.js';\nexport * from './sha.js';\nexport type * from './types.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC","sourcesContent":["export * from './hkdf.js';\nexport * from './hmac.js';\nexport * from './pbkdf2.js';\nexport * from './random.js';\nexport * from './sha.js';\nexport type * from './types.js';\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generate random bytes using the platform's cryptographically secure pseudo-random number generator (CSPRNG).
3
+ *
4
+ * @param length - The number of random bytes to generate.
5
+ * @returns An `Uint8Array` of the provided length with random bytes.
6
+ * @throws If `length` is not greater than 0.
7
+ */
8
+ export declare function getRandomBytes(length: number): Uint8Array;
9
+ //# sourceMappingURL=random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAKzD"}
package/dist/random.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Generate random bytes using the platform's cryptographically secure pseudo-random number generator (CSPRNG).
3
+ *
4
+ * @param length - The number of random bytes to generate.
5
+ * @returns An `Uint8Array` of the provided length with random bytes.
6
+ * @throws If `length` is not greater than 0.
7
+ */
8
+ export function getRandomBytes(length) {
9
+ if (length <= 0) {
10
+ throw new Error('Invalid length: Length must be greater than 0.');
11
+ }
12
+ return globalThis.crypto.getRandomValues(new Uint8Array(length));
13
+ }
14
+ //# sourceMappingURL=random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.js","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACnE,CAAC","sourcesContent":["/**\n * Generate random bytes using the platform's cryptographically secure pseudo-random number generator (CSPRNG).\n *\n * @param length - The number of random bytes to generate.\n * @returns An `Uint8Array` of the provided length with random bytes.\n * @throws If `length` is not greater than 0.\n */\nexport function getRandomBytes(length: number): Uint8Array {\n if (length <= 0) {\n throw new Error('Invalid length: Length must be greater than 0.');\n }\n return globalThis.crypto.getRandomValues(new Uint8Array(length));\n}\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Convert a `BufferSource` to a `Uint8Array` view over the same bytes.
3
+ *
4
+ * @param source - The `ArrayBuffer`, typed array, or `DataView` to convert.
5
+ * @returns A `Uint8Array` sharing memory with the source.
6
+ */
7
+ export declare function toUint8Array(source: BufferSource): Uint8Array<ArrayBuffer>;
8
+ /**
9
+ * Build the 16-byte PKCS8 header for a private key.
10
+ * https://www.rfc-editor.org/rfc/rfc8410#section-7
11
+ *
12
+ * @param oid - The 3-byte curve OID.
13
+ * @returns The PKCS8 header.
14
+ */
15
+ export declare function buildPKCS8Header(oid: [number, number, number]): Uint8Array<ArrayBuffer>;
16
+ /**
17
+ * Wrap a raw private key in a PKCS8 envelope.
18
+ *
19
+ * @param header - The algorithm-specific PKCS8 header.
20
+ * @param key - The raw key bytes to wrap.
21
+ * @returns The complete PKCS8 envelope.
22
+ */
23
+ export declare function toPKCS8(header: Uint8Array, key: BufferSource): Uint8Array<ArrayBuffer>;
24
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAAC,WAAW,CAAC,CAK1E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC5B,UAAU,CAAC,WAAW,CAAC,CAiBzB;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,YAAY,GAChB,UAAU,CAAC,WAAW,CAAC,CAKzB"}
package/dist/utils.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Convert a `BufferSource` to a `Uint8Array` view over the same bytes.
3
+ *
4
+ * @param source - The `ArrayBuffer`, typed array, or `DataView` to convert.
5
+ * @returns A `Uint8Array` sharing memory with the source.
6
+ */
7
+ export function toUint8Array(source) {
8
+ if (source instanceof ArrayBuffer) {
9
+ return new Uint8Array(source);
10
+ }
11
+ return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
12
+ }
13
+ /**
14
+ * Build the 16-byte PKCS8 header for a private key.
15
+ * https://www.rfc-editor.org/rfc/rfc8410#section-7
16
+ *
17
+ * @param oid - The 3-byte curve OID.
18
+ * @returns The PKCS8 header.
19
+ */
20
+ export function buildPKCS8Header(oid) {
21
+ return new Uint8Array([
22
+ 0x30,
23
+ 0x2e,
24
+ 0x02,
25
+ 0x01,
26
+ 0x00,
27
+ 0x30,
28
+ 0x05,
29
+ 0x06,
30
+ 0x03,
31
+ ...oid,
32
+ 0x04,
33
+ 0x22,
34
+ 0x04,
35
+ 0x20,
36
+ ]);
37
+ }
38
+ /**
39
+ * Wrap a raw private key in a PKCS8 envelope.
40
+ *
41
+ * @param header - The algorithm-specific PKCS8 header.
42
+ * @param key - The raw key bytes to wrap.
43
+ * @returns The complete PKCS8 envelope.
44
+ */
45
+ export function toPKCS8(header, key) {
46
+ const pkcs8 = new Uint8Array(header.length + key.byteLength);
47
+ pkcs8.set(header);
48
+ pkcs8.set(toUint8Array(key), header.length);
49
+ return pkcs8;
50
+ }
51
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,IAAI,MAAM,YAAY,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAA6B;IAE7B,OAAO,IAAI,UAAU,CAAC;QACpB,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,GAAG,GAAG;QACN,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,MAAkB,EAClB,GAAiB;IAEjB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7D,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/**\n * Convert a `BufferSource` to a `Uint8Array` view over the same bytes.\n *\n * @param source - The `ArrayBuffer`, typed array, or `DataView` to convert.\n * @returns A `Uint8Array` sharing memory with the source.\n */\nexport function toUint8Array(source: BufferSource): Uint8Array<ArrayBuffer> {\n if (source instanceof ArrayBuffer) {\n return new Uint8Array(source);\n }\n return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);\n}\n\n/**\n * Build the 16-byte PKCS8 header for a private key.\n * https://www.rfc-editor.org/rfc/rfc8410#section-7\n *\n * @param oid - The 3-byte curve OID.\n * @returns The PKCS8 header.\n */\nexport function buildPKCS8Header(\n oid: [number, number, number],\n): Uint8Array<ArrayBuffer> {\n return new Uint8Array([\n 0x30,\n 0x2e,\n 0x02,\n 0x01,\n 0x00,\n 0x30,\n 0x05,\n 0x06,\n 0x03,\n ...oid,\n 0x04,\n 0x22,\n 0x04,\n 0x20,\n ]);\n}\n\n/**\n * Wrap a raw private key in a PKCS8 envelope.\n *\n * @param header - The algorithm-specific PKCS8 header.\n * @param key - The raw key bytes to wrap.\n * @returns The complete PKCS8 envelope.\n */\nexport function toPKCS8(\n header: Uint8Array,\n key: BufferSource,\n): Uint8Array<ArrayBuffer> {\n const pkcs8 = new Uint8Array(header.length + key.byteLength);\n pkcs8.set(header);\n pkcs8.set(toUint8Array(key), header.length);\n return pkcs8;\n}\n"]}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Derive the X25519 public key corresponding to a private key.
3
+ *
4
+ * @param privateKey - The 32-byte X25519 private key.
5
+ * @returns The 32-byte X25519 public key.
6
+ */
7
+ export declare function getPublicKey(privateKey: BufferSource): Promise<Uint8Array>;
8
+ /**
9
+ * Compute the X25519 shared secret given a private key and a peer's public key.
10
+ *
11
+ * @param privateKey - The 32-byte X25519 private key.
12
+ * @param publicKey - The 32-byte X25519 public key of the peer.
13
+ * @returns The 32-byte shared secret.
14
+ */
15
+ export declare function getSharedSecret(privateKey: BufferSource, publicKey: BufferSource): Promise<Uint8Array>;
16
+ //# sourceMappingURL=x25519.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x25519.d.ts","sourceRoot":"","sources":["../src/x25519.ts"],"names":[],"mappings":"AA8DA;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,YAAY,GACvB,OAAO,CAAC,UAAU,CAAC,CAGrB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,YAAY,EACxB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,UAAU,CAAC,CAGrB"}
package/dist/x25519.js ADDED
@@ -0,0 +1,51 @@
1
+ import { buildPKCS8Header, toPKCS8 } from './utils.js';
2
+ const X25519_KEY_LENGTH = 32;
3
+ // https://www.rfc-editor.org/rfc/rfc7748#section-4.1
4
+ const X25519_BASE_POINT = new Uint8Array(32);
5
+ X25519_BASE_POINT[0] = 9;
6
+ // https://www.rfc-editor.org/rfc/rfc8410#section-7
7
+ // https://github.com/nodejs/node/blob/main/test/parallel/test-webcrypto-export-import-cfrg.js
8
+ const X25519_PKCS8_HEADER = buildPKCS8Header([0x2b, 0x65, 0x6e]);
9
+ /**
10
+ * Perform scalar multiplication of a point by a private key,
11
+ * specified as the X25519 function in RFC 7748, Section 5.
12
+ *
13
+ * @param privateKey - The 32-byte X25519 private key (scalar).
14
+ * @param publicKey - The 32-byte X25519 public key (u-coordinate).
15
+ * @returns The 32-byte result of the scalar multiplication.
16
+ */
17
+ async function scalarMultiply(privateKey, publicKey) {
18
+ if (privateKey.byteLength !== X25519_KEY_LENGTH) {
19
+ throw new Error(`Invalid private key length: Private key must be exactly ${X25519_KEY_LENGTH} bytes for X25519.`);
20
+ }
21
+ if (publicKey.byteLength !== X25519_KEY_LENGTH) {
22
+ throw new Error(`Invalid public key length: Public key must be exactly ${X25519_KEY_LENGTH} bytes for X25519.`);
23
+ }
24
+ // The WebCrypto API expects private keys to be in PKCS8 format.
25
+ const subtlePrivateKey = await globalThis.crypto.subtle.importKey('pkcs8', toPKCS8(X25519_PKCS8_HEADER, privateKey), { name: 'X25519' }, false, ['deriveBits']);
26
+ const subtlePublicKey = await globalThis.crypto.subtle.importKey('raw', publicKey, { name: 'X25519' }, false, []);
27
+ const result = await globalThis.crypto.subtle.deriveBits({ name: 'X25519', public: subtlePublicKey }, subtlePrivateKey, X25519_KEY_LENGTH * 8);
28
+ return new Uint8Array(result);
29
+ }
30
+ /**
31
+ * Derive the X25519 public key corresponding to a private key.
32
+ *
33
+ * @param privateKey - The 32-byte X25519 private key.
34
+ * @returns The 32-byte X25519 public key.
35
+ */
36
+ export async function getPublicKey(privateKey) {
37
+ // X25519 public keys are derived as X25519(k, 9)
38
+ return scalarMultiply(privateKey, X25519_BASE_POINT);
39
+ }
40
+ /**
41
+ * Compute the X25519 shared secret given a private key and a peer's public key.
42
+ *
43
+ * @param privateKey - The 32-byte X25519 private key.
44
+ * @param publicKey - The 32-byte X25519 public key of the peer.
45
+ * @returns The 32-byte shared secret.
46
+ */
47
+ export async function getSharedSecret(privateKey, publicKey) {
48
+ // X25519 shared secrets are derived as X25519(a, K_b)
49
+ return scalarMultiply(privateKey, publicKey);
50
+ }
51
+ //# sourceMappingURL=x25519.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x25519.js","sourceRoot":"","sources":["../src/x25519.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,qDAAqD;AACrD,MAAM,iBAAiB,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;AAC7C,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAEzB,mDAAmD;AACnD,8FAA8F;AAC9F,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAEjE;;;;;;;GAOG;AACH,KAAK,UAAU,cAAc,CAC3B,UAAwB,EACxB,SAAuB;IAEvB,IAAI,UAAU,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,2DAA2D,iBAAiB,oBAAoB,CACjG,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,CAAC,UAAU,KAAK,iBAAiB,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CACb,yDAAyD,iBAAiB,oBAAoB,CAC/F,CAAC;IACJ,CAAC;IAED,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC/D,OAAO,EACP,OAAO,CAAC,mBAAmB,EAAE,UAAU,CAAC,EACxC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC9D,KAAK,EACL,SAAS,EACT,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,EAAE,CACH,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CACtD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,EAC3C,gBAAgB,EAChB,iBAAiB,GAAG,CAAC,CACtB,CAAC;IAEF,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAwB;IAExB,iDAAiD;IACjD,OAAO,cAAc,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AACvD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAwB,EACxB,SAAuB;IAEvB,sDAAsD;IACtD,OAAO,cAAc,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import { buildPKCS8Header, toPKCS8 } from './utils.js';\n\nconst X25519_KEY_LENGTH = 32;\n\n// https://www.rfc-editor.org/rfc/rfc7748#section-4.1\nconst X25519_BASE_POINT = new Uint8Array(32);\nX25519_BASE_POINT[0] = 9;\n\n// https://www.rfc-editor.org/rfc/rfc8410#section-7\n// https://github.com/nodejs/node/blob/main/test/parallel/test-webcrypto-export-import-cfrg.js\nconst X25519_PKCS8_HEADER = buildPKCS8Header([0x2b, 0x65, 0x6e]);\n\n/**\n * Perform scalar multiplication of a point by a private key,\n * specified as the X25519 function in RFC 7748, Section 5.\n *\n * @param privateKey - The 32-byte X25519 private key (scalar).\n * @param publicKey - The 32-byte X25519 public key (u-coordinate).\n * @returns The 32-byte result of the scalar multiplication.\n */\nasync function scalarMultiply(\n privateKey: BufferSource,\n publicKey: BufferSource,\n): Promise<Uint8Array> {\n if (privateKey.byteLength !== X25519_KEY_LENGTH) {\n throw new Error(\n `Invalid private key length: Private key must be exactly ${X25519_KEY_LENGTH} bytes for X25519.`,\n );\n }\n\n if (publicKey.byteLength !== X25519_KEY_LENGTH) {\n throw new Error(\n `Invalid public key length: Public key must be exactly ${X25519_KEY_LENGTH} bytes for X25519.`,\n );\n }\n\n // The WebCrypto API expects private keys to be in PKCS8 format.\n const subtlePrivateKey = await globalThis.crypto.subtle.importKey(\n 'pkcs8',\n toPKCS8(X25519_PKCS8_HEADER, privateKey),\n { name: 'X25519' },\n false,\n ['deriveBits'],\n );\n\n const subtlePublicKey = await globalThis.crypto.subtle.importKey(\n 'raw',\n publicKey,\n { name: 'X25519' },\n false,\n [],\n );\n\n const result = await globalThis.crypto.subtle.deriveBits(\n { name: 'X25519', public: subtlePublicKey },\n subtlePrivateKey,\n X25519_KEY_LENGTH * 8,\n );\n\n return new Uint8Array(result);\n}\n\n/**\n * Derive the X25519 public key corresponding to a private key.\n *\n * @param privateKey - The 32-byte X25519 private key.\n * @returns The 32-byte X25519 public key.\n */\nexport async function getPublicKey(\n privateKey: BufferSource,\n): Promise<Uint8Array> {\n // X25519 public keys are derived as X25519(k, 9)\n return scalarMultiply(privateKey, X25519_BASE_POINT);\n}\n\n/**\n * Compute the X25519 shared secret given a private key and a peer's public key.\n *\n * @param privateKey - The 32-byte X25519 private key.\n * @param publicKey - The 32-byte X25519 public key of the peer.\n * @returns The 32-byte shared secret.\n */\nexport async function getSharedSecret(\n privateKey: BufferSource,\n publicKey: BufferSource,\n): Promise<Uint8Array> {\n // X25519 shared secrets are derived as X25519(a, K_b)\n return scalarMultiply(privateKey, publicKey);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/cryptography",
3
- "version": "0.0.0-preview-e45297452",
3
+ "version": "0.0.0-preview-635748c9f",
4
4
  "description": "Provides optimized versions of commonly used cryptography functions for MetaMask clients",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -25,6 +25,14 @@
25
25
  "types": "./dist/index.d.ts",
26
26
  "default": "./dist/index.js"
27
27
  },
28
+ "./ed25519": {
29
+ "types": "./dist/ed25519.d.ts",
30
+ "default": "./dist/ed25519.js"
31
+ },
32
+ "./x25519": {
33
+ "types": "./dist/x25519.d.ts",
34
+ "default": "./dist/x25519.js"
35
+ },
28
36
  "./package.json": "./package.json"
29
37
  },
30
38
  "publishConfig": {