@microsoft/useragent-sdk
Version:
SDK for building decentralized identity wallets and enterprise agents.
193 lines • 12.5 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const JwsToken_1 = require("../../../../../src/crypto/protocols/jose/jws/JwsToken");
const OctKey_1 = require("../../../../../src/crypto/keys/Oct/OctKey");
const KeyStoreInMemory_1 = require("../../../../../src/crypto/keyStore/KeyStoreInMemory");
const CryptoFactory_1 = require("../../../../../src/crypto/plugin/CryptoFactory");
const SubtleCryptoNode_1 = require("../../../../../src/crypto/plugin/SubtleCryptoNode");
const ProtectionFormat_1 = require("../../../../../src/crypto/keyStore/ProtectionFormat");
const SubtleCryptoExtension_1 = require("../../../../../src/crypto/plugin/SubtleCryptoExtension");
const JoseProtocol_1 = require("../../../../../src/crypto/protocols/jose/JoseProtocol");
const typescript_map_1 = require("typescript-map");
const JoseConstants_1 = require("../../../../../src/crypto/protocols/jose/JoseConstants");
const KeyContainer_1 = require("../../../../../src/crypto/keys/KeyContainer");
describe('JwsToken', () => {
it('should create a jws token', async () => {
const payload = 'test payload';
const keyStore = new KeyStoreInMemory_1.default();
const seedReference = 'seed';
await keyStore.save(seedReference, new KeyContainer_1.default(new OctKey_1.default('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')));
const subtle = SubtleCryptoNode_1.default.getSubtleCrypto();
const options = {
algorithm: { name: 'ECDSA', namedCurve: 'P-256K', hash: { name: 'SHA-256' } },
cryptoFactory: new CryptoFactory_1.default(keyStore, subtle)
};
const generate = new SubtleCryptoExtension_1.default(options.cryptoFactory);
const privateKey = await generate.generatePairwiseKey(options.algorithm, seedReference, 'did:personaId', 'did:peerId');
privateKey.alg = 'ES256K';
privateKey.defaultSignAlgorithm = 'ES256K';
await keyStore.save('key', new KeyContainer_1.default(privateKey));
const jwsToken = new JwsToken_1.default(options);
const signature = await jwsToken.sign('key', Buffer.from(payload), ProtectionFormat_1.ProtectionFormat.JwsGeneralJson);
expect(signature).toBeDefined();
});
it('should create, validate and serialize a JwsToken', async () => {
const payload = 'The true sign of intelligence is not knowledge but imagination.';
const keyStore = new KeyStoreInMemory_1.default();
await keyStore.save('seed', new KeyContainer_1.default(new OctKey_1.default('ABEE')));
const cryptoFactory = new CryptoFactory_1.default(keyStore, SubtleCryptoNode_1.default.getSubtleCrypto());
const options = {
cryptoFactory: cryptoFactory,
options: new typescript_map_1.TSMap(),
payloadProtection: new JoseProtocol_1.default()
};
const alg = { name: 'RSASSA-PKCS1-V1_5', hash: 'SHA-256', modulusLength: 2048, publicExponent: new Uint8Array([0x01, 0x00, 0x01]) };
const generator = new SubtleCryptoExtension_1.default(cryptoFactory);
const privateKey = await generator.generatePairwiseKey(alg, 'seed', 'persona', 'peer');
expect(privateKey.alg).toBeUndefined();
privateKey.alg = 'RS256';
await keyStore.save('key', new KeyContainer_1.default(privateKey));
// sign
const signature = await options.payloadProtection.sign('key', Buffer.from(payload), 'JwsGeneralJson', options);
const signatures = signature.get(JoseConstants_1.default.tokenSignatures);
expect(signatures[0].protected).toBeDefined();
expect(signatures[0].signature).toBeDefined();
expect(signature.get(JoseConstants_1.default.tokenPayload)).toEqual(Buffer.from(payload));
// serialize
let serialized = options.payloadProtection.serialize(signature, 'JwsGeneralJson', options);
let parsed = JSON.parse(serialized);
expect(parsed['payload']).toBeDefined();
expect(parsed['signatures']).toBeDefined();
// deserialize
let deserialized = options.payloadProtection.deserialize(serialized, 'JwsGeneralJson', options);
let deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
// validate
const publicKeyContainer = (await keyStore.get('key', true)).getKey();
const result = await options.payloadProtection.verify([publicKeyContainer], Buffer.from(payload), signature, options);
expect(result.result).toBeTruthy();
// Flat serialization
serialized = options.payloadProtection.serialize(signature, 'JwsFlatJson', options);
parsed = JSON.parse(serialized);
expect(parsed['payload']).toBeDefined();
expect(parsed['protected']).toBeDefined();
expect(parsed['signature']).toBeDefined();
deserialized = options.payloadProtection.deserialize(serialized, 'JwsFlatJson', options);
deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
// Compact serialization
serialized = options.payloadProtection.serialize(signature, 'JwsCompactJson', options);
parsed = serialized.split('.');
expect(parsed.length).toEqual(3);
deserialized = options.payloadProtection.deserialize(serialized, 'JwsCompactJson', options);
deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
});
// tslint:disable-next-line: max-func-body-length
it('should set headers in JwsToken', async () => {
const payload = 'The true sign of intelligence is not knowledge but imagination.';
const keyStore = new KeyStoreInMemory_1.default();
await keyStore.save('seed', new KeyContainer_1.default(new OctKey_1.default('ABEE')));
const cryptoFactory = new CryptoFactory_1.default(keyStore, SubtleCryptoNode_1.default.getSubtleCrypto());
const options = {
cryptoFactory: cryptoFactory,
options: new typescript_map_1.TSMap([
[JoseConstants_1.default.optionHeader, new typescript_map_1.TSMap([['test', 'ES256K']])],
[JoseConstants_1.default.optionProtectedHeader, new typescript_map_1.TSMap([['test', 'elo']])]
]),
payloadProtection: new JoseProtocol_1.default()
};
const alg = { name: 'ECDSA', namedCurve: 'P-256K', hash: { name: 'SHA-256' }, format: 'DER' };
const generator = new SubtleCryptoExtension_1.default(cryptoFactory);
const privateKey = await generator.generatePairwiseKey(alg, 'seed', 'persona', 'peer');
privateKey.alg = 'ES256K';
await keyStore.save('key', new KeyContainer_1.default(privateKey));
let publicKey = await keyStore.get('key', true);
// sign
const signature = await options.payloadProtection.sign('key', Buffer.from(payload), 'JwsGeneralJson', options);
const signatures = signature.get(JoseConstants_1.default.tokenSignatures);
expect(signatures[0].protected.get('test')).toEqual('elo');
expect(signatures[0].header.get('test')).toEqual('ES256K');
expect(signatures[0].signature).toBeDefined();
expect(signature.get(JoseConstants_1.default.tokenPayload)).toEqual(Buffer.from(payload));
// serialize
let serialized = options.payloadProtection.serialize(signature, 'JwsGeneralJson', options);
let parsed = JSON.parse(serialized);
expect(parsed['payload']).toBeDefined();
expect(parsed['signatures']).toBeDefined();
// deserialize
let deserialized = options.payloadProtection.deserialize(serialized, 'JwsGeneralJson', options);
let deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].header).toEqual(signatures[0].header);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
// validate
const publicKeyContainer = (await keyStore.get('key', true)).getKey();
const result = await options.payloadProtection.verify([publicKeyContainer], Buffer.from(payload), signature, options);
expect(result.result).toBeTruthy();
// Flat serialization
serialized = options.payloadProtection.serialize(signature, 'JwsFlatJson', options);
parsed = JSON.parse(serialized);
expect(parsed['payload']).toBeDefined();
expect(parsed['protected']).toBeDefined();
expect(parsed['header']).toBeDefined();
expect(parsed['signature']).toBeDefined();
deserialized = options.payloadProtection.deserialize(serialized, 'JwsFlatJson', options);
deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].header).toEqual(signatures[0].header);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
// Compact serialization
serialized = options.payloadProtection.serialize(signature, 'JwsCompactJson', options);
parsed = serialized.split('.');
expect(parsed.length).toEqual(3);
deserialized = options.payloadProtection.deserialize(serialized, 'JwsCompactJson', options);
deSignatures = deserialized.get(JoseConstants_1.default.tokenSignatures);
expect(deSignatures[0].protected).toEqual(signatures[0].protected);
expect(deSignatures[0].signature).toEqual(signatures[0].signature);
expect(deserialized.get(JoseConstants_1.default.tokenPayload)).toEqual(signature.get(JoseConstants_1.default.tokenPayload));
// negative cases
let throwed = false;
try {
options.payloadProtection.serialize(signature, 'bluesky', options);
}
catch (err) {
throwed = true;
expect(err.message).toEqual(`Format 'bluesky' is not supported`);
}
expect(throwed).toBeTruthy();
throwed = false;
try {
options.payloadProtection.deserialize(serialized, 'bluesky', options);
}
catch (err) {
throwed = true;
expect(err.message).toEqual(`Format 'bluesky' is not supported`);
}
expect(throwed).toBeTruthy();
const sigs = signature.get(JoseConstants_1.default.tokenSignatures);
sigs[0].protected.set('alg', '');
throwed = false;
try {
await options.payloadProtection.verify([publicKey], Buffer.from(payload), signature, options);
}
catch (err) {
expect(err.message).toEqual('Unable to validate signature as no signature algorithm has been specified in the header.');
throwed = true;
}
expect(throwed).toBeTruthy();
});
});
//# sourceMappingURL=JwsToken.spec.js.map