Skip to content

Commit

Permalink
fix: error handling for secp256k1.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
rodolfopietro97 committed Oct 27, 2023
1 parent 1105edc commit 1332416
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 33 deletions.
38 changes: 26 additions & 12 deletions packages/core/src/secp256k1/secp256k1.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { randomBytes } from 'crypto';
import {
ERRORS,
PRIVATE_KEY_MAX_VALUE,
SIGNATURE_LENGTH,
ZERO_BUFFER
} from '../utils';
import { PRIVATE_KEY_MAX_VALUE, SIGNATURE_LENGTH, ZERO_BUFFER } from '../utils';
import { ec as EC } from 'elliptic';
import { buildError, SECP256K1 } from '@vechain-sdk/errors';

// Cureve algorithm
const curve = new EC('secp256k1');
Expand Down Expand Up @@ -54,7 +50,10 @@ function generatePrivateKey(entropy?: () => Buffer): Buffer {
*/
function derivePublicKey(privateKey: Buffer): Buffer {
if (!isValidPrivateKey(privateKey)) {
throw new Error(ERRORS.SECP256K1.INVALID_PRIVATE_KEY);
throw buildError(
SECP256K1.INVALID_SECP256k1_PRIVATE_KEY,
'Invalid private key given as input. Length must be 32 bytes'
);
}
const keyPair = curve.keyFromPrivate(privateKey);
return Buffer.from(keyPair.getPublic().encode('array', false));
Expand All @@ -67,11 +66,17 @@ function derivePublicKey(privateKey: Buffer): Buffer {
*/
function sign(msgHash: Buffer, privKey: Buffer): Buffer {
if (!isValidMessageHash(msgHash)) {
throw new Error(ERRORS.SECP256K1.INVALID_MESSAGE_HASH);
throw buildError(
SECP256K1.INVALID_SECP256k1_MESSAGE_HASH,
'Invalid message hash given as input. Length must be 32 bytes'
);
}

if (!isValidPrivateKey(privKey)) {
throw new Error(ERRORS.SECP256K1.INVALID_PRIVATE_KEY);
throw buildError(
SECP256K1.INVALID_SECP256k1_PRIVATE_KEY,
'Invalid private key given as input. Length must be 32 bytes'
);
}

const keyPair = curve.keyFromPrivate(privKey);
Expand All @@ -90,14 +95,23 @@ function sign(msgHash: Buffer, privKey: Buffer): Buffer {
*/
function recover(msgHash: Buffer, sig: Buffer): Buffer {
if (!isValidMessageHash(msgHash)) {
throw new Error(ERRORS.SECP256K1.INVALID_MESSAGE_HASH);
throw buildError(
SECP256K1.INVALID_SECP256k1_MESSAGE_HASH,
'Invalid message hash given as input. Length must be 32 bytes'
);
}
if (!Buffer.isBuffer(sig) || sig.length !== SIGNATURE_LENGTH) {
throw new Error(ERRORS.SECP256K1.INVALID_SIGNATURE);
throw buildError(
SECP256K1.INVALID_SECP256k1_SIGNATURE,
'Invalid signature given as input. Length must be 65 bytes'
);
}
const recovery = sig[64];
if (recovery !== 0 && recovery !== 1) {
throw new Error(ERRORS.SECP256K1.INVALID_SIGNATURE_RECOVERY);
throw buildError(
SECP256K1.INVALID_SECP256k1_SIGNATURE_RECOVERY,
'Invalid signature recovery given as input. Signature bytes in position 64 must be 0 or 1'
);
}

const rCopy = Uint8Array.from(sig);
Expand Down
10 changes: 0 additions & 10 deletions packages/core/src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@
* @constant
*/
const ERRORS = {
/**
* Error messages related to Secp256k1 cryptographic operations.
*/
SECP256K1: {
INVALID_PRIVATE_KEY: 'Invalid private key',
INVALID_MESSAGE_HASH: 'Invalid message hash',
INVALID_SIGNATURE: 'Invalid signature',
INVALID_SIGNATURE_RECOVERY: 'Invalid signature recovery'
},

/**
* Error messages concerning operations with keystores.
*/
Expand Down
9 changes: 6 additions & 3 deletions packages/core/tests/address/address.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { describe, expect, test } from '@jest/globals';
import { ERRORS, address, secp256k1 } from '../../src';
import { address, secp256k1 } from '../../src';
import {
checksumedAndUnchecksumedAddresses,
invalidPrivateKey,
simpleAddress,
simplePrivateKey,
simplePublicKey
} from './fixture';
import { InvalidAddressError } from '@vechain-sdk/errors';
import {
InvalidAddressError,
InvalidSecp256k1PrivateKeyError
} from '@vechain-sdk/errors';

/**
* Test address module
Expand Down Expand Up @@ -51,7 +54,7 @@ describe('Address', () => {
// Invalid private key to derive public key
expect(() =>
secp256k1.derivePublicKey(invalidPrivateKey)
).toThrowError(ERRORS.SECP256K1.INVALID_PRIVATE_KEY);
).toThrowError(InvalidSecp256k1PrivateKeyError);
});
});

Expand Down
3 changes: 2 additions & 1 deletion packages/core/tests/keystore/keystore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { describe, test, expect } from '@jest/globals';
import { secp256k1, address, ERRORS, keystore } from '../../src';
import { type Keystore } from '../../src';
import { encryptionPassword } from './fixture';
import { InvalidSecp256k1PrivateKeyError } from '@vechain-sdk/errors';

/**
* Keystore tests
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('Keystore', () => {
Buffer.from('wrong private key', 'hex'),
encryptionPassword
)
).rejects.toThrowError(ERRORS.SECP256K1.INVALID_PRIVATE_KEY);
).rejects.toThrowError(InvalidSecp256k1PrivateKeyError);
});

/**
Expand Down
20 changes: 13 additions & 7 deletions packages/core/tests/secp256k1/secp256k1.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, test, expect } from '@jest/globals';
import { ERRORS, ZERO_BUFFER, secp256k1 } from '../../src';
import { ZERO_BUFFER, secp256k1 } from '../../src';
import {
invalidMessageHashes,
invalidPrivateKeys,
Expand All @@ -11,6 +11,12 @@ import {
validMessageHashes,
validPrivateKeys
} from './fixture';
import {
InvalidSecp256k1MessageHashError,
InvalidSecp256k1PrivateKeyError,
InvalidSecp256k1SignatureError,
InvalidSecp256k1SignatureRecoveryError
} from '@vechain-sdk/errors';

/**
* Secp256k1 tests
Expand Down Expand Up @@ -68,7 +74,7 @@ describe('Secp256k1', () => {

// Invalid private key
expect(() => secp256k1.derivePublicKey(ZERO_BUFFER(32))).toThrowError(
ERRORS.SECP256K1.INVALID_PRIVATE_KEY
InvalidSecp256k1PrivateKeyError
);
});

Expand All @@ -83,7 +89,7 @@ describe('Secp256k1', () => {
// Invalid message hash
expect(() =>
secp256k1.sign(Buffer.from('some_invalid_stuff', 'hex'), privateKey)
).toThrowError(ERRORS.SECP256K1.INVALID_MESSAGE_HASH);
).toThrowError(InvalidSecp256k1MessageHashError);

// Invalid private key
expect(() =>
Expand All @@ -94,7 +100,7 @@ describe('Secp256k1', () => {
'hex'
)
)
).toThrowError(ERRORS.SECP256K1.INVALID_PRIVATE_KEY);
).toThrowError(InvalidSecp256k1PrivateKeyError);
});

/**
Expand All @@ -111,15 +117,15 @@ describe('Secp256k1', () => {
Buffer.from('some_invalid_stuff', 'hex'),
signature
)
).toThrowError(ERRORS.SECP256K1.INVALID_MESSAGE_HASH);
).toThrowError(InvalidSecp256k1MessageHashError);

// Invalid signature
expect(() =>
secp256k1.recover(
messageHashBuffer,
Buffer.from('some_invalid_stuff', 'hex')
)
).toThrowError(ERRORS.SECP256K1.INVALID_SIGNATURE);
).toThrowError(InvalidSecp256k1SignatureError);

// Invalid signature recovery
const invalidSignatureRecovery = new Uint8Array(signature);
Expand All @@ -129,7 +135,7 @@ describe('Secp256k1', () => {
messageHashBuffer,
Buffer.from(invalidSignatureRecovery)
)
).toThrowError(ERRORS.SECP256K1.INVALID_SIGNATURE_RECOVERY);
).toThrowError(InvalidSecp256k1SignatureRecoveryError);
});

/**
Expand Down

0 comments on commit 1332416

Please sign in to comment.