Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const createHttpStakePoolMetadataService = (
const { data } = await axiosClient.get<Uint8Array>(url, { responseType: 'arraybuffer' });

// Produce metadata hash
const metadataHash = Crypto.blake2b(Crypto.blake2b.BYTES).update(data).digest('hex');
const metadataHash = Crypto.blake2b.hash(HexBlob.fromBytes(data), 32);

// Verify base hashes
if (metadataHash !== hash) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Cardano } from '@cardano-sdk/core';
import { DataMocks } from '../../data-mocks';
import { ExtMetadataFormat } from '../../../src/StakePool/types';
import { Hash32ByteBase16 } from '@cardano-sdk/crypto';
import { HexBlob } from '@cardano-sdk/util';
import { IncomingMessage } from 'http';
import {
StakePoolMetadataServiceError,
Expand Down Expand Up @@ -90,15 +91,13 @@ describe('StakePoolMetadataService', () => {

// Since the extended metadata URL will change each run and its part of the metadata, we must
// recalculate metadata the hash.
const metadataHash = Crypto.blake2b(Crypto.blake2b.BYTES)
.update(Buffer.from(JSON.stringify(metadata), 'ascii'))
.digest('hex');

const resultMetadata = await metadataService.getStakePoolMetadata(
metadataHash as Hash32ByteBase16,
`${serverUrl}/metadata`
const metadataHash = Crypto.blake2b.hash<Hash32ByteBase16>(
HexBlob.fromBytes(Buffer.from(JSON.stringify(metadata), 'ascii')),
32
);

const resultMetadata = await metadataService.getStakePoolMetadata(metadataHash, `${serverUrl}/metadata`);

expect(resultMetadata).toEqual(metadata);

const resultExtendedMetadata = await metadataService.getValidateStakePoolExtendedMetadata(
Expand Down Expand Up @@ -249,14 +248,9 @@ describe('StakePoolMetadataService', () => {
extVkey: INVALID_KEY
};

const metadataHash = Crypto.blake2b(Crypto.blake2b.BYTES)
.update(Buffer.from(JSON.stringify(metadata), 'ascii'))
.digest('hex');
const metadataHash = Crypto.blake2b.hash(HexBlob.fromBytes(Buffer.from(JSON.stringify(metadata), 'ascii')), 32);

const metadataResult = await metadataService.getStakePoolMetadata(
metadataHash as Hash32ByteBase16,
`${serverUrl}/metadata`
);
const metadataResult = await metadataService.getStakePoolMetadata(metadataHash, `${serverUrl}/metadata`);

const result2 = await metadataService.getValidateStakePoolExtendedMetadata(
metadataResult as Cardano.StakePoolMetadata
Expand Down
6 changes: 1 addition & 5 deletions packages/core/src/Cardano/types/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ export const AssetFingerprint = (value: string): AssetFingerprint => typedBech32
AssetFingerprint.fromParts = (policyId: PolicyId, assetName: AssetName): AssetFingerprint => {
const policyBuf = Buffer.from(policyId, 'hex');
const assetNameBuf = Buffer.from(assetName, 'hex');
const hexDigest = HexBlob(
Crypto.blake2b(20)
.update(new Uint8Array([...policyBuf, ...assetNameBuf]))
.digest('hex')
);
const hexDigest = Crypto.blake2b.hash(HexBlob.fromBytes(new Uint8Array([...policyBuf, ...assetNameBuf])), 20);

return AssetFingerprint(HexBlob.toTypedBech32<string>('asset', hexDigest));
};
9 changes: 1 addition & 8 deletions packages/core/src/Cardano/types/AuxiliaryData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as Crypto from '@cardano-sdk/crypto';
import * as Serialization from '../../Serialization/AuxiliaryData';
import { Hash32ByteBase16 } from '@cardano-sdk/crypto';
import { Script } from './Script';
import { hexToBytes } from '../../util/misc';

// eslint-disable-next-line no-use-before-define
export type MetadatumMap = Map<Metadatum, Metadatum>;
Expand All @@ -17,10 +16,4 @@ export interface AuxiliaryData {
}

export const computeAuxiliaryDataHash = (data: AuxiliaryData | undefined): Hash32ByteBase16 | undefined =>
data
? Hash32ByteBase16(
Crypto.blake2b(Crypto.blake2b.BYTES)
.update(hexToBytes(Serialization.AuxiliaryData.fromCore(data).toCbor()))
.digest('hex')
)
: undefined;
data ? Crypto.blake2b.hash<Hash32ByteBase16>(Serialization.AuxiliaryData.fromCore(data).toCbor(), 32) : undefined;
2 changes: 1 addition & 1 deletion packages/core/src/Cardano/types/StakePool/primitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const PoolId = (value: string): PoolId => typedBech32(value, 'pool', 45);
* @param {string} value blake2b_224 digest of an operator verification key hash
* @throws InvalidStringError
*/
PoolId.fromKeyHash = (value: Crypto.Ed25519KeyHashHex): PoolId => HexBlob.toTypedBech32('pool', HexBlob(value));
PoolId.fromKeyHash = (value: Crypto.Ed25519KeyHashHex): PoolId => HexBlob.toTypedBech32('pool', value);

/** /** pool operator verification key hash as hex string */
export type PoolIdHex = OpaqueString<'PoolIdHex'>;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/Cardano/types/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { RewardAccount } from '../Address';
import { Script } from './Script';

/** transaction hash as hex string */
export type TransactionId = OpaqueString<'TransactionId'>;
export type TransactionId = OpaqueString<'TransactionId'> & Crypto.Hash32ByteBase16;

/**
* @param {string} value transaction hash as hex string
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/Cardano/util/computeImplicitCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ const computeConwayDeposits = (
case Cardano.CertificateType.UnregisterDelegateRepresentative:
if (
!dRepKeyHash ||
(cert.dRepCredential.type === Address.CredentialType.KeyHash &&
cert.dRepCredential.hash === Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(dRepKeyHash))
(cert.dRepCredential.type === Address.CredentialType.KeyHash && cert.dRepCredential.hash === dRepKeyHash)
) {
cert.__typename === Cardano.CertificateType.RegisterDelegateRepresentative
? (deposit += cert.deposit)
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/Serialization/PlutusData/PlutusData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,7 @@ export class PlutusData {
* @returns the plutus data hash.
*/
hash(): Crypto.Hash32ByteBase16 {
const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(this.toCbor(), 'hex')).digest();

return Crypto.Hash32ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(this.toCbor(), HASH_LENGTH_IN_BYTES);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,9 @@ export class NativeScript {
hash(): Crypto.Hash28ByteBase16 {
// To compute a script hash, note that you must prepend a tag to the bytes of
// the script before hashing. The tags in the Babbage era for native scripts is "\x00"
const bytes = `00${this.toCbor()}`;
const bytes = `00${this.toCbor()}` as HexBlob;

const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(bytes, 'hex')).digest();

return Crypto.Hash28ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(bytes, HASH_LENGTH_IN_BYTES);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,9 @@ export class PlutusV1Script {
hash(): Crypto.Hash28ByteBase16 {
// To compute a script hash, note that you must prepend a tag to the bytes of
// the script before hashing. The tags in the Babbage era for PlutusV1 is "\x01"
const bytes = `01${this.rawBytes()}`;
const bytes = `01${this.rawBytes()}` as HexBlob;

const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(bytes, 'hex')).digest();

return Crypto.Hash28ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(bytes, HASH_LENGTH_IN_BYTES);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,9 @@ export class PlutusV2Script {
hash(): Crypto.Hash28ByteBase16 {
// To compute a script hash, note that you must prepend a tag to the bytes of
// the script before hashing. The tags in the Babbage era for PlutusV2 is "\x02"
const bytes = `02${this.rawBytes()}`;
const bytes = `02${this.rawBytes()}` as HexBlob;

const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(bytes, 'hex')).digest();

return Crypto.Hash28ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(bytes, HASH_LENGTH_IN_BYTES);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,9 @@ export class PlutusV3Script {
hash(): Crypto.Hash28ByteBase16 {
// To compute a script hash, note that you must prepend a tag to the bytes of
// the script before hashing. The tags in the Conway era for PlutusV3 is "\x03"
const bytes = `03${this.rawBytes()}`;
const bytes = `03${this.rawBytes()}` as HexBlob;

const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(bytes, 'hex')).digest();

return Crypto.Hash28ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(bytes, HASH_LENGTH_IN_BYTES);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/Serialization/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import type * as Cardano from '../Cardano';
const ALONZO_ERA_TX_FRAME_SIZE = 4;

/** Transaction serialized as CBOR, encoded as hex string */
export type TxCBOR = OpaqueString<'TxCbor'>;
export type TxCBOR = OpaqueString<'TxCbor'> & HexBlob;
/** Transaction body serialized as CBOR, encoded as hex string */
export type TxBodyCBOR = OpaqueString<'TxBodyCbor' & HexBlob['__opaqueString']>;
export type TxBodyCBOR = OpaqueString<'TxBodyCbor'> & HexBlob;

/**
* A transaction is a record of value transfer between two or more addresses on the network. It represents a request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -933,8 +933,7 @@ export class TransactionBody {
* @returns The hash of the transaction body.
*/
hash() {
const hash = Crypto.blake2b(Crypto.blake2b.BYTES).update(hexToBytes(this.toCbor())).digest();
return TransactionId.fromHexBlob(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash<TransactionId>(this.toCbor(), 32);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,6 @@ export class Redeemer {
* @returns the redeemer hash.
*/
hash(): Crypto.Hash32ByteBase16 {
const hash = Crypto.blake2b(HASH_LENGTH_IN_BYTES).update(Buffer.from(this.toCbor(), 'hex')).digest();

return Crypto.Hash32ByteBase16(HexBlob.fromBytes(hash));
return Crypto.blake2b.hash(this.toCbor(), HASH_LENGTH_IN_BYTES);
}
}
4 changes: 2 additions & 2 deletions packages/core/test/Cardano/util/computeImplicitCoin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ describe('Cardano.util.computeImplicitCoin', () => {
__typename: Cardano.CertificateType.RegisterDelegateRepresentative,
anchor: null,
dRepCredential: {
hash: Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(dRepKeyHash),
hash: dRepKeyHash,
type: Cardano.CredentialType.KeyHash
} as Cardano.Credential,
deposit: drepDeposit
},
{
__typename: Cardano.CertificateType.UnregisterDelegateRepresentative,
dRepCredential: {
hash: Crypto.Hash28ByteBase16.fromEd25519KeyHashHex(dRepKeyHash),
hash: dRepKeyHash,
type: Cardano.CredentialType.KeyHash
} as Cardano.Credential,
deposit: drepDeposit
Expand Down
9 changes: 7 additions & 2 deletions packages/crypto/src/Bip32/Bip32PublicKey.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as Bip32KeyDerivation from './Bip32KeyDerivation';
import { BIP32_PUBLIC_KEY_HASH_LENGTH, Bip32PublicKeyHashHex, Bip32PublicKeyHex } from '../hexTypes';
import { ED25519_PUBLIC_KEY_LENGTH, Ed25519PublicKey } from '../Ed25519e';
import {
BIP32_PUBLIC_KEY_HASH_LENGTH,
Bip32PublicKeyHashHex,
Bip32PublicKeyHex,
ED25519_PUBLIC_KEY_LENGTH
} from '../hexTypes';
import { Ed25519PublicKey } from '../Ed25519e';
import { InvalidArgumentError } from '@cardano-sdk/util';
import sodium from 'libsodium-wrappers-sumo';

Expand Down
4 changes: 1 addition & 3 deletions packages/crypto/src/Ed25519e/Ed25519PublicKey.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { ED25519_PUBLIC_KEY_HASH_LENGTH, Ed25519KeyHash } from './Ed25519KeyHash';
import { Ed25519PublicKeyHex } from '../hexTypes';
import { ED25519_PUBLIC_KEY_LENGTH, Ed25519PublicKeyHex } from '../hexTypes';
import { Ed25519Signature } from './Ed25519Signature';
import { HexBlob, InvalidArgumentError } from '@cardano-sdk/util';
import sodium from 'libsodium-wrappers-sumo';

export const ED25519_PUBLIC_KEY_LENGTH = 32;

/**
* Ed25519 raw public key. This key can be used for cryptographically verifying messages
* previously signed with the matching Ed25519 raw private key.
Expand Down
31 changes: 31 additions & 0 deletions packages/crypto/src/blake2b-hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { HexBlob, hexStringToBuffer } from '@cardano-sdk/util';
import hash from 'blake2b';
import type { Hash28ByteBase16, Hash32ByteBase16 } from './hexTypes';

export interface Blake2b {
/**
* blake2b-256
*
* @param message payload to hash
* @param outputLengthBytes digest size, e.g. 28 for blake2b-224 or 32 for blake2b-256
*/
hash<T extends Hash32ByteBase16>(message: HexBlob, outputLengthBytes: 32): T;
/**
* blake2b-224
*
* @param message payload to hash
* @param outputLengthBytes digest size, e.g. 28 for blake2b-224 or 32 for blake2b-256
*/
hash<T extends Hash28ByteBase16>(message: HexBlob, outputLengthBytes: 28): T;
/**
* @param message payload to hash
* @param outputLengthBytes digest size, e.g. 28 for blake2b-224 or 32 for blake2b-256
*/
hash<T extends HexBlob>(message: HexBlob, outputLengthBytes: number): T;
}

export const blake2b: Blake2b = {
hash<T extends HexBlob>(message: HexBlob, outputLengthBytes: number) {
return hash(outputLengthBytes).update(hexStringToBuffer(message)).digest('hex') as T;
}
};
62 changes: 31 additions & 31 deletions packages/crypto/src/hexTypes.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@
import { HexBlob, OpaqueString, castHexBlob, typedHex } from '@cardano-sdk/util';

export const BIP32_PUBLIC_KEY_HASH_LENGTH = 28;
export const ED25519_PUBLIC_KEY_LENGTH = 32;

/** 28 byte hash as hex string */
export type Hash28ByteBase16 = OpaqueString<'Hash28ByteBase16'> & HexBlob;
/**
* @param {string} value 28 byte hash as hex string
* @throws InvalidStringError
*/
export const Hash28ByteBase16 = (value: string): Hash28ByteBase16 => typedHex<Hash28ByteBase16>(value, 56);

/** 32 byte hash as hex string */
export type Hash32ByteBase16 = OpaqueString<'Hash32ByteBase16'> & HexBlob;
/**
* @param {string} value 32 byte hash as hex string
* @throws InvalidStringError
*/
export const Hash32ByteBase16 = (value: string): Hash32ByteBase16 => typedHex<Hash32ByteBase16>(value, 64);
Hash32ByteBase16.fromHexBlob = <T>(value: HexBlob) => castHexBlob<T>(value, 64);

/** Ed25519 signature as hex string */
export type Ed25519SignatureHex = OpaqueString<'Ed25519SignatureHex'>;
export type Ed25519SignatureHex = OpaqueString<'Ed25519SignatureHex'> & HexBlob;
export const Ed25519SignatureHex = (value: string): Ed25519SignatureHex => typedHex(value, 128);

/** BIP32 public key as hex string */
export type Bip32PublicKeyHex = OpaqueString<'Bip32PublicKeyHex'>;
export type Bip32PublicKeyHex = OpaqueString<'Bip32PublicKeyHex'> & HexBlob;
export const Bip32PublicKeyHex = (key: string): Bip32PublicKeyHex => typedHex(key, 128);

/** BIP32 private key as hex string */
export type Bip32PrivateKeyHex = OpaqueString<'Bip32PrivateKeyHex'>;
export type Bip32PrivateKeyHex = OpaqueString<'Bip32PrivateKeyHex'> & HexBlob;
export const Bip32PrivateKeyHex = (key: string): Bip32PrivateKeyHex => typedHex(key, 192);

/** Ed25519 public key as hex string */
export type Ed25519PublicKeyHex = OpaqueString<'Ed25519PublicKeyHex'>;
export const Ed25519PublicKeyHex = (value: string): Ed25519PublicKeyHex => typedHex(value, 64);
export type Ed25519PublicKeyHex = OpaqueString<'Ed25519PublicKeyHex'> & HexBlob;
export const Ed25519PublicKeyHex = (value: string): Ed25519PublicKeyHex =>
typedHex(value, ED25519_PUBLIC_KEY_LENGTH * HexBlob.CHARS_PER_BYTE);
Ed25519PublicKeyHex.fromBip32PublicKey = (bip32PublicKey: Bip32PublicKeyHex): Ed25519PublicKeyHex =>
bip32PublicKey.slice(0, ED25519_PUBLIC_KEY_LENGTH * HexBlob.CHARS_PER_BYTE) as Ed25519PublicKeyHex;

/** Ed25519 private extended key as hex string */
export type Ed25519PrivateExtendedKeyHex = OpaqueString<'Ed25519PrivateKeyHex'>;
export type Ed25519PrivateExtendedKeyHex = OpaqueString<'Ed25519PrivateKeyHex'> & HexBlob;
export const Ed25519PrivateExtendedKeyHex = (value: string): Ed25519PrivateExtendedKeyHex => typedHex(value, 128);

/** Ed25519 private normal key as hex string */
export type Ed25519PrivateNormalKeyHex = OpaqueString<'Ed25519PrivateKeyHex'>;
export type Ed25519PrivateNormalKeyHex = OpaqueString<'Ed25519PrivateKeyHex'> & HexBlob;
export const Ed25519PrivateNormalKeyHex = (value: string): Ed25519PrivateNormalKeyHex => typedHex(value, 64);

/** 28 byte ED25519 key hash as hex string */
export type Ed25519KeyHashHex = OpaqueString<'Ed25519KeyHashHex'>;
export type Ed25519KeyHashHex = OpaqueString<'Ed25519KeyHashHex'> & Hash28ByteBase16 & HexBlob;
export const Ed25519KeyHashHex = (value: string): Ed25519KeyHashHex => typedHex(value, 56);

/** 28 byte BIP32 public key hash as hex string */
export type Bip32PublicKeyHashHex = OpaqueString<'Bip32PublicKeyHashHex'>;
export type Bip32PublicKeyHashHex = OpaqueString<'Bip32PublicKeyHashHex'> & HexBlob;
export const Bip32PublicKeyHashHex = (value: string): Bip32PublicKeyHashHex =>
typedHex(value, BIP32_PUBLIC_KEY_HASH_LENGTH * 2);

/** 32 byte hash as hex string */
export type Hash32ByteBase16 = OpaqueString<'Hash32ByteBase16'>;

/**
* @param {string} value 32 byte hash as hex string
* @throws InvalidStringError
*/
export const Hash32ByteBase16 = (value: string): Hash32ByteBase16 => typedHex<Hash32ByteBase16>(value, 64);
Hash32ByteBase16.fromHexBlob = <T>(value: HexBlob) => castHexBlob<T>(value, 64);

/** 28 byte hash as hex string */
export type Hash28ByteBase16 = OpaqueString<'Hash28ByteBase16'>;

/**
* @param {string} value 28 byte hash as hex string
* @throws InvalidStringError
*/
export const Hash28ByteBase16 = (value: string): Hash28ByteBase16 => typedHex<Hash28ByteBase16>(value, 56);
/** Ed25519KeyHashHex is a 28 byte hash. This is a utility function that downcasts without validation. */
Hash28ByteBase16.fromEd25519KeyHashHex = (value: Ed25519KeyHashHex) => value as unknown as Hash28ByteBase16;
typedHex(value, BIP32_PUBLIC_KEY_HASH_LENGTH * HexBlob.CHARS_PER_BYTE);
3 changes: 1 addition & 2 deletions packages/crypto/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import blake2b from 'blake2b';
import sodium from 'libsodium-wrappers-sumo';
export { blake2b };

export * from './blake2b-hash';
export * from './Bip32';
export * from './Bip32Ed25519';
export * from './Ed25519e';
Expand Down
Loading
Loading