Skip to content

Commit

Permalink
fix: using specification algorithm for ECDSA signatures (IEEE-P1363 f…
Browse files Browse the repository at this point in the history
…ormat)
  • Loading branch information
AlexanderTar committed Jan 12, 2024
1 parent f52b0ee commit a1fb91c
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 19 deletions.
21 changes: 17 additions & 4 deletions src/algorithm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
VerifyPublicKeyInput,
sign,
verify,
KeyObject,
} from 'crypto';
import { RSA_PKCS1_PADDING, RSA_PKCS1_PSS_PADDING } from 'constants';
import { SigningKey, Algorithm, Verifier } from '../types';
Expand Down Expand Up @@ -50,10 +51,16 @@ export function createSigner(key: BinaryLike | KeyLike | SignKeyObjectInput | Si
} as SignPrivateKeyInput);
break;
case 'ecdsa-p256-sha256':
signer.sign = async (data: Buffer) => createSign('sha256').update(data).sign(key as KeyLike);
signer.sign = async (data: Buffer) => createSign('sha256').update(data).sign({
key: key as KeyObject,
dsaEncoding: 'ieee-p1363',
});
break;
case 'ecdsa-p384-sha384':
signer.sign = async (data: Buffer) => createSign('sha384').update(data).sign(key as KeyLike);
signer.sign = async (data: Buffer) => createSign('sha384').update(data).sign({
key: key as KeyObject,
dsaEncoding: 'ieee-p1363',
});
break;
case 'ed25519':
signer.sign = async (data: Buffer) => sign(null, data, key as KeyLike);
Expand Down Expand Up @@ -108,10 +115,16 @@ export function createVerifier(key: BinaryLike | KeyLike | VerifyKeyObjectInput
} as VerifyPublicKeyInput, signature);
break;
case 'ecdsa-p256-sha256':
verifier = async (data: Buffer, signature: Buffer) => createVerify('sha256').update(data).verify(key as KeyLike, signature);
verifier = async (data: Buffer, signature: Buffer) => createVerify('sha256').update(data).verify({
key: key as KeyObject,
dsaEncoding: 'ieee-p1363',
}, signature);
break;
case 'ecdsa-p384-sha384':
verifier = async (data: Buffer, signature: Buffer) => createVerify('sha384').update(data).verify(key as KeyLike, signature);
verifier = async (data: Buffer, signature: Buffer) => createVerify('sha384').update(data).verify({
key: key as KeyObject,
dsaEncoding: 'ieee-p1363',
}, signature);
break;
case 'ed25519':
verifier = async (data: Buffer, signature: Buffer) => verify(null, data, key as KeyLike, signature) as unknown as boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type Signer = (data: Buffer) => Promise<Buffer>;
export type Verifier = (data: Buffer, signature: Buffer, parameters?: SignatureParameters) => Promise<boolean | null>;
export type VerifierFinder = (parameters: SignatureParameters) => Promise<VerifyingKey | null>;

export type Algorithm = 'rsa-v1_5-sha256' | 'ecdsa-p256-sha256' | 'hmac-sha256' | 'rsa-pss-sha512' | string;
export type Algorithm = 'rsa-v1_5-sha256' | 'ecdsa-p256-sha256' | 'ecdsa-p384-sha384' | 'ed25519' | 'hmac-sha256' | 'rsa-pss-sha512' | string;

export interface SigningKey {
/**
Expand Down
19 changes: 13 additions & 6 deletions test/algorithm/ecdsa-p256-sha256.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,20 @@ describe('ecdsa-p256-sha256', () => {
const data = Buffer.from('some random data');
const sig = await signer.sign(data);
expect(signer.alg).to.equal('ecdsa-p256-sha256');
expect(sig).to.satisfy((arg: Buffer) => verify('sha256', data, ecdsaKeyPair.publicKey, arg));
expect(sig).to.satisfy((arg: Buffer) => verify('sha256', data, {
key: ecdsaKeyPair.publicKey,
dsaEncoding: 'ieee-p1363',
}, arg));
});
});
describe('verifying', () => {
it('verifies a signature', async () => {
const verifier = createVerifier(ecdsaKeyPair.publicKey, 'ecdsa-p256-sha256');
const data = Buffer.from('some random data');
const sig = sign('sha256', data, ecdsaKeyPair.privateKey);
const sig = sign('sha256', data, {
key: ecdsaKeyPair.privateKey,
dsaEncoding: 'ieee-p1363',
});
expect(sig).to.satisfy((arg: Buffer) => verifier(data, arg));
});
});
Expand All @@ -52,11 +58,12 @@ describe('ecdsa-p256-sha256', () => {
'"@signature-params": ("@status" "content-type" "content-digest" "content-length");created=1618884473;keyid="test-key-ecc-p256"');
it('successfully signs a payload', async () => {
const sig = await (createSigner(ecKeyPem, 'ecdsa-p256-sha256').sign(data));
expect(sig).to.satisfy((arg: Buffer) => verify('sha256', data, ecKeyPem, arg));
expect(sig).to.satisfy((arg: Buffer) => verify('sha256', data, {
key: ecKeyPem,
dsaEncoding: 'ieee-p1363',
}, arg));
});
// seems to be broken in node - Error: error:0D07207B:asn1 encoding routines:ASN1_get_object:header too long
// could be to do with https://stackoverflow.com/a/39575576
it.skip('successfully verifies a signature', async () => {
it('successfully verifies a signature', async () => {
const sig = Buffer.from('wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NKocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==', 'base64');
expect(await (createVerifier(ecKeyPem, 'ecdsa-p256-sha256')(data, sig))).to.equal(true);
});
Expand Down
10 changes: 8 additions & 2 deletions test/algorithm/ecdsa-p384-sha384.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,20 @@ describe('ecdsa-p384-sha384', () => {
const data = Buffer.from('some random data');
const sig = await signer.sign(data);
expect(signer.alg).to.equal('ecdsa-p384-sha384');
expect(sig).to.satisfy((arg: Buffer) => verify('sha384', data, ecdsaKeyPair.publicKey, arg));
expect(sig).to.satisfy((arg: Buffer) => verify('sha384', data, {
key: ecdsaKeyPair.publicKey,
dsaEncoding: 'ieee-p1363',
}, arg));
});
});
describe('verifying', () => {
it('verifies a signature', async () => {
const verifier = createVerifier(ecdsaKeyPair.publicKey, 'ecdsa-p384-sha384');
const data = Buffer.from('some random data');
const sig = sign('sha384', data, ecdsaKeyPair.privateKey);
const sig = sign('sha384', data, {
key: ecdsaKeyPair.privateKey,
dsaEncoding: 'ieee-p1363',
});
expect(sig).to.satisfy((arg: Buffer) => verifier(data, arg));
});
});
Expand Down
11 changes: 5 additions & 6 deletions test/httpbis/httpbis.int.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ describe('httpbis', () => {
res.setHeader('Content-Digest', 'sha-512=:mEWXIS7MaLRuGgxOBdODa3xqM1XdEvxoYhvlCFJ41QJgJc4GTsPp29l5oGX69wWdXymyU0rjJuahq4l5aGgfLQ==:');
res.setHeader('Content-Length', '23');
res.setHeader('Signature-Input', 'sig-b24=("@status" "content-type" "content-digest" "content-length");created=1618884473;keyid="test-key-ecc-p256"');
res.setHeader('Signature', 'sig-b24=:MEYCIQDXrmWrcxKWLQQm0zlwbFr5/KAlB9oHkfMpNRVCuGVHjQIhAKtljVKRuRoWv5dCKuc+GgP3eqLAq+Eg0d3olyR67BYK:');
res.setHeader('Signature', 'sig-b24=:wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NKocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==:');
res.end('{"message": "good dog"}');
});
return server.start();
Expand Down Expand Up @@ -335,8 +335,7 @@ describe('httpbis', () => {
});
});
describe('ecdsa-p256-sha256', () => {
// There seems to be a problem in node in verifying ecdsa signatures from external sources
it.skip('verifies a response', async () => {
it('verifies a response', async () => {
const response = await makeHttpRequest({
method: 'POST',
url: 'http://example.com/foo?param=Value&Pet=dog',
Expand Down Expand Up @@ -455,7 +454,7 @@ describe('httpbis', () => {
'content-digest': 'sha-512=:mEWXIS7MaLRuGgxOBdODa3xqM1XdEvxoYhvlCFJ41QJgJc4GTsPp29l5oGX69wWdXymyU0rjJuahq4l5aGgfLQ==:',
'content-length': '23',
'signature-input': 'sig-b24=("@status" "content-type" "content-digest" "content-length");created=1618884473;keyid="test-key-ecc-p256"',
'signature': 'sig-b24=:MEYCIQDXrmWrcxKWLQQm0zlwbFr5/KAlB9oHkfMpNRVCuGVHjQIhAKtljVKRuRoWv5dCKuc+GgP3eqLAq+Eg0d3olyR67BYK:',
'signature': 'sig-b24=:wNmSUAhwb5LxtOtOpNa6W5xj067m5hFrj0XQ4fvpaCLx0NKocgPquLgyahnzDnDAUy5eCdlYUEkLIj+32oiasw==:',
});
stream.end('{"message": "good dog"}');
stream.close();
Expand Down Expand Up @@ -610,8 +609,7 @@ describe('httpbis', () => {
});
});
describe('ecdsa-p256-sha256', () => {
// There seems to be a problem in node in verifying ecdsa signatures from external sources
it.skip('verifies a response', async () => {
it('verifies a response', async () => {
const response = await makeHttp2Request({
method: 'POST',
url: 'http://example.com/foo?param=Value&Pet=dog',
Expand All @@ -634,6 +632,7 @@ describe('httpbis', () => {
}
return null;
});
console.log(response.headers);
const valid = await httpbis.verifyMessage({
keyLookup,
}, {
Expand Down

0 comments on commit a1fb91c

Please sign in to comment.