From 8e43dfb82a24a496bb1630eeb39789cac7e9e300 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 13 Oct 2020 11:02:02 +0200 Subject: [PATCH 1/4] crypto: Add convenience hash functions --- packages/crypto/src/index.ts | 6 +++--- packages/crypto/src/keccak.ts | 4 ++++ packages/crypto/src/ripemd.ts | 4 ++++ packages/crypto/src/sha.ts | 12 ++++++++++++ packages/crypto/types/index.d.ts | 6 +++--- packages/crypto/types/keccak.d.ts | 1 + packages/crypto/types/ripemd.d.ts | 1 + packages/crypto/types/sha.d.ts | 3 +++ 8 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index bd19288f..d69fa326 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -2,7 +2,7 @@ export { Bip39 } from "./bip39"; export { EnglishMnemonic } from "./englishmnemonic"; export { HashFunction } from "./hash"; export { Hmac } from "./hmac"; -export { Keccak256 } from "./keccak"; +export { Keccak256, keccak256 } from "./keccak"; export { Xchacha20poly1305Ietf, xchacha20NonceLength, @@ -13,10 +13,10 @@ export { Ed25519Keypair, } from "./libsodium"; export { Random } from "./random"; -export { Ripemd160 } from "./ripemd"; +export { Ripemd160, ripemd160 } from "./ripemd"; export { Secp256k1, Secp256k1Keypair } from "./secp256k1"; export { ExtendedSecp256k1Signature, Secp256k1Signature } from "./secp256k1signature"; -export { Sha1, Sha256, Sha512 } from "./sha"; +export { Sha1, sha1, Sha256, sha256, Sha512, sha512 } from "./sha"; export { HdPath, pathToString, diff --git a/packages/crypto/src/keccak.ts b/packages/crypto/src/keccak.ts index 3ee60552..a2f5c88e 100644 --- a/packages/crypto/src/keccak.ts +++ b/packages/crypto/src/keccak.ts @@ -24,3 +24,7 @@ export class Keccak256 implements HashFunction { return new Uint8Array(this.impl.digest()); } } + +export function keccak256(data: Uint8Array): Uint8Array { + return new Keccak256(data).digest(); +} diff --git a/packages/crypto/src/ripemd.ts b/packages/crypto/src/ripemd.ts index c726e37f..08d819a3 100644 --- a/packages/crypto/src/ripemd.ts +++ b/packages/crypto/src/ripemd.ts @@ -22,3 +22,7 @@ export class Ripemd160 implements HashFunction { return Uint8Array.from(this.impl.digest()); } } + +export function ripemd160(data: Uint8Array): Uint8Array { + return new Ripemd160(data).digest(); +} diff --git a/packages/crypto/src/sha.ts b/packages/crypto/src/sha.ts index cf4c4f53..0380b23e 100644 --- a/packages/crypto/src/sha.ts +++ b/packages/crypto/src/sha.ts @@ -26,6 +26,10 @@ export class Sha1 implements HashFunction { } } +export function sha1(data: Uint8Array): Uint8Array { + return new Sha1(data).digest(); +} + export class Sha256 implements HashFunction { public readonly blockSize = 512 / 8; @@ -49,6 +53,10 @@ export class Sha256 implements HashFunction { } } +export function sha256(data: Uint8Array): Uint8Array { + return new Sha256(data).digest(); +} + export class Sha512 implements HashFunction { public readonly blockSize = 1024 / 8; @@ -71,3 +79,7 @@ export class Sha512 implements HashFunction { return new Uint8Array(this.impl.digest()); } } + +export function sha512(data: Uint8Array): Uint8Array { + return new Sha512(data).digest(); +} diff --git a/packages/crypto/types/index.d.ts b/packages/crypto/types/index.d.ts index bd19288f..d69fa326 100644 --- a/packages/crypto/types/index.d.ts +++ b/packages/crypto/types/index.d.ts @@ -2,7 +2,7 @@ export { Bip39 } from "./bip39"; export { EnglishMnemonic } from "./englishmnemonic"; export { HashFunction } from "./hash"; export { Hmac } from "./hmac"; -export { Keccak256 } from "./keccak"; +export { Keccak256, keccak256 } from "./keccak"; export { Xchacha20poly1305Ietf, xchacha20NonceLength, @@ -13,10 +13,10 @@ export { Ed25519Keypair, } from "./libsodium"; export { Random } from "./random"; -export { Ripemd160 } from "./ripemd"; +export { Ripemd160, ripemd160 } from "./ripemd"; export { Secp256k1, Secp256k1Keypair } from "./secp256k1"; export { ExtendedSecp256k1Signature, Secp256k1Signature } from "./secp256k1signature"; -export { Sha1, Sha256, Sha512 } from "./sha"; +export { Sha1, sha1, Sha256, sha256, Sha512, sha512 } from "./sha"; export { HdPath, pathToString, diff --git a/packages/crypto/types/keccak.d.ts b/packages/crypto/types/keccak.d.ts index 419fb31b..1aec50c8 100644 --- a/packages/crypto/types/keccak.d.ts +++ b/packages/crypto/types/keccak.d.ts @@ -6,3 +6,4 @@ export declare class Keccak256 implements HashFunction { update(data: Uint8Array): Keccak256; digest(): Uint8Array; } +export declare function keccak256(data: Uint8Array): Uint8Array; diff --git a/packages/crypto/types/ripemd.d.ts b/packages/crypto/types/ripemd.d.ts index db0d6572..a2396ec8 100644 --- a/packages/crypto/types/ripemd.d.ts +++ b/packages/crypto/types/ripemd.d.ts @@ -6,3 +6,4 @@ export declare class Ripemd160 implements HashFunction { update(data: Uint8Array): Ripemd160; digest(): Uint8Array; } +export declare function ripemd160(data: Uint8Array): Uint8Array; diff --git a/packages/crypto/types/sha.d.ts b/packages/crypto/types/sha.d.ts index a5b8b212..3aed0987 100644 --- a/packages/crypto/types/sha.d.ts +++ b/packages/crypto/types/sha.d.ts @@ -6,6 +6,7 @@ export declare class Sha1 implements HashFunction { update(data: Uint8Array): Sha1; digest(): Uint8Array; } +export declare function sha1(data: Uint8Array): Uint8Array; export declare class Sha256 implements HashFunction { readonly blockSize: number; private readonly impl; @@ -13,6 +14,7 @@ export declare class Sha256 implements HashFunction { update(data: Uint8Array): Sha256; digest(): Uint8Array; } +export declare function sha256(data: Uint8Array): Uint8Array; export declare class Sha512 implements HashFunction { readonly blockSize: number; private readonly impl; @@ -20,3 +22,4 @@ export declare class Sha512 implements HashFunction { update(data: Uint8Array): Sha512; digest(): Uint8Array; } +export declare function sha512(data: Uint8Array): Uint8Array; From 53d7d34b8adad70446b951683b6c60f812322224 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 13 Oct 2020 11:20:27 +0200 Subject: [PATCH 2/4] Use convenience hash functions in codebase --- packages/cli/src/cli.ts | 4 +++- packages/cosmwasm/src/cosmwasmclient.spec.ts | 4 ++-- packages/cosmwasm/src/cosmwasmclient.ts | 4 ++-- packages/cosmwasm/src/lcdapi/wasm.spec.ts | 6 +++--- packages/cosmwasm/src/signingcosmwasmclient.spec.ts | 4 ++-- packages/cosmwasm/src/signingcosmwasmclient.ts | 6 +++--- packages/crypto/src/englishmnemonic.spec.ts | 4 ++-- packages/crypto/src/secp256k1.spec.ts | 6 +++--- packages/launchpad-ledger/src/ledgersigner.spec.ts | 4 ++-- packages/launchpad/src/address.ts | 10 +++++----- packages/launchpad/src/cosmosclient.ts | 4 ++-- packages/launchpad/src/secp256k1hdwallet.spec.ts | 4 ++-- packages/launchpad/src/secp256k1hdwallet.ts | 4 ++-- packages/launchpad/src/sequence.ts | 4 ++-- .../proto-signing/src/directsecp256k1wallet.spec.ts | 4 ++-- packages/proto-signing/src/directsecp256k1wallet.ts | 4 ++-- 16 files changed, 39 insertions(+), 37 deletions(-) diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 50ff5f71..47cbac29 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -75,7 +75,9 @@ export async function main(originalArgs: readonly string[]): Promise { "Random", "Secp256k1", "Sha256", + "sha256", "Sha512", + "sha512", "Slip10", "Slip10Curve", "Slip10RawIndex", @@ -148,7 +150,7 @@ export async function main(originalArgs: readonly string[]): Promise { const readmeContent = fs.readFileSync(process.cwd() + "/README.md"); fs.writeFileSync(process.cwd() + "/README.md", readmeContent); - const hash = new Sha512(new Uint8Array([])).digest(); + const hash = sha512(new Uint8Array([])); const hexHash = toHex(hash); export class NewDummyClass {}; diff --git a/packages/cosmwasm/src/cosmwasmclient.spec.ts b/packages/cosmwasm/src/cosmwasmclient.spec.ts index e09cbacd..ea3e4cb7 100644 --- a/packages/cosmwasm/src/cosmwasmclient.spec.ts +++ b/packages/cosmwasm/src/cosmwasmclient.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { Bech32, fromHex, fromUtf8, toAscii, toBase64 } from "@cosmjs/encoding"; import { assertIsBroadcastTxSuccess, @@ -285,7 +285,7 @@ describe("CosmWasmClient", () => { // check info expect(result).toEqual(jasmine.objectContaining(expectedInfo)); // check data - expect(new Sha256(result.data).digest()).toEqual(fromHex(expectedInfo.checksum)); + expect(sha256(result.data)).toEqual(fromHex(expectedInfo.checksum)); }); it("caches downloads", async () => { diff --git a/packages/cosmwasm/src/cosmwasmclient.ts b/packages/cosmwasm/src/cosmwasmclient.ts index f2b26ab0..f053f801 100644 --- a/packages/cosmwasm/src/cosmwasmclient.ts +++ b/packages/cosmwasm/src/cosmwasmclient.ts @@ -1,4 +1,4 @@ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { fromBase64, fromHex, toHex } from "@cosmjs/encoding"; import { AuthExtension, @@ -202,7 +202,7 @@ export class CosmWasmClient { public async getIdentifier(tx: WrappedStdTx): Promise { // We consult the REST API because we don't have a local amino encoder const response = await this.lcdClient.encodeTx(tx); - const hash = new Sha256(fromBase64(response.tx)).digest(); + const hash = sha256(fromBase64(response.tx)); return toHex(hash).toUpperCase(); } diff --git a/packages/cosmwasm/src/lcdapi/wasm.spec.ts b/packages/cosmwasm/src/lcdapi/wasm.spec.ts index 385ea78a..cd34a1a6 100644 --- a/packages/cosmwasm/src/lcdapi/wasm.spec.ts +++ b/packages/cosmwasm/src/lcdapi/wasm.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { Bech32, fromAscii, fromHex, fromUtf8, toAscii, toBase64, toHex } from "@cosmjs/encoding"; import { assertIsBroadcastTxSuccess, @@ -165,7 +165,7 @@ describe("WasmExtension", () => { expect(lastCode.creator).toEqual(alice.address0); expect(lastCode.source).toEqual(hackatom.source); expect(lastCode.builder).toEqual(hackatom.builder); - expect(lastCode.data_hash.toLowerCase()).toEqual(toHex(new Sha256(hackatom.data).digest())); + expect(lastCode.data_hash.toLowerCase()).toEqual(toHex(sha256(hackatom.data))); }); }); @@ -179,7 +179,7 @@ describe("WasmExtension", () => { expect(code.creator).toEqual(alice.address0); expect(code.source).toEqual(hackatom.source); expect(code.builder).toEqual(hackatom.builder); - expect(code.data_hash.toLowerCase()).toEqual(toHex(new Sha256(hackatom.data).digest())); + expect(code.data_hash.toLowerCase()).toEqual(toHex(sha256(hackatom.data))); expect(code.data).toEqual(toBase64(hackatom.data)); }); }); diff --git a/packages/cosmwasm/src/signingcosmwasmclient.spec.ts b/packages/cosmwasm/src/signingcosmwasmclient.spec.ts index cfb5ad6a..84bc05fc 100644 --- a/packages/cosmwasm/src/signingcosmwasmclient.spec.ts +++ b/packages/cosmwasm/src/signingcosmwasmclient.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { toHex } from "@cosmjs/encoding"; import { assertIsBroadcastTxSuccess, @@ -259,7 +259,7 @@ describe("SigningCosmWasmClient", () => { compressedChecksum, compressedSize, } = await client.upload(wasm); - expect(originalChecksum).toEqual(toHex(new Sha256(wasm).digest())); + expect(originalChecksum).toEqual(toHex(sha256(wasm))); expect(originalSize).toEqual(wasm.length); expect(compressedChecksum).toMatch(/^[0-9a-f]{64}$/); expect(compressedSize).toBeLessThan(wasm.length * 0.5); diff --git a/packages/cosmwasm/src/signingcosmwasmclient.ts b/packages/cosmwasm/src/signingcosmwasmclient.ts index 6c845eb3..834112fc 100644 --- a/packages/cosmwasm/src/signingcosmwasmclient.ts +++ b/packages/cosmwasm/src/signingcosmwasmclient.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { toBase64, toHex } from "@cosmjs/encoding"; import { BroadcastMode, @@ -212,9 +212,9 @@ export class SigningCosmWasmClient extends CosmWasmClient { const codeIdAttr = findAttribute(result.logs, "message", "code_id"); return { originalSize: wasmCode.length, - originalChecksum: toHex(new Sha256(wasmCode).digest()), + originalChecksum: toHex(sha256(wasmCode)), compressedSize: compressed.length, - compressedChecksum: toHex(new Sha256(compressed).digest()), + compressedChecksum: toHex(sha256(compressed)), codeId: Number.parseInt(codeIdAttr.value, 10), logs: result.logs, transactionHash: result.transactionHash, diff --git a/packages/crypto/src/englishmnemonic.spec.ts b/packages/crypto/src/englishmnemonic.spec.ts index e365c0b9..ec377d1b 100644 --- a/packages/crypto/src/englishmnemonic.spec.ts +++ b/packages/crypto/src/englishmnemonic.spec.ts @@ -1,7 +1,7 @@ import { fromAscii, fromBase64, fromHex } from "@cosmjs/encoding"; import { EnglishMnemonic } from "./englishmnemonic"; -import { Sha256 } from "./sha"; +import { sha256 } from "./sha"; import wordlists from "./testdata/bip39_wordlists.json"; describe("EnglishMnemonic", () => { @@ -11,7 +11,7 @@ describe("EnglishMnemonic", () => { const bip39EnglishTxt = fromBase64(wordlists.english); // Ensure we loaded the correct english.txt from https://github.com/bitcoin/bips/tree/master/bip-0039 - const checksum = new Sha256(bip39EnglishTxt).digest(); + const checksum = sha256(bip39EnglishTxt); expect(checksum).toEqual(fromHex("2f5eed53a4727b4bf8880d8f3f199efc90e58503646d9ff8eff3a2ed3b24dbda")); const wordsFromSpec: string[] = []; diff --git a/packages/crypto/src/secp256k1.spec.ts b/packages/crypto/src/secp256k1.spec.ts index 84586cb8..0e90d4a2 100644 --- a/packages/crypto/src/secp256k1.spec.ts +++ b/packages/crypto/src/secp256k1.spec.ts @@ -3,7 +3,7 @@ import { fromHex } from "@cosmjs/encoding"; import { Secp256k1 } from "./secp256k1"; import { ExtendedSecp256k1Signature, Secp256k1Signature } from "./secp256k1signature"; -import { Sha256 } from "./sha"; +import { sha256 } from "./sha"; describe("Secp256k1", () => { // How to generate Secp256k1 test vectors: @@ -383,7 +383,7 @@ describe("Secp256k1", () => { for (const [index, row] of data.entries()) { const pubkey = (await Secp256k1.makeKeypair(row.privkey)).pubkey; - const messageHash = new Sha256(row.message).digest(); + const messageHash = sha256(row.message); const isValid = await Secp256k1.verifySignature( Secp256k1Signature.fromDer(row.signature), messageHash, @@ -494,7 +494,7 @@ describe("Secp256k1", () => { for (const [index, row] of data.entries()) { const keypair = await Secp256k1.makeKeypair(row.privkey); - const messageHash = new Sha256(row.message).digest(); + const messageHash = sha256(row.message); // create signature const calculatedSignature = await Secp256k1.createSignature(messageHash, row.privkey); diff --git a/packages/launchpad-ledger/src/ledgersigner.spec.ts b/packages/launchpad-ledger/src/ledgersigner.spec.ts index a1e3a995..ff2851ad 100644 --- a/packages/launchpad-ledger/src/ledgersigner.spec.ts +++ b/packages/launchpad-ledger/src/ledgersigner.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Secp256k1, Secp256k1Signature, Sha256 } from "@cosmjs/crypto"; +import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; import { fromBase64 } from "@cosmjs/encoding"; import { coins, @@ -124,7 +124,7 @@ describe("LedgerSigner", () => { expect(signed).toEqual(signDoc); const valid = await Secp256k1.verifySignature( Secp256k1Signature.fromFixedLength(fromBase64(signature.signature)), - new Sha256(serializeSignDoc(signed)).digest(), + sha256(serializeSignDoc(signed)), fistAccount.pubkey, ); expect(valid).toEqual(true); diff --git a/packages/launchpad/src/address.ts b/packages/launchpad/src/address.ts index 5f48efa0..87fede26 100644 --- a/packages/launchpad/src/address.ts +++ b/packages/launchpad/src/address.ts @@ -1,4 +1,4 @@ -import { Ripemd160, Sha256 } from "@cosmjs/crypto"; +import { ripemd160, sha256 } from "@cosmjs/crypto"; import { Bech32, fromBase64 } from "@cosmjs/encoding"; import { PubKey, pubkeyType } from "./types"; @@ -7,8 +7,8 @@ export function rawSecp256k1PubkeyToAddress(pubkeyRaw: Uint8Array, prefix: strin if (pubkeyRaw.length !== 33) { throw new Error(`Invalid Secp256k1 pubkey length (compressed): ${pubkeyRaw.length}`); } - const hash1 = new Sha256(pubkeyRaw).digest(); - const hash2 = new Ripemd160(hash1).digest(); + const hash1 = sha256(pubkeyRaw); + const hash2 = ripemd160(hash1); return Bech32.encode(prefix, hash2); } @@ -24,14 +24,14 @@ export function pubkeyToAddress(pubkey: PubKey, prefix: string): string { if (pubkeyBytes.length !== 32) { throw new Error(`Invalid Ed25519 pubkey length: ${pubkeyBytes.length}`); } - const hash = new Sha256(pubkeyBytes).digest(); + const hash = sha256(pubkeyBytes); return Bech32.encode(prefix, hash.slice(0, 20)); } case pubkeyType.sr25519: { if (pubkeyBytes.length !== 32) { throw new Error(`Invalid Sr25519 pubkey length: ${pubkeyBytes.length}`); } - const hash = new Sha256(pubkeyBytes).digest(); + const hash = sha256(pubkeyBytes); return Bech32.encode(prefix, hash.slice(0, 20)); } default: diff --git a/packages/launchpad/src/cosmosclient.ts b/packages/launchpad/src/cosmosclient.ts index c59ec73f..8a087332 100644 --- a/packages/launchpad/src/cosmosclient.ts +++ b/packages/launchpad/src/cosmosclient.ts @@ -1,4 +1,4 @@ -import { Sha256 } from "@cosmjs/crypto"; +import { sha256 } from "@cosmjs/crypto"; import { fromBase64, fromHex, toHex } from "@cosmjs/encoding"; import { Uint53 } from "@cosmjs/math"; @@ -207,7 +207,7 @@ export class CosmosClient { public async getIdentifier(tx: WrappedStdTx): Promise { // We consult the REST API because we don't have a local amino encoder const response = await this.lcdClient.encodeTx(tx); - const hash = new Sha256(fromBase64(response.tx)).digest(); + const hash = sha256(fromBase64(response.tx)); return toHex(hash).toUpperCase(); } diff --git a/packages/launchpad/src/secp256k1hdwallet.spec.ts b/packages/launchpad/src/secp256k1hdwallet.spec.ts index f8cb95ea..f053accc 100644 --- a/packages/launchpad/src/secp256k1hdwallet.spec.ts +++ b/packages/launchpad/src/secp256k1hdwallet.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { Secp256k1, Secp256k1Signature, Sha256 } from "@cosmjs/crypto"; +import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; import { fromBase64, fromHex } from "@cosmjs/encoding"; import { serializeSignDoc, StdSignDoc } from "./encoding"; @@ -124,7 +124,7 @@ describe("Secp256k1HdWallet", () => { expect(signed).toEqual(signDoc); const valid = await Secp256k1.verifySignature( Secp256k1Signature.fromFixedLength(fromBase64(signature.signature)), - new Sha256(serializeSignDoc(signed)).digest(), + sha256(serializeSignDoc(signed)), defaultPubkey, ); expect(valid).toEqual(true); diff --git a/packages/launchpad/src/secp256k1hdwallet.ts b/packages/launchpad/src/secp256k1hdwallet.ts index 92b89194..32e44569 100644 --- a/packages/launchpad/src/secp256k1hdwallet.ts +++ b/packages/launchpad/src/secp256k1hdwallet.ts @@ -5,7 +5,7 @@ import { pathToString, Random, Secp256k1, - Sha256, + sha256, Slip10, Slip10Curve, stringToPath, @@ -263,7 +263,7 @@ export class Secp256k1HdWallet implements OfflineSigner { if (signerAddress !== this.address) { throw new Error(`Address ${signerAddress} not found in wallet`); } - const message = new Sha256(serializeSignDoc(signDoc)).digest(); + const message = sha256(serializeSignDoc(signDoc)); const signature = await Secp256k1.createSignature(message, this.privkey); const signatureBytes = new Uint8Array([...signature.r(32), ...signature.s(32)]); return { diff --git a/packages/launchpad/src/sequence.ts b/packages/launchpad/src/sequence.ts index a11c1eb2..3ed14221 100644 --- a/packages/launchpad/src/sequence.ts +++ b/packages/launchpad/src/sequence.ts @@ -1,4 +1,4 @@ -import { Secp256k1, Secp256k1Signature, Sha256 } from "@cosmjs/crypto"; +import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; import { makeSignDoc, serializeSignDoc } from "./encoding"; import { decodeSignature } from "./signature"; @@ -33,7 +33,7 @@ export async function findSequenceForSignedTx( const signBytes = serializeSignDoc( makeSignDoc(tx.value.msg, tx.value.fee, chainId, tx.value.memo || "", accountNumber, s), ); - const prehashed = new Sha256(signBytes).digest(); + const prehashed = sha256(signBytes); const valid = await Secp256k1.verifySignature(secp256keSignature, prehashed, pubkey); if (valid) return s; } diff --git a/packages/proto-signing/src/directsecp256k1wallet.spec.ts b/packages/proto-signing/src/directsecp256k1wallet.spec.ts index 6f0fbcac..56eae17b 100644 --- a/packages/proto-signing/src/directsecp256k1wallet.spec.ts +++ b/packages/proto-signing/src/directsecp256k1wallet.spec.ts @@ -1,4 +1,4 @@ -import { Secp256k1, Secp256k1Signature, Sha256 } from "@cosmjs/crypto"; +import { Secp256k1, Secp256k1Signature, sha256 } from "@cosmjs/crypto"; import { fromBase64, fromHex, toAscii } from "@cosmjs/encoding"; import { DirectSecp256k1Wallet } from "./directsecp256k1wallet"; @@ -61,7 +61,7 @@ describe("DirectSecp256k1Wallet", () => { const signature = await wallet.sign(defaultAddress, message); const valid = await Secp256k1.verifySignature( Secp256k1Signature.fromFixedLength(fromBase64(signature.signature)), - new Sha256(message).digest(), + sha256(message), defaultPubkey, ); expect(valid).toEqual(true); diff --git a/packages/proto-signing/src/directsecp256k1wallet.ts b/packages/proto-signing/src/directsecp256k1wallet.ts index 921b25ec..4cca17dc 100644 --- a/packages/proto-signing/src/directsecp256k1wallet.ts +++ b/packages/proto-signing/src/directsecp256k1wallet.ts @@ -4,7 +4,7 @@ import { HdPath, Random, Secp256k1, - Sha256, + sha256, Slip10, Slip10Curve, } from "@cosmjs/crypto"; @@ -117,7 +117,7 @@ export class DirectSecp256k1Wallet { if (address !== this.address) { throw new Error(`Address ${address} not found in wallet`); } - const hashedMessage = new Sha256(message).digest(); + const hashedMessage = sha256(message); const signature = await Secp256k1.createSignature(hashedMessage, this.privkey); const signatureBytes = new Uint8Array([...signature.r(32), ...signature.s(32)]); return encodeSecp256k1Signature(this.pubkey, signatureBytes); From 0a1da22fb48675123e4d6b4d54063a03b5ffb0e4 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 13 Oct 2020 12:28:13 +0200 Subject: [PATCH 3/4] crypto: Add tests for convenience hash functions --- packages/crypto/src/keccak.spec.ts | 7 ++++++- packages/crypto/src/ripemd.spec.ts | 7 ++++++- packages/crypto/src/sha.spec.ts | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/crypto/src/keccak.spec.ts b/packages/crypto/src/keccak.spec.ts index ee1f20c7..5284063e 100644 --- a/packages/crypto/src/keccak.spec.ts +++ b/packages/crypto/src/keccak.spec.ts @@ -1,6 +1,6 @@ import { fromHex, toHex } from "@cosmjs/encoding"; -import { Keccak256 } from "./keccak"; +import { Keccak256, keccak256 } from "./keccak"; import keccakVectors from "./testdata/keccak.json"; describe("Keccak256", () => { @@ -25,4 +25,9 @@ describe("Keccak256", () => { expect(new Keccak256(fromHex(input)).digest()).toEqual(fromHex(output)); } }); + + it("exposes a convenience function", () => { + const { in: input, out: output } = keccakVectors.keccak256[0]; + expect(keccak256(fromHex(input))).toEqual(fromHex(output)); + }); }); diff --git a/packages/crypto/src/ripemd.spec.ts b/packages/crypto/src/ripemd.spec.ts index 234691c2..72fd2f8a 100644 --- a/packages/crypto/src/ripemd.spec.ts +++ b/packages/crypto/src/ripemd.spec.ts @@ -1,6 +1,6 @@ import { fromHex } from "@cosmjs/encoding"; -import { Ripemd160 } from "./ripemd"; +import { Ripemd160, ripemd160 } from "./ripemd"; import ripemdVectors from "./testdata/ripemd.json"; describe("Ripemd160", () => { @@ -25,4 +25,9 @@ describe("Ripemd160", () => { expect(new Ripemd160(fromHex(input)).digest()).toEqual(fromHex(output)); } }); + + it("exposes a convenience function", () => { + const { in: input, out: output } = ripemdVectors.ripemd160[0]; + expect(ripemd160(fromHex(input))).toEqual(fromHex(output)); + }); }); diff --git a/packages/crypto/src/sha.spec.ts b/packages/crypto/src/sha.spec.ts index 3549164b..311c2597 100644 --- a/packages/crypto/src/sha.spec.ts +++ b/packages/crypto/src/sha.spec.ts @@ -1,6 +1,6 @@ import { fromHex, toHex } from "@cosmjs/encoding"; -import { Sha256 } from "./sha"; +import { Sha256, sha256 } from "./sha"; import shaVectors from "./testdata/sha.json"; describe("Sha256", () => { @@ -25,4 +25,9 @@ describe("Sha256", () => { expect(new Sha256(fromHex(input)).digest()).toEqual(fromHex(output)); } }); + + it("exposes a convenience function", () => { + const { in: input, out: output } = shaVectors.sha256[0]; + expect(sha256(fromHex(input))).toEqual(fromHex(output)); + }); }); From 4944e736eeca87f34d144219481e7e7522f88c26 Mon Sep 17 00:00:00 2001 From: willclarktech Date: Tue, 13 Oct 2020 13:02:38 +0200 Subject: [PATCH 4/4] Update docs for convenience hash functions --- CHANGELOG.md | 5 +++++ packages/crypto/src/keccak.ts | 1 + packages/crypto/src/ripemd.ts | 1 + packages/crypto/src/sha.ts | 3 +++ packages/crypto/types/keccak.d.ts | 1 + packages/crypto/types/ripemd.d.ts | 1 + packages/crypto/types/sha.d.ts | 3 +++ 7 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29e6e3f8..7b4772c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 0.23.1 (unreleased) + +- @cosmjs/crypto: Export new convenience functions `keccak256`, `ripemd160`, + `sha1`, `sha256` and `sha512`. + ## 0.23.0 (2020-10-09) - @cosmjs/cli: Expose `HdPath` type. diff --git a/packages/crypto/src/keccak.ts b/packages/crypto/src/keccak.ts index a2f5c88e..ea4e7fc3 100644 --- a/packages/crypto/src/keccak.ts +++ b/packages/crypto/src/keccak.ts @@ -25,6 +25,7 @@ export class Keccak256 implements HashFunction { } } +/** Convenience function equivalent to `new Keccak256(data).digest()` */ export function keccak256(data: Uint8Array): Uint8Array { return new Keccak256(data).digest(); } diff --git a/packages/crypto/src/ripemd.ts b/packages/crypto/src/ripemd.ts index 08d819a3..258a43e0 100644 --- a/packages/crypto/src/ripemd.ts +++ b/packages/crypto/src/ripemd.ts @@ -23,6 +23,7 @@ export class Ripemd160 implements HashFunction { } } +/** Convenience function equivalent to `new Ripemd160(data).digest()` */ export function ripemd160(data: Uint8Array): Uint8Array { return new Ripemd160(data).digest(); } diff --git a/packages/crypto/src/sha.ts b/packages/crypto/src/sha.ts index 0380b23e..319633c3 100644 --- a/packages/crypto/src/sha.ts +++ b/packages/crypto/src/sha.ts @@ -26,6 +26,7 @@ export class Sha1 implements HashFunction { } } +/** Convenience function equivalent to `new Sha1(data).digest()` */ export function sha1(data: Uint8Array): Uint8Array { return new Sha1(data).digest(); } @@ -53,6 +54,7 @@ export class Sha256 implements HashFunction { } } +/** Convenience function equivalent to `new Sha256(data).digest()` */ export function sha256(data: Uint8Array): Uint8Array { return new Sha256(data).digest(); } @@ -80,6 +82,7 @@ export class Sha512 implements HashFunction { } } +/** Convenience function equivalent to `new Sha512(data).digest()` */ export function sha512(data: Uint8Array): Uint8Array { return new Sha512(data).digest(); } diff --git a/packages/crypto/types/keccak.d.ts b/packages/crypto/types/keccak.d.ts index 1aec50c8..a8538463 100644 --- a/packages/crypto/types/keccak.d.ts +++ b/packages/crypto/types/keccak.d.ts @@ -6,4 +6,5 @@ export declare class Keccak256 implements HashFunction { update(data: Uint8Array): Keccak256; digest(): Uint8Array; } +/** Convenience function equivalent to `new Keccak256(data).digest()` */ export declare function keccak256(data: Uint8Array): Uint8Array; diff --git a/packages/crypto/types/ripemd.d.ts b/packages/crypto/types/ripemd.d.ts index a2396ec8..8aa19510 100644 --- a/packages/crypto/types/ripemd.d.ts +++ b/packages/crypto/types/ripemd.d.ts @@ -6,4 +6,5 @@ export declare class Ripemd160 implements HashFunction { update(data: Uint8Array): Ripemd160; digest(): Uint8Array; } +/** Convenience function equivalent to `new Ripemd160(data).digest()` */ export declare function ripemd160(data: Uint8Array): Uint8Array; diff --git a/packages/crypto/types/sha.d.ts b/packages/crypto/types/sha.d.ts index 3aed0987..a8c73543 100644 --- a/packages/crypto/types/sha.d.ts +++ b/packages/crypto/types/sha.d.ts @@ -6,6 +6,7 @@ export declare class Sha1 implements HashFunction { update(data: Uint8Array): Sha1; digest(): Uint8Array; } +/** Convenience function equivalent to `new Sha1(data).digest()` */ export declare function sha1(data: Uint8Array): Uint8Array; export declare class Sha256 implements HashFunction { readonly blockSize: number; @@ -14,6 +15,7 @@ export declare class Sha256 implements HashFunction { update(data: Uint8Array): Sha256; digest(): Uint8Array; } +/** Convenience function equivalent to `new Sha256(data).digest()` */ export declare function sha256(data: Uint8Array): Uint8Array; export declare class Sha512 implements HashFunction { readonly blockSize: number; @@ -22,4 +24,5 @@ export declare class Sha512 implements HashFunction { update(data: Uint8Array): Sha512; digest(): Uint8Array; } +/** Convenience function equivalent to `new Sha512(data).digest()` */ export declare function sha512(data: Uint8Array): Uint8Array;