diff --git a/packages/cryptography/CHANGELOG.md b/packages/cryptography/CHANGELOG.md index b6531df0d11..c6a0fc94ff0 100644 --- a/packages/cryptography/CHANGELOG.md +++ b/packages/cryptography/CHANGELOG.md @@ -9,11 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- 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)) +- 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)) - Add `sha256`, `sha384`, and `sha512` functions for computing SHA digests - Add `hmacSha256`, `hmacSha384`, and `hmacSha512` functions for computing HMAC digests - Add `pbkdf2Sha256`, `pbkdf2Sha384`, and `pbkdf2Sha512` functions for key derivation - Add `hkdfSha256`, `hkdfSha384`, and `hkdfSha512` functions for key derivation - Add `getPublicKey` and `getSharedSecret` functions for X25519 key derivation exported via `@metamask/cryptography/x25519` + - Add `getRandomBytes` function for generating cryptographically secure random bytes [Unreleased]: https://github.com/MetaMask/core/ diff --git a/packages/cryptography/src/index.ts b/packages/cryptography/src/index.ts index 932af223c58..753e73d9843 100644 --- a/packages/cryptography/src/index.ts +++ b/packages/cryptography/src/index.ts @@ -1,5 +1,6 @@ export * from './hkdf.js'; export * from './hmac.js'; export * from './pbkdf2.js'; +export * from './random.js'; export * from './sha.js'; export type * from './types.js'; diff --git a/packages/cryptography/src/random.test.ts b/packages/cryptography/src/random.test.ts new file mode 100644 index 00000000000..384c046c6e7 --- /dev/null +++ b/packages/cryptography/src/random.test.ts @@ -0,0 +1,31 @@ +import { getRandomBytes } from './random.js'; + +describe('getRandomBytes', () => { + it('returns a Uint8Array of the requested length', () => { + const bytes = getRandomBytes(32); + + expect(bytes).toBeInstanceOf(Uint8Array); + expect(bytes).toHaveLength(32); + }); + + it('fills the array using `crypto.getRandomValues`', () => { + const spy = jest + .spyOn(globalThis.crypto, 'getRandomValues') + .mockImplementation((array) => { + (array as Uint8Array).fill(0xab); + return array; + }); + + const bytes = getRandomBytes(4); + + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(expect.any(Uint8Array)); + expect(bytes).toStrictEqual(new Uint8Array([0xab, 0xab, 0xab, 0xab])); + }); + + it('throws if the length is zero', () => { + expect(() => getRandomBytes(0)).toThrow( + 'Invalid length: Length must be greater than 0.', + ); + }); +}); diff --git a/packages/cryptography/src/random.ts b/packages/cryptography/src/random.ts new file mode 100644 index 00000000000..9490cdd2533 --- /dev/null +++ b/packages/cryptography/src/random.ts @@ -0,0 +1,13 @@ +/** + * Generate random bytes using the platform's cryptographically secure pseudo-random number generator (CSPRNG). + * + * @param length - The number of random bytes to generate. + * @returns An `Uint8Array` of the provided length with random bytes. + * @throws If `length` is not greater than 0. + */ +export function getRandomBytes(length: number): Uint8Array { + if (length <= 0) { + throw new Error('Invalid length: Length must be greater than 0.'); + } + return globalThis.crypto.getRandomValues(new Uint8Array(length)); +}