@vechain/sdk-core
Advanced tools
Comparing version 1.0.0-beta.14 to 1.0.0-beta.15
{ | ||
"name": "@vechain/sdk-core", | ||
"version": "1.0.0-beta.14", | ||
"version": "1.0.0-beta.15", | ||
"description": "Includes modules for fundamental operations like hashing and cryptography", | ||
@@ -42,8 +42,8 @@ "author": "vechain Foundation", | ||
"@types/elliptic": "^6.4.18", | ||
"@vechain/sdk-errors": "1.0.0-beta.14", | ||
"@vechain/sdk-logging": "1.0.0-beta.14", | ||
"@vechain/sdk-errors": "1.0.0-beta.15", | ||
"@vechain/sdk-logging": "1.0.0-beta.15", | ||
"bignumber.js": "^9.1.2", | ||
"blakejs": "^1.2.1", | ||
"elliptic": "^6.5.5", | ||
"ethers": "6.12.1", | ||
"ethers": "6.13.0", | ||
"fast-json-stable-stringify": "^2.1.0", | ||
@@ -50,0 +50,0 @@ "@noble/ciphers": "^0.5.2" |
@@ -28,3 +28,3 @@ import { ADDRESS, assert } from '@vechain/sdk-errors'; | ||
*/ | ||
function fromPrivateKey(privateKey: Uint8Array): `0x${string}` { | ||
function fromPrivateKey(privateKey: Uint8Array): string { | ||
return fromPublicKey(secp256k1.derivePublicKey(privateKey)); | ||
@@ -57,3 +57,3 @@ } | ||
function fromPublicKey(publicKey: Uint8Array): `0x${string}` { | ||
function fromPublicKey(publicKey: Uint8Array): string { | ||
return toERC55Checksum( | ||
@@ -95,3 +95,3 @@ Hex0x.of( | ||
*/ | ||
function toERC55Checksum(address: string): `0x${string}` { | ||
function toERC55Checksum(address: string): string { | ||
assert( | ||
@@ -106,3 +106,3 @@ 'addressUtils.toERC55Checksum', | ||
const hash = Hex.of(keccak256(digits)); | ||
let result: `0x${string}` = '0x'; | ||
let result: string = '0x'; | ||
for (let i = 0; i < digits.length; i++) { | ||
@@ -109,0 +109,0 @@ if (parseInt(hash[i], 16) >= 8) { |
@@ -1,2 +0,1 @@ | ||
import * as utils from '@noble/curves/abstract/utils'; | ||
import fastJsonStableStringify from 'fast-json-stable-stringify'; | ||
@@ -7,2 +6,3 @@ import { Hex, Hex0x } from '../utils'; | ||
import { blake2b256 } from '../hash'; | ||
import { hexToBytes } from '@noble/curves/abstract/utils'; | ||
import { secp256k1 } from '../secp256k1'; | ||
@@ -37,3 +37,3 @@ import { type Certificate } from './types'; | ||
/** | ||
* Verifies the validity of a certificate. | ||
* Matches a certificate against a given address and signature. | ||
* | ||
@@ -47,5 +47,63 @@ * This method is insensitive to the case representation of the signer's address. | ||
* - {@link blake2b256}; | ||
* - {@link certificate.encode}; | ||
* - {@link secp256k1.recover}. | ||
* | ||
* @param {Uint8Array} cert - The certificate to match. computed from the certificate without the `signature` property. | ||
* @param {string} address - The address to match against, optionally prefixed with `0x`. | ||
* @param {string} signature - The signature to verify expressed in hexadecimal form, optionally prefixed with `0x`. | ||
* | ||
* @returns {void} - No return value. | ||
* | ||
* @throws CertificateInvalidSignatureFormatError - If the certificate signature's is not a valid hexadecimal expression prefixed with `0x`. | ||
* @throws CertificateNotSignedError - If the certificate is not signed. | ||
* @throws CertificateInvalidSignerError - If the certificate's signature's doesn't match with the signer;s public key. | ||
* | ||
*/ | ||
function match(cert: Uint8Array, address: string, signature: string): void { | ||
// Invalid hexadecimal as signature. | ||
assert( | ||
'certificate.match', | ||
Hex0x.isValid(signature, true, true), | ||
CERTIFICATE.CERTIFICATE_INVALID_SIGNATURE_FORMAT, | ||
'Verification failed: signature format is invalid.', | ||
{ signature } | ||
); | ||
try { | ||
// The `encode` method could throw `InvalidAddressError`. | ||
const signingHash = blake2b256(cert, 'buffer'); | ||
const signingPublicKey = secp256k1.recover( | ||
signingHash, | ||
hexToBytes(Hex.canon(signature)) | ||
); | ||
const signingAddress = addressUtils.fromPublicKey(signingPublicKey); | ||
// Signature does not match with the signer's public key. | ||
assert( | ||
'certificate.match', | ||
signingAddress.toLowerCase() === address.toLowerCase(), | ||
CERTIFICATE.CERTIFICATE_INVALID_SIGNER, | ||
"Verification failed: signature does not correspond to the signer's public key.", | ||
{ pubKey: signingPublicKey, cert } | ||
); | ||
} catch (e) { | ||
throw buildError( | ||
'certificate.match', | ||
CERTIFICATE.CERTIFICATE_INVALID_SIGNER, | ||
(e as Error).message, | ||
{ address, certificate: cert, signature }, | ||
e | ||
); | ||
} | ||
} | ||
/** | ||
* Verifies the validity of a certificate. | ||
* | ||
* This method is insensitive to the case representation of the signer's address. | ||
* | ||
* [EIP/ERC-55: Mixed-case checksum address encoding](https://eips.ethereum.org/EIPS/eip-55). | ||
* is supported. | ||
* | ||
* Secure audit function. | ||
* - {@link certificate.encode}; | ||
* - {@link match}. | ||
* | ||
* @param {Certificate} cert - The certificate to verify. | ||
@@ -60,3 +118,3 @@ * | ||
* @remark This methods {@link certificate.encode} the `cert` instance | ||
* to extract its signer 's address and compare it with the address derioved from the public key recovered from the | ||
* to extract its signer 's address and compare it with the address computed from the public key recovered from the | ||
* certificate using the | ||
@@ -67,2 +125,3 @@ * [BLAKE2](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2) | ||
* @see {encode} | ||
* @see {match} | ||
*/ | ||
@@ -86,20 +145,10 @@ function verify(cert: Certificate): void { | ||
); | ||
// Encode the certificate without the signature and get signing hash. | ||
try { | ||
// The `encode` method could throw `InvalidAddressError`. | ||
const encoded = encode({ ...cert, signature: undefined }); | ||
const signingHash = blake2b256(encoded); | ||
const pubKey = secp256k1.recover( | ||
signingHash, | ||
utils.hexToBytes(Hex.canon(cert.signature as string)) | ||
// Encode the certificate without the signature. | ||
const encoded = new TextEncoder().encode( | ||
certificate | ||
.encode({ ...cert, signature: undefined }) | ||
.normalize('NFC') | ||
); | ||
// Signature does not match with the signer's public key. | ||
assert( | ||
'certificate.verify', | ||
addressUtils.fromPublicKey(pubKey).toLowerCase() === | ||
cert.signer.toLowerCase(), | ||
CERTIFICATE.CERTIFICATE_INVALID_SIGNER, | ||
"Verification failed: signature does not correspond to the signer's public key.", | ||
{ pubKey, cert } | ||
); | ||
match(new Uint8Array(encoded), cert.signer, cert.signature as string); | ||
} catch (e) { | ||
@@ -119,2 +168,2 @@ throw buildError( | ||
*/ | ||
export const certificate = { encode, verify }; | ||
export const certificate = { encode, match, verify }; |
@@ -1,24 +0,18 @@ | ||
import { Hex0x } from '../utils'; | ||
import { Hex, Hex0x } from '../utils'; | ||
import { assertIsValidReturnType } from '../assertions'; | ||
import { blake2b } from '@noble/hashes/blake2b'; | ||
import { buildError, DATA } from '@vechain/sdk-errors'; | ||
import { hexToBytes, utf8ToBytes } from '@noble/hashes/utils'; | ||
import { type ReturnType } from './types'; | ||
/** | ||
* Internal function to calculates the BLAKE2B-256 hash of the input data. | ||
* The [normalization form for canonical composition](https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms). | ||
* | ||
* Secure audit function. | ||
* * [blake2b](https://github.com/paulmillr/noble-hashes?tab=readme-ov-file#blake2b-blake2s-blake3) | ||
* @constant {string} NORMALIZATION_FORM_CANONICAL_COMPOSITION | ||
* @description This constant represents the normalization form 'NFC'. It is used to specify the normalization form for converting strings to their canonical composition. | ||
* Canonical composition refers to the transformation of the input string to the composed form, where each character is represented by a single Unicode codepoint. | ||
* This normalization form is useful for comparing strings and ensuring consistency and interoperability. | ||
* | ||
* @param {Array<Uint8Array|string>} data - The input data to be hashed. | ||
* It accepts multiple arguments in the form of `Uint8Array` or strings. | ||
* | ||
* @returns {Uint8Array} - The BLAKE2B-256 hash of the input data. | ||
*/ | ||
function _blake2b256(...data: Array<Uint8Array | string>): Uint8Array { | ||
const ctx = blake2b.create({ dkLen: 32 }); | ||
data.forEach((datum) => { | ||
ctx.update(datum); | ||
}); | ||
return ctx.digest(); | ||
} | ||
const NORMALIZATION_FORM_CANONICAL_COMPOSITION = 'NFC'; | ||
@@ -28,9 +22,12 @@ /* --- Overloaded functions start --- */ | ||
/** | ||
* Calculates the Blake2b-256 hash value for the given data. | ||
* Computes the Blake2bB-256 hash of the given data. | ||
* If `data` is a string this is normalized using the {@link NORMALIZATION_FORM_CANONICAL_COMPOSITION} encoding. | ||
* | ||
* Secure audit function. | ||
* * {@link _blake2b256} | ||
* @param {string | Uint8Array} data - The data to compute the hash for. It can be either a string or a Uint8Array. | ||
* | ||
* @param {string | Uint8Array} data - The input data for which the hash needs to be computed. | ||
* @returns {Uint8Array} - The BLAKE2B-256 hash value computed for the given input data. | ||
* @return {Uint8Array} - The computed hash as a Uint8Array. | ||
* | ||
* @throws {InvalidDataReturnTypeError} - If the specified return type is invalid. | ||
* | ||
* @remark Use {@link blake2b256OfHex} to hash a string representing an array of bytes in hexadecimal form. | ||
*/ | ||
@@ -40,10 +37,12 @@ function blake2b256(data: string | Uint8Array): Uint8Array; | ||
/** | ||
* Calculates the BLAKE2b-256 hash of the given data. | ||
* Calculates the Blake2b-256 hash of the given data. | ||
* If `data` is a string this is normalized using the {@link NORMALIZATION_FORM_CANONICAL_COMPOSITION} encoding. | ||
* | ||
* Secure audit function. | ||
* * {@link _blake2b256} | ||
* @param {string | Uint8Array} data - The input data to be hashed. | ||
* | ||
* @param {string | Uint8Array} data - The input data to be hashed. Can be either a string or a Uint8Array. | ||
* @param {'buffer'} returnType - The desired return type. Currently only supports 'buffer'. | ||
* @returns {Uint8Array} - The BLAKE2b-256 hash as a Uint8Array. | ||
* @return {Uint8Array} - The Blake2b-256 hash of the given data as a Uint8Array. | ||
* | ||
* @throws {InvalidDataReturnTypeError} - If the specified return type is invalid. | ||
* | ||
* @remark Use {@link blake2b256OfHex} to hash a string representing an array of bytes in hexadecimal form. | ||
*/ | ||
@@ -56,11 +55,13 @@ function blake2b256( | ||
/** | ||
* Compute the BLAKE2b-256 hash of the given data. | ||
* Computes the blake2b-256 hash of the input data. | ||
* If `data` is a string this is normalized using the {@link NORMALIZATION_FORM_CANONICAL_COMPOSITION} encoding. | ||
* | ||
* Secure audit function. | ||
* * {@link _blake2b256} | ||
* @param {string | Uint8Array} data - The input data to be hashed. | ||
* @param {string} returnType - The return type of the hash. It can be 'hex'. | ||
* | ||
* @param {string | Uint8Array} data - The data to hash. | ||
* @param {string} returnType - The desired return type of the hash. Only "hex" is supported. | ||
* @return {Uint8Array} The blake2b-256 hash of the input data. | ||
* | ||
* @return {string} - The BLAKE2b-256 hash of the data in the specified return type. | ||
* @throws {InvalidDataReturnTypeError} - If the specified return type is invalid. | ||
* | ||
* @remark Use {@link blake2b256OfHex} to hash a string representing an array of bytes in hexadecimal form. | ||
*/ | ||
@@ -72,15 +73,19 @@ function blake2b256(data: string | Uint8Array, returnType: 'hex'): string; | ||
/** | ||
* Computes the BLAKE2b-256 hash of the given data. | ||
* Calculates the Blake2b-256 hash of the given input data. | ||
* If `data` is a string this is normalized using the {@link NORMALIZATION_FORM_CANONICAL_COMPOSITION} encoding. | ||
* | ||
* Secure audit function. | ||
* * {@link _blake2b256} | ||
* Calculates the BLAKE2b-256 hash of the provided data. | ||
* * {@link blake2b256OfArray} | ||
* * {@link blake2b256OfString} | ||
* | ||
* @param {string | Uint8Array} data - The data to be hashed. | ||
* @param {ReturnType} [returnType='buffer'] - The type of the return value. Valid options are 'buffer' (default) and 'hex'. | ||
* @param {string | Uint8Array} data - The input data to hash. | ||
* It can be either a string calling {@link blake2b256OfString}, | ||
* or a Uint8Array calling {@link blake2b256OfArray}. | ||
* @param {string} [returnType='buffer'] - The desired return type of the hash. It can be 'buffer' or 'hex'. | ||
* It is `buffer` by default. | ||
* @return {Uint8Array | string} - The hash value of the input data in the specified return type. | ||
* If `returnType` is `hex` it returns the hexadecimal expression of the hash prefixed with `0x`. | ||
* @throws {InvalidDataReturnTypeError} - If the specified return type is invalid. | ||
* | ||
* @returns {Uint8Array | string} - The computed hash value. | ||
* @param {string | Uint8Array} data - The data to be hashed. | ||
* @param {ReturnType} [returnType='buffer'] - The return type of the hash. 'buffer' returns a Buffer object, 'hex' returns a hexadecimal string. | ||
* @returns {Buffer | string} - The hash value calculated from the data. | ||
* @remark Use {@link blake2b256OfHex} to hash a string representing an array of bytes in hexadecimal form. | ||
*/ | ||
@@ -91,13 +96,74 @@ function blake2b256( | ||
): Uint8Array | string { | ||
// Assert that the returnType is valid | ||
assertIsValidReturnType('blake2b256', returnType); | ||
if (data instanceof Uint8Array) { | ||
const hash = blake2b256OfArray(data); | ||
return returnType === 'hex' ? Hex0x.of(hash) : hash; | ||
} else { | ||
const hash = blake2b256OfString(data); | ||
return returnType === 'hex' ? Hex0x.of(hash) : hash; | ||
} | ||
} | ||
// Converts the data to an array of Uint8Array or string | ||
const dataBytesLike = [data] as Array<Uint8Array | string>; | ||
/** | ||
* Calculates the BLAKE2b-256 hash value of an array. | ||
* | ||
* Secure audit function. | ||
* * [blake2b](https://github.com/paulmillr/noble-hashes?tab=readme-ov-file#blake2b-blake2s-blake3) | ||
* | ||
* @param {Uint8Array} array - The input array to calculate the hash value for. | ||
* @return {Uint8Array} The BLAKE2b-256 hash value of the input array. | ||
*/ | ||
function blake2b256OfArray(array: Uint8Array): Uint8Array { | ||
return blake2b.create({ dkLen: 32 }).update(array).digest(); | ||
} | ||
const hash = _blake2b256(...dataBytesLike); | ||
/** | ||
* | ||
* Calculate the Blake2b-256 hash of a hexadecimal string. | ||
* | ||
* Secure audit function. | ||
* * {@link blake2b256OfArray} | ||
* | ||
* @param {string} hex - The hexadecimal string to calculate the hash for, optionally prefixed with `0x`. | ||
* @param {string} returnType - The type of the return value. Must be either "buffer" or "hex", it's "buffer" by default. | ||
* @returns {string|Uint8Array} - The hash as either a hexadecimal string or Uint8Array, depending on the returnType parameter. | ||
* @throws {InvalidDataTypeError} - Throws an error if the conversion fails or the returnType is invalid. | ||
* @throws {InvalidDataReturnTypeError} - If the specified return type is invalid. | ||
*/ | ||
function blake2b256OfHex( | ||
hex: string, | ||
returnType: ReturnType = 'buffer' | ||
): string | Uint8Array { | ||
assertIsValidReturnType('blake2b256', returnType); | ||
try { | ||
const hash = blake2b256OfArray(hexToBytes(Hex.canon(hex))); | ||
return returnType === 'hex' ? Hex0x.of(hash) : hash; | ||
} catch (e) { | ||
throw buildError( | ||
'blake2b256OfHex', | ||
DATA.INVALID_DATA_TYPE, | ||
(e as Error).message, | ||
{ hex }, | ||
e | ||
); | ||
} | ||
} | ||
return returnType === 'buffer' ? hash : Hex0x.of(hash); | ||
/** | ||
* Calculates the BLAKE2b-256 hash of a given string. | ||
* The string is normalized using the {@link NORMALIZATION_FORM_CANONICAL_COMPOSITION} encoding. | ||
* | ||
* Secure audit function. | ||
* * {@link blake2b256OfArray} | ||
* * [utf8ToBytes](https://github.com/paulmillr/noble-hashes?tab=readme-ov-file#utils) | ||
* | ||
* @param {string} txt - The string to calculate the hash for. | ||
* @return {Uint8Array} - The BLAKE2b-256 hash as a Uint8Array. | ||
*/ | ||
function blake2b256OfString(txt: string): Uint8Array { | ||
return blake2b256OfArray( | ||
utf8ToBytes(txt.normalize(NORMALIZATION_FORM_CANONICAL_COMPOSITION)) | ||
); | ||
} | ||
export { blake2b256 }; | ||
export { blake2b256, blake2b256OfHex }; |
@@ -1,3 +0,1 @@ | ||
import { type BytesLike } from 'ethers'; | ||
/** | ||
@@ -4,0 +2,0 @@ * Input to hash function. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
979042
26174
+ Added@vechain/sdk-errors@1.0.0-beta.15(transitive)
+ Added@vechain/sdk-logging@1.0.0-beta.15(transitive)
+ Addedethers@6.13.0(transitive)
- Removed@vechain/sdk-errors@1.0.0-beta.14(transitive)
- Removed@vechain/sdk-logging@1.0.0-beta.14(transitive)
- Removedethers@6.12.1(transitive)
Updatedethers@6.13.0