Skip to content

Commit

Permalink
Add assertions lib & test multiple keyTypes.
Browse files Browse the repository at this point in the history
  • Loading branch information
aljones15 committed Jul 5, 2024
1 parent 533c8fb commit 51db63f
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 94 deletions.
57 changes: 16 additions & 41 deletions test/EcdsaMultikey.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
import * as base58 from 'base58-universal';
import * as EcdsaMultikey from '../lib/index.js';
import chai from 'chai';
import {CryptoKey, webcrypto} from '../lib/crypto.js';
import {webcrypto} from '../lib/crypto.js';
import {getNamedCurveFromPublicMultikey} from '../lib/helpers.js';
import {exportKeyPair} from '../lib/serialize.js';
import {
mockKey,
mockKeyEcdsaSecp256,
mockKeyEcdsaSecp384,
mockKeyEcdsaSecp521
mockKeyEcdsaSecp521,
keyTypes
} from './mock-data.js';
import {testAlgorithm, testGenerate} from './assertions.js';

const should = chai.should();
const {expect} = chai;

Expand All @@ -27,18 +30,11 @@ describe('EcdsaMultikey', () => {
});

describe('algorithm', () => {
it('signer() instance should export proper algorithm', async () => {
const keyPair = await EcdsaMultikey.from(mockKey);
const signer = keyPair.signer();
signer.algorithm.should.equal('P-256');
});

it('verifier() instance should export proper algorithm', async () => {
const keyPair = await EcdsaMultikey.from(mockKey);
const verifier = keyPair.verifier();
verifier.algorithm.should.equal('P-256');
});

for(const [keyType, {serializedKeyPair}] of keyTypes) {
describe(keyType, function() {
testAlgorithm({keyType, serializedKeyPair});
});
}
it('deriveSecret() should not be supported by default', async () => {
const keyPair = await EcdsaMultikey.generate({curve: 'P-256'});

Expand All @@ -65,33 +61,12 @@ describe('EcdsaMultikey', () => {
});
});

describe('generate', () => {
it('should generate a key pair', async () => {
let keyPair;
let error;
try {
keyPair = await EcdsaMultikey.generate({curve: 'P-256'});
} catch(e) {
error = e;
}
should.not.exist(error);

expect(keyPair).to.have.property('publicKeyMultibase');
expect(keyPair).to.have.property('secretKeyMultibase');
expect(keyPair).to.have.property('publicKey');
expect(keyPair?.publicKey instanceof CryptoKey).to.be.true;
expect(keyPair).to.have.property('secretKey');
expect(keyPair?.secretKey instanceof CryptoKey).to.be.true;
expect(keyPair).to.have.property('export');
expect(keyPair).to.have.property('signer');
expect(keyPair).to.have.property('verifier');
const secretKeyBytes = base58
.decode(keyPair.secretKeyMultibase.slice(1));
const publicKeyBytes = base58
.decode(keyPair.publicKeyMultibase.slice(1));
secretKeyBytes.length.should.equal(34);
publicKeyBytes.length.should.equal(35);
});
describe('generate', function() {
for(const [keyType, {props}] of keyTypes) {
describe(keyType, function() {
testGenerate({curve: keyType, ...props});
});
}
});

describe('export', () => {
Expand Down
100 changes: 100 additions & 0 deletions test/assertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*!
* Copyright (c) 2023-2024 Digital Bazaar, Inc.
*/
import * as base58 from 'base58-universal';
import chai from 'chai';
import * as EcdsaMultikey from '../lib/index.js';
import {stringToUint8Array} from './text-encoder.js';
import {CryptoKey} from '../lib/crypto.js';

chai.should();
const {expect} = chai;

export function testSignVerify({id, serializedKeyPair}) {
let signer;
let verifier;
before(async function() {
const keyPair = await EcdsaMultikey.from({
id,
...serializedKeyPair
});
signer = keyPair.signer();
verifier = keyPair.verifier();
});
it('should have correct id', function() {
signer.should.have.property('id', id);
verifier.should.have.property('id', id);
});
it('should sign & verify', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
const result = await verifier.verify({data, signature});
result.should.be.true;
});

it('has proper signature format', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
expect(signature).to.be.instanceof(Uint8Array);
});

it('fails if signing data is changed', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
const changedData = stringToUint8Array('test 4321');
const result = await verifier.verify({data: changedData, signature});
result.should.be.false;
});
}

export function testAlgorithm({serializedKeyPair, keyType}) {
it('signer() instance should export proper algorithm', async () => {
const keyPair = await EcdsaMultikey.from(serializedKeyPair);
const signer = keyPair.signer();
signer.algorithm.should.equal(keyType);
});
it('verifier() instance should export proper algorithm', async () => {
const keyPair = await EcdsaMultikey.from(serializedKeyPair);
const verifier = keyPair.verifier();
verifier.algorithm.should.equal(keyType);
});
}

export function testGenerate({
curve,
decoder = base58,
secretKeyByteLength = 34,
publicKeyByteLength = 35
}) {
it('should generate a key pair', async function() {
let keyPair;
let err;
try {
keyPair = await EcdsaMultikey.generate({curve});
} catch(e) {
err = e;
}
expect(err).to.not.exist;

expect(keyPair).to.have.property('publicKeyMultibase');
expect(keyPair).to.have.property('secretKeyMultibase');
expect(keyPair).to.have.property('publicKey');
expect(keyPair?.publicKey instanceof CryptoKey).to.be.true;
expect(keyPair).to.have.property('secretKey');
expect(keyPair?.secretKey instanceof CryptoKey).to.be.true;
expect(keyPair).to.have.property('export');
expect(keyPair).to.have.property('signer');
expect(keyPair).to.have.property('verifier');
const secretKeyBytes = decoder
.decode(keyPair.secretKeyMultibase.slice(1));
const publicKeyBytes = decoder
.decode(keyPair.publicKeyMultibase.slice(1));
secretKeyBytes.length.should.equal(
secretKeyByteLength,
`Expected secretKey byte length to be ${secretKeyByteLength}.`);
publicKeyBytes.length.should.equal(
publicKeyByteLength,
`Expected publicKey byte length to be ${publicKeyByteLength}.`);
});
}

29 changes: 26 additions & 3 deletions test/mock-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,31 @@ export const mockKeyEcdsaSecp521 = {
'K6vuzCXSp1hwwvgGGEnQS82ZeKaPcFDrvhWhaq4767Am'
};

const getKeyId = ({controller, publicKeyMultibase}) =>
`${controller}#${publicKeyMultibase}`;

export const keyTypes = new Map([
['P-256', mockKeyEcdsaSecp256],
['P-384', mockKeyEcdsaSecp384],
['P-521', mockKeyEcdsaSecp521]
['P-256', {
id: getKeyId(mockKeyEcdsaSecp256),
serializedKeyPair: mockKeyEcdsaSecp256,
props: {

}
}],
['P-384', {
id: getKeyId(mockKeyEcdsaSecp384),
serializedKeyPair: mockKeyEcdsaSecp384,
props: {
secretKeyByteLength: 50,
publicKeyByteLength: 51
}
}],
['P-521', {
id: getKeyId(mockKeyEcdsaSecp521),
serializedKeyPair: mockKeyEcdsaSecp521,
props: {
secretKeyByteLength: 68,
publicKeyByteLength: 69
}
}]
]);
14 changes: 14 additions & 0 deletions test/multikey.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*!
* Copyright (c) 2024 Digital Bazaar, Inc.
*/
/*
import {multikeys} from './mock-data.js';
describe('multikey', function() {
for(const [keyType, options] of multikeys) {
describe(keyType, function() {
});
}
})
*/
53 changes: 3 additions & 50 deletions test/sign-verify.spec.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,13 @@
/*!
* Copyright (c) 2023-2024 Digital Bazaar, Inc.
*/
import chai from 'chai';
import * as EcdsaMultikey from '../lib/index.js';
import {keyTypes} from './mock-data.js';
import {stringToUint8Array} from './text-encoder.js';

chai.should();
const {expect} = chai;
import {testSignVerify} from './assertions.js';

describe('sign and verify', function() {
for(const [keyType, exportedKey] of keyTypes) {
for(const [keyType, {serializedKeyPair, id}] of keyTypes) {
describe(keyType, function() {
const id = `${exportedKey.controller}#${exportedKey.publicKeyMultibase}`;
_testKeyType({id, exportedKey, keyType});
testSignVerify({id, serializedKeyPair, keyType});
});
}
});

function _testKeyType({id, exportedKey, keyType}) {
let signer;
let verifier;
before(async function() {
const keyPair = await EcdsaMultikey.from({
id,
...exportedKey
});
signer = keyPair.signer();
verifier = keyPair.verifier();
});
it('should have correct id', function() {
signer.should.have.property('id', id);
verifier.should.have.property('id', id);
});
it(`should have algorithm ${keyType}`, function() {
signer.should.have.property('algorithm', keyType);
verifier.should.have.property('algorithm', keyType);
});
it('should sign & verify', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
const result = await verifier.verify({data, signature});
result.should.be.true;
});

it('has proper signature format', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
expect(signature).to.be.instanceof(Uint8Array);
});

it('fails if signing data is changed', async function() {
const data = stringToUint8Array('test 1234');
const signature = await signer.sign({data});
const changedData = stringToUint8Array('test 4321');
const result = await verifier.verify({data: changedData, signature});
result.should.be.false;
});
}

0 comments on commit 51db63f

Please sign in to comment.