From d8b4521a0fb26f4095b5751e7bca2974340bba44 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 28 Feb 2022 15:48:41 +0100 Subject: [PATCH] Create noble implementation of pbkdf2Sha512 --- packages/crypto/src/pbkdf2.spec.ts | 25 ++++++++++++++++++++++++- packages/crypto/src/pbkdf2.ts | 16 ++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/packages/crypto/src/pbkdf2.spec.ts b/packages/crypto/src/pbkdf2.spec.ts index 6571c8ec..d76b48c4 100644 --- a/packages/crypto/src/pbkdf2.spec.ts +++ b/packages/crypto/src/pbkdf2.spec.ts @@ -1,6 +1,13 @@ import { fromHex, toAscii, toUtf8 } from "@cosmjs/encoding"; -import { getCryptoModule, getSubtle, pbkdf2Sha512, pbkdf2Sha512Crypto, pbkdf2Sha512Subtle } from "./pbkdf2"; +import { + getCryptoModule, + getSubtle, + pbkdf2Sha512, + pbkdf2Sha512Crypto, + pbkdf2Sha512Noble, + pbkdf2Sha512Subtle, +} from "./pbkdf2"; interface TestVector { secret: Uint8Array; @@ -157,4 +164,20 @@ describe("pbkdf2", () => { } }); }); + + describe("pbkdf2Sha512Noble", () => { + it("works", async () => { + { + const { secret, salt, iterations, keylen, expected } = botanTest; + const hash = await pbkdf2Sha512Noble(secret, salt, iterations, keylen); + expect(hash).toEqual(expected); + } + + for (const [index, test] of brycxTests.entries()) { + const { secret, salt, iterations, keylen, expected } = test; + const hash = await pbkdf2Sha512Noble(secret, salt, iterations, keylen); + expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected); + } + }, 120_000); + }); }); diff --git a/packages/crypto/src/pbkdf2.ts b/packages/crypto/src/pbkdf2.ts index 93fe949b..110b16e2 100644 --- a/packages/crypto/src/pbkdf2.ts +++ b/packages/crypto/src/pbkdf2.ts @@ -1,4 +1,6 @@ import { assert } from "@cosmjs/utils"; +import { pbkdf2Async as noblePbkdf2Async } from "@noble/hashes/pbkdf2"; +import { sha512 as nobleSha512 } from "@noble/hashes/sha512"; /** * Returns the Node.js crypto module when available and `undefined` @@ -85,6 +87,15 @@ export async function pbkdf2Sha512Crypto( }); } +export async function pbkdf2Sha512Noble( + secret: Uint8Array, + salt: Uint8Array, + iterations: number, + keylen: number, +): Promise { + return noblePbkdf2Async(nobleSha512, secret, salt, { c: iterations, dkLen: keylen }); +} + /** * A pbkdf2 implementation for BIP39. This is not exported at package level and thus a private API. */ @@ -102,10 +113,7 @@ export async function pbkdf2Sha512( if (crypto) { return pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen); } else { - throw new Error( - "Could not find a pbkdf2 implementation in subtle (WebCrypto) or the crypto module. " + - "If you need a pure software implementation, please open an issue at https://github.com/cosmos/cosmjs", - ); + return pbkdf2Sha512Noble(secret, salt, iterations, keylen); } } }