Revert "Remove pbkdf2Sha512Crypto and getCryptoModule"

This reverts commit 1eb7f49446 (PR #1342).
This commit is contained in:
Simon Warta 2022-12-20 13:57:53 +01:00
parent d6c962b3eb
commit 29afc855ef
3 changed files with 77 additions and 7 deletions

View File

@ -12,10 +12,6 @@ and this project adheres to
- all: Add full support for Node.js 18 and run all CI tests with it ([#1240]).
- @cosmjs/tendermint-rpc: Remove unused `index` field from `RpcTxEvent` and
`TxEvent`. This is unset starting with Tendermint 0.34.
- @cosmjs/crypto: The pbkdf2 implementation for old Node.js versions
`pbkdf2Sha512Crypto` was removed. Node.js has sufficient support for WebCrypto
these days and we still have a pure-JS fallback implementation. This avoids
unnecessary problems around importing Node.js modules. ([#1341])
- @cosmjs/proto-signing: Make input and output of `decodePubkey` non-optional
([#1289]).
- @cosmjs/stargate: Remove unnecessary address prefix argument from
@ -31,7 +27,6 @@ and this project adheres to
[#1289]: https://github.com/cosmos/cosmjs/issues/1289
[#1291]: https://github.com/cosmos/cosmjs/issues/1291
[#1329]: https://github.com/cosmos/cosmjs/pull/1329
[#1341]: https://github.com/cosmos/cosmjs/issues/1341
## [0.29.5] - 2022-12-07

View File

@ -1,6 +1,13 @@
import { fromHex, toAscii, toUtf8 } from "@cosmjs/encoding";
import { getSubtle, pbkdf2Sha512, pbkdf2Sha512Noble, pbkdf2Sha512Subtle } from "./pbkdf2";
import {
getCryptoModule,
getSubtle,
pbkdf2Sha512,
pbkdf2Sha512Crypto,
pbkdf2Sha512Noble,
pbkdf2Sha512Subtle,
} from "./pbkdf2";
interface TestVector {
secret: Uint8Array;
@ -139,6 +146,25 @@ describe("pbkdf2", () => {
});
});
describe("pbkdf2Sha512Crypto", () => {
it("works", async () => {
const crypto = await getCryptoModule();
if (!crypto) pending("The crypto module is not available in this environment");
{
const { secret, salt, iterations, keylen, expected } = botanTest;
const hash = await pbkdf2Sha512Crypto(crypto, 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 pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
expect(hash).withContext(`brycx tests index ${index}`).toEqual(expected);
}
});
});
describe("pbkdf2Sha512Noble", () => {
it("works", async () => {
{

View File

@ -2,6 +2,27 @@ 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`
* otherwise.
*
* Detects an unimplemented fallback module from Webpack 5 and returns
* `undefined` in that case.
*/
export async function getCryptoModule(): Promise<any | undefined> {
try {
const crypto = await import("crypto");
// We get `Object{default: Object{}}` as a fallback when using
// `crypto: false` in Webpack 5, which we interprete as unavailable.
if (typeof crypto === "object" && Object.keys(crypto).length <= 1) {
return undefined;
}
return crypto;
} catch {
return undefined;
}
}
export async function getSubtle(): Promise<any | undefined> {
// From Node.js 15 onwards, webcrypto is available in globalThis.
// In version 15 and 16 this was stored under the webcrypto key.
@ -47,6 +68,29 @@ export async function pbkdf2Sha512Subtle(
);
}
export async function pbkdf2Sha512Crypto(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
crypto: any,
secret: Uint8Array,
salt: Uint8Array,
iterations: number,
keylen: number,
): Promise<Uint8Array> {
assert(crypto, "Argument crypto is falsy");
assert(typeof crypto === "object", "Argument crypto is not of type object");
assert(typeof crypto.pbkdf2 === "function", "crypto.pbkdf2 is not a function");
return new Promise((resolve, reject) => {
crypto.pbkdf2(secret, salt, iterations, keylen, "sha512", (error: any, result: any) => {
if (error) {
reject(error);
} else {
resolve(Uint8Array.from(result));
}
});
});
}
export async function pbkdf2Sha512Noble(
secret: Uint8Array,
salt: Uint8Array,
@ -69,6 +113,11 @@ export async function pbkdf2Sha512(
if (subtle) {
return pbkdf2Sha512Subtle(subtle, secret, salt, iterations, keylen);
} else {
return pbkdf2Sha512Noble(secret, salt, iterations, keylen);
const crypto = await getCryptoModule();
if (crypto) {
return pbkdf2Sha512Crypto(crypto, secret, salt, iterations, keylen);
} else {
return pbkdf2Sha512Noble(secret, salt, iterations, keylen);
}
}
}