Skip to content

Commit

Permalink
Mark Ed25519 and Secp256k1 key validation methods public
Browse files Browse the repository at this point in the history
Signed-off-by: Frank Hinek <[email protected]>
  • Loading branch information
frankhinek committed Jan 4, 2024
1 parent 8158687 commit bb70273
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 114 deletions.
76 changes: 38 additions & 38 deletions packages/crypto/src/primitives/ed25519.ts
Original file line number Diff line number Diff line change
Expand Up @@ -467,43 +467,6 @@ export class Ed25519 {
return signature;
}

/**
* Verifies an RFC8032-compliant EdDSA signature against given data using an Ed25519 public key.
*
* @remarks
* This method validates a digital signature to ensure its authenticity and integrity.
* It uses the EdDSA (Edwards-curve Digital Signature Algorithm) as specified in RFC8032.
* The verification process involves converting the public key from JWK format to a raw
* byte array and using the Ed25519 algorithm to validate the signature against the provided data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // A Jwk object representing an Ed25519 public key
* const signature = new Uint8Array([...]); // Signature to verify
* const isValid = await Ed25519.verify({ key: publicKey, signature, data });
* console.log(isValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key in JWK format used for verification.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
public static async verify({ key, signature, data }:
VerifyParams
): Promise<boolean> {
// Convert the public key from JWK format to bytes.
const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey: key });

// Perform the verification of the signature.
const isValid = ed25519.verify(signature, data, publicKeyBytes);

return isValid;
}

/**
* Validates a given public key to confirm its mathematical correctness on the Edwards curve.
*
Expand All @@ -529,7 +492,7 @@ export class Ed25519 {
* @returns A Promise that resolves to a boolean indicating whether the key
* corresponds to a valid point on the Edwards curve.
*/
private static validatePublicKey({ publicKey }: {
public static validatePublicKey({ publicKey }: {
publicKey: Uint8Array;
}): boolean {
try {
Expand All @@ -545,4 +508,41 @@ export class Ed25519 {

return true;
}

/**
* Verifies an RFC8032-compliant EdDSA signature against given data using an Ed25519 public key.
*
* @remarks
* This method validates a digital signature to ensure its authenticity and integrity.
* It uses the EdDSA (Edwards-curve Digital Signature Algorithm) as specified in RFC8032.
* The verification process involves converting the public key from JWK format to a raw
* byte array and using the Ed25519 algorithm to validate the signature against the provided data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // A Jwk object representing an Ed25519 public key
* const signature = new Uint8Array([...]); // Signature to verify
* const isValid = await Ed25519.verify({ key: publicKey, signature, data });
* console.log(isValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key in JWK format used for verification.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
public static async verify({ key, signature, data }:
VerifyParams
): Promise<boolean> {
// Convert the public key from JWK format to bytes.
const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey: key });

// Perform the verification of the signature.
const isValid = ed25519.verify(signature, data, publicKeyBytes);

return isValid;
}
}
146 changes: 73 additions & 73 deletions packages/crypto/src/primitives/secp256k1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,79 @@ export class Secp256k1 {
return signature;
}

/**
* Validates a given private key to ensure its compliance with the secp256k1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256k1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256k1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
public static async validatePrivateKey({ privateKeyBytes }: {
privateKeyBytes: Uint8Array;
}): Promise<boolean> {
return secp256k1.utils.isValidPrivateKey(privateKeyBytes);
}

/**
* Validates a given public key to confirm its mathematical correctness on the secp256k1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256k1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256k1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256k1 curve.
*/
public static async validatePublicKey({ publicKeyBytes }: {
publicKeyBytes: Uint8Array;
}): Promise<boolean> {
try {
// Decode Weierstrass points from key bytes.
const point = secp256k1.ProjectivePoint.fromHex(publicKeyBytes);

// Check if points are on the Short Weierstrass curve.
point.assertValidity();

} catch(error: any) {
return false;
}

return true;
}

/**
* Verifies an RFC6979-compliant ECDSA signature against given data and a secp256k1 public key.
*
Expand Down Expand Up @@ -700,77 +773,4 @@ export class Secp256k1 {

return { x, y };
}

/**
* Validates a given private key to ensure its compliance with the secp256k1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256k1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256k1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
private static async validatePrivateKey({ privateKeyBytes }: {
privateKeyBytes: Uint8Array;
}): Promise<boolean> {
return secp256k1.utils.isValidPrivateKey(privateKeyBytes);
}

/**
* Validates a given public key to confirm its mathematical correctness on the secp256k1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256k1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256k1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256k1 curve.
*/
private static async validatePublicKey({ publicKeyBytes }: {
publicKeyBytes: Uint8Array;
}): Promise<boolean> {
try {
// Decode Weierstrass points from key bytes.
const point = secp256k1.ProjectivePoint.fromHex(publicKeyBytes);

// Check if points are on the Short Weierstrass curve.
point.assertValidity();

} catch(error: any) {
return false;
}

return true;
}
}
1 change: 0 additions & 1 deletion packages/crypto/tests/primitives/ed25519.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ describe('Ed25519', () => {
describe('validatePublicKey()', () => {
it('returns true for valid public keys', async () => {
const publicKey = Convert.hex('a12c2beb77265f2aac953b5009349d94155a03ada416aad451319480e983ca4c').toUint8Array();
// @ts-expect-error because validatePublicKey() is a private method.
const isValid = await Ed25519.validatePublicKey({ publicKey });
expect(isValid).to.be.true;
});
Expand Down
2 changes: 0 additions & 2 deletions packages/crypto/tests/primitives/secp256k1.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,6 @@ describe('Secp256k1', () => {
for (const vector of secp256k1ValidatePrivateKey.vectors) {
it(vector.description, async () => {
const privateKeyBytes = Convert.hex(vector.input.privateKeyBytes).toUint8Array();
// @ts-expect-error because validatePrivateKey() is a private method.
const isValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
expect(isValid).to.equal(vector.output);
});
Expand All @@ -524,7 +523,6 @@ describe('Secp256k1', () => {
for (const vector of secp256k1ValidatePublicKey.vectors) {
it(vector.description, async () => {
const publicKeyBytes = Convert.hex(vector.input.publicKeyBytes).toUint8Array();
// @ts-expect-error because validatePublicKey() is a private method.
const isValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
expect(isValid).to.equal(vector.output);
});
Expand Down

0 comments on commit bb70273

Please sign in to comment.