@microsoft/useragent-sdk
Version:
SDK for building decentralized identity wallets and enterprise agents.
305 lines (304 loc) • 15.1 kB
JavaScript
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const IdentifierDocument_1 = require("../src/IdentifierDocument");
const Identifier_1 = require("../src/Identifier");
const UserAgentOptions_1 = require("../src/UserAgentOptions");
const TestResolver_1 = require("./resolvers/TestResolver");
const UserAgentError_1 = require("../src/UserAgentError");
const CryptoOptions_1 = require("../src/CryptoOptions");
const TestRegistrar_1 = require("./registrars/TestRegistrar");
const KeyTypeFactory_1 = require("../src/crypto/keys/KeyTypeFactory");
const KeyUseFactory_1 = require("../src/crypto/keys/KeyUseFactory");
const KeyStoreInMemory_1 = require("../src/crypto/keyStore/KeyStoreInMemory");
const JwsToken_1 = require("../src/crypto/protocols/jose/jws/JwsToken");
const OctKey_1 = require("../src/crypto/keys/Oct/OctKey");
const CryptoFactory_1 = require("../src/crypto/plugin/CryptoFactory");
const SubtleCryptoNode_1 = require("../src/crypto/plugin/SubtleCryptoNode");
const KeyContainer_1 = require("../src/crypto/keys/KeyContainer");
describe('Identifier', () => {
let testResolver;
let options;
beforeAll(() => {
testResolver = new TestResolver_1.default();
// Configure the agent options for the tests
options = new UserAgentOptions_1.default();
options.resolver = testResolver;
options.timeoutInSeconds = 30;
});
it('should construct a storage identfier for the key', () => {
let identifier = Identifier_1.default.keyStorageIdentifier('did:ion:identifier', 'peer', KeyUseFactory_1.KeyUse.Encryption, KeyTypeFactory_1.KeyType.EC);
expect(identifier).toEqual('did:ion:identifier-peer-enc-EC');
identifier = Identifier_1.default.keyStorageIdentifier('did:ion:identifier', 'peer', KeyUseFactory_1.KeyUse.Encryption, KeyTypeFactory_1.KeyType.RSA);
expect(identifier).toEqual('did:ion:identifier-peer-enc-RSA');
identifier = Identifier_1.default.keyStorageIdentifier('did:ion:identifier', 'peer', KeyUseFactory_1.KeyUse.Signature, KeyTypeFactory_1.KeyType.EC);
expect(identifier).toEqual('did:ion:identifier-peer-sig-EC');
identifier = Identifier_1.default.keyStorageIdentifier('did:ion:identifier', 'peer', KeyUseFactory_1.KeyUse.Signature, KeyTypeFactory_1.KeyType.RSA);
expect(identifier).toEqual('did:ion:identifier-peer-sig-RSA');
});
it('should construct new instance when provided an identifier string', () => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
expect(identifier).toBeDefined();
expect(identifier.id).toEqual('did:ion:identifier');
});
it('should construct new instance when provided an identifier document', () => {
const identifierDocument = new IdentifierDocument_1.default({ id: 'did:ion:identifier', created: '2019-01-25T01:08:44.732Z' });
const identifier = new Identifier_1.default(identifierDocument, options);
expect(identifier).toBeDefined();
expect(identifier.id).toEqual('did:ion:identifier');
});
it('should return document from local', () => {
const identifierDocument = new IdentifierDocument_1.default({ id: 'did:ion:identifier', created: '2019-01-25T01:08:44.732Z' });
const identifier = new Identifier_1.default(identifierDocument, options);
const resolver = spyOn(testResolver, 'resolve').and.callThrough();
const localDocument = identifier.getDocument();
expect(localDocument).toBeDefined();
expect(resolver).not.toHaveBeenCalled();
});
it('should throw when no resolver specified and document not cached', async (done) => {
const options = {
timeoutInSeconds: 30
};
const identifier = new Identifier_1.default('did:ion:identifier', options);
await identifier
.getDocument()
.catch(error => {
expect(error instanceof UserAgentError_1.default).toBeTruthy();
expect(error.message).toEqual('Resolver not specified in user agent options.');
})
.finally(done);
});
it('should resolve identifier and return document', () => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({ id: 'did:ion:identifier', created: '2019-01-25T01:08:44.732Z' });
options.resolver.prepareTest(identifier, identifierDocument);
const resolver = spyOn(testResolver, 'resolve').and.callThrough();
const result = identifier.getDocument();
expect(result).toBeDefined();
expect(resolver).toHaveBeenCalled();
});
it('should call getDocument() when local document undefined', async () => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z',
publicKeys: [
{
id: '#master',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
}
]
});
options.resolver.prepareTest(identifier, identifierDocument);
const resolver = spyOn(testResolver, 'resolve').and.callThrough();
const result = await identifier.getPublicKey('#master');
expect(result).toBeDefined();
expect(resolver).toHaveBeenCalled();
});
it('should throw when document has no keys', async (done) => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z'
});
options.resolver.prepareTest(identifier, identifierDocument);
await identifier
.getPublicKey('#master')
.catch(error => {
expect(error instanceof UserAgentError_1.default).toBeTruthy();
expect(error.message).toEqual('Document does not contain any public keys');
})
.finally(done);
});
it('should throw when document does not contain specified key', async (done) => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z',
publicKeys: [
{
id: '#master',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
}
]
});
options.resolver.prepareTest(identifier, identifierDocument);
await identifier
.getPublicKey('#notInDocument')
.catch(error => {
expect(error instanceof UserAgentError_1.default).toBeTruthy();
expect(error.message).toEqual(`No matching public key found for #notInDocument`);
})
.finally(done);
});
it('should return public key for specified key identifier', async () => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z',
publicKeys: [
{
id: '#master',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
}
]
});
options.resolver.prepareTest(identifier, identifierDocument);
const publicKey = await identifier.getPublicKey('#master');
expect(publicKey).toBeDefined();
expect(publicKey.id).toEqual('#master');
});
it('should return first public key when no key identifier specified', async () => {
const identifier = new Identifier_1.default('did:ion:identifier', options);
const identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z',
publicKeys: [
{
id: '#first',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
},
{
id: '#second',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
}
]
});
options.resolver.prepareTest(identifier, identifierDocument);
const publicKey = await identifier.getPublicKey();
expect(publicKey).toBeDefined();
expect(publicKey.id).toEqual('#first');
});
describe('sign', () => {
let options;
beforeEach(() => {
options = new UserAgentOptions_1.default();
options.resolver = testResolver;
options.timeoutInSeconds = 30;
options.didPrefix = 'did:ion';
options.registrar = new TestRegistrar_1.default();
});
it('should sign a payload that is a string', async () => {
options.cryptoOptions = new CryptoOptions_1.default(new CryptoFactory_1.default(new KeyStoreInMemory_1.default(), SubtleCryptoNode_1.default.getSubtleCrypto()));
options.cryptoOptions.signingAlgorithm = 'ES256K';
const seed = new OctKey_1.default('ABDE');
await options.keyStore.save('masterSeed', new KeyContainer_1.default(seed));
const identifier = await Identifier_1.default.create(options);
const keystore = await options.keyStore.list();
console.log(keystore);
const signedPayload = await identifier.sign('examplePayload', 'did:ion-did:ion-ES256K-sig');
expect(signedPayload).toBeDefined();
expect(JwsToken_1.default.deserialize(signedPayload).getPayload()).toEqual('examplePayload');
});
it('should sign a payload that is an object', async () => {
options.cryptoOptions = new CryptoOptions_1.default(new CryptoFactory_1.default(new KeyStoreInMemory_1.default(), SubtleCryptoNode_1.default.getSubtleCrypto()));
options.cryptoOptions.signingAlgorithm = 'ES256K';
options.keyStore = new KeyStoreInMemory_1.default();
const seed = new OctKey_1.default('ABDE');
await options.keyStore.save('masterSeed', new KeyContainer_1.default(seed));
const identifier = await Identifier_1.default.create(options);
const signedPayload = await identifier.sign({ payload: 'examplePayload' }, 'did:ion-did:ion-ES256K-sig');
expect(signedPayload).toBeDefined();
expect(JwsToken_1.default.deserialize(signedPayload).getPayload()).toEqual(`{"payload":"examplePayload"}`);
});
});
describe('verify', () => {
let identifier;
let identifierDocument;
beforeAll(() => {
identifier = new Identifier_1.default('did:ion:identifier', options);
identifierDocument = new IdentifierDocument_1.default({
id: 'did:ion:identifier',
created: '2019-01-25T01:08:44.732Z',
publicKeys: [
{
id: '#master',
type: 'RsaVerificationKey2018',
publicKeyJwk: {
kty: 'RSA',
kid: '#master',
keyOps: [
'sign',
'verify'
],
n: 'vdpHn7kNq42UMC1W8bwxgE7K...',
e: 'AQAB'
}
}
]
});
console.log(identifier);
console.log(identifierDocument);
});
/*
const testJws = 'testJWS';
fit('should resolve identifier document and verify jws', async () => {
(<TestResolver> options.resolver).prepareTest(identifier, identifierDocument);
const verifiedPayload = await identifier.verify(testJws);
expect(verifiedPayload).toBeDefined();
expect(verifiedPayload).toBe('verifiedPayload');
});
fit('should verify jws', async () => {
console.log(identifier);
const testIdentifier = new Identifier(identifierDocument, options);
const verifiedPayload = await testIdentifier.verify(testJws);
expect(verifiedPayload).toBeDefined();
expect(verifiedPayload).toBe('verifiedPayload');
});
*/
});
});
//# sourceMappingURL=Identifier.spec.js.map