Update unit tests for key vault
This commit is contained in:
Родитель
6c18f93c2a
Коммит
5a9b7e4795
|
@ -1,3 +1,8 @@
|
|||
# version 1.1.12-preview.1
|
||||
## Keyvault exportKey did not add the kid in the jwk.
|
||||
**Type of change:** engineering
|
||||
**Customer impact:** low
|
||||
|
||||
# version 1.1.12-preview.0
|
||||
## Remove all console.log calls from the SDK
|
||||
**Type of change:** engineering
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-keystore",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"description": "Package for managing keys in a key store.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -35,7 +35,7 @@
|
|||
"typescript": "4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"@types/node": "14.6.2",
|
||||
"base64url": "^3.0.1",
|
||||
"clone": "^2.1.2",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-keys",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"description": "Package for managing keys in the DID space.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"description": "Package crypto factory suites.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -36,9 +36,9 @@
|
|||
"typescript": "4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.1",
|
||||
"base64url": "^3.0.1",
|
||||
"clone": "2.1.2",
|
||||
"webcrypto-core": "1.1.8"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-plugin-elliptic",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -29,7 +29,7 @@
|
|||
"elliptic": "6.5.3",
|
||||
"minimalistic-crypto-utils": "1.0.1",
|
||||
"sha.js": "^2.4.11",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"webcrypto-core": "1.1.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-plugin-factory",
|
||||
"description": "Factory Package for crypto plugins.",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -39,10 +39,10 @@
|
|||
"dependencies": {
|
||||
"@azure/identity": "1.0.0",
|
||||
"lru-cache": "6.0.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-keyvault": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-keyvault": "1.1.12-preview.1",
|
||||
"@types/node": "14.6.2",
|
||||
"webcrypto-core": "1.1.8"
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-plugin-keyvault",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -50,10 +50,10 @@
|
|||
"@azure/keyvault-keys": "4.0.2",
|
||||
"@azure/keyvault-secrets": "4.0.2",
|
||||
"lru-cache": "6.0.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.1",
|
||||
"base64url": "3.0.1",
|
||||
"clone": "2.1.2",
|
||||
"webcrypto-core": "1.1.8"
|
||||
|
|
|
@ -135,7 +135,7 @@ export default class KeyStoreKeyVault implements IKeyStore {
|
|||
keyContainerItem = options.publicKeyOnly ?
|
||||
new RsaPublicKey(version.key ? version.key : version.value as any) : new RsaPrivateKey(version.key ? version.key : version.value as any);
|
||||
} else {
|
||||
throw new Error(`Non supported key type ${kty}`);
|
||||
return Promise.reject(new Error(`Non supported key type ${kty}`));
|
||||
}
|
||||
} else {
|
||||
if (kty === 'EC') {
|
||||
|
@ -159,15 +159,14 @@ export default class KeyStoreKeyVault implements IKeyStore {
|
|||
}
|
||||
|
||||
if (!container) {
|
||||
throw new Error(`The secret with reference '${keyName}' has not usable secrets`);
|
||||
return Promise.reject(new Error(`The secret with reference '${keyName}' has not usable secrets`));
|
||||
}
|
||||
|
||||
return container;
|
||||
} catch (e) {
|
||||
console.error(`Could not retrieve ${JSON.stringify(keyReference)}. Error: ${e}`);
|
||||
throw e;
|
||||
return Promise.reject(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,7 +178,7 @@ export default class KeyStoreKeyVault implements IKeyStore {
|
|||
*/
|
||||
async save(keyReference: KeyReference, key: CryptographicKey | string, options: KeyStoreOptions = new KeyStoreOptions()): Promise<void> {
|
||||
if (!keyReference || !keyReference.keyReference) {
|
||||
throw new Error(`Key reference needs to be specified`);
|
||||
return Promise.reject(new Error(`Key reference needs to be specified`));
|
||||
}
|
||||
const keyName = keyReference.remoteKeyReference || keyReference.keyReference;
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ export default class KeyVaultEcdsaProvider extends KeyVaultProvider {
|
|||
|
||||
const kid = (<any>key.algorithm).kid;
|
||||
if (!kid) {
|
||||
throw new CryptoError(algorithm, 'Missing kid in algortihm');
|
||||
return Promise.reject(new CryptoError(algorithm, 'Missing kid in algortihm'));
|
||||
}
|
||||
|
||||
const client = (<KeyStoreKeyVault>this.keyStore).getCryptoClient(kid);
|
||||
|
@ -65,7 +65,7 @@ export default class KeyVaultEcdsaProvider extends KeyVaultProvider {
|
|||
// Added for legacy. Used by keys generated with crv: SECP256K1
|
||||
signature = await client.sign(<any>'ECDSA256', new Uint8Array(hash));
|
||||
} else {
|
||||
throw exception;
|
||||
return Promise.reject(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,28 +85,28 @@ export default class KeyVaultEcdsaProvider extends KeyVaultProvider {
|
|||
jwk: JsonWebKey, _algorithm: EcKeyImportParams, _extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
|
||||
|
||||
if (format !== 'jwk') {
|
||||
throw new Error(`Import key only supports jwk`);
|
||||
return Promise.reject(new Error(`Import key only supports jwk`));
|
||||
}
|
||||
|
||||
if (jwk.kty?.toUpperCase() !== 'EC') {
|
||||
throw new Error(`Import key only supports kty EC`);
|
||||
return Promise.reject(new Error(`Import key only supports kty EC`));
|
||||
}
|
||||
|
||||
if (jwk.crv?.toUpperCase() === 'SECP256K1') {
|
||||
jwk.crv = 'P-256K';
|
||||
} else if (jwk.crv?.toUpperCase() !== 'P-256K') {
|
||||
throw new Error(`Import key only supports crv P-256K`);
|
||||
return Promise.reject(new Error(`Import key only supports crv P-256K`));
|
||||
}
|
||||
|
||||
if (!jwk.kid && jwk.kid!.startsWith('https://')) {
|
||||
throw new Error(`Imported key must have a kid in the format https://<vault>/keys/<name>/<version>`);
|
||||
if (!(jwk.kid && jwk.kid.startsWith('https://'))) {
|
||||
return Promise.reject(new Error(`Imported key must have a kid in the format https://<vault>/keys/<name>/<version>`));
|
||||
}
|
||||
|
||||
const kidParts = jwk.kid!.split('/');
|
||||
let secretType: boolean = kidParts[3] === 'secrets';
|
||||
|
||||
if (!['keys', 'secrets'].includes(kidParts[3])) {
|
||||
throw new Error(`Imported key must be of type keys or secrets`);
|
||||
if (!(kidParts.length >= 5 && ['keys', 'secrets'].includes(kidParts[3]))) {
|
||||
return Promise.reject(new Error(`Imported key must be of type keys or secrets`));
|
||||
}
|
||||
|
||||
if (kidParts.length <= 5) {
|
||||
|
@ -189,8 +189,13 @@ export default class KeyVaultEcdsaProvider extends KeyVaultProvider {
|
|||
*/
|
||||
async onExportKey(format: KeyFormat, key: CryptoKey): Promise<JsonWebKey> {
|
||||
if (format !== 'jwk') {
|
||||
throw new Error(`Export key only supports jwk`);
|
||||
return Promise.reject(new Error(`Export key only supports jwk`));
|
||||
}
|
||||
return <Promise<JsonWebKey>>this.subtle.exportKey(format, key);
|
||||
|
||||
const jwk: any = await this.subtle.exportKey(format, key);
|
||||
if (!jwk.kid) {
|
||||
jwk.kid = (<any>key.algorithm).kid;
|
||||
}
|
||||
return <Promise<JsonWebKey>>jwk;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { ClientSecretCredential } from '@azure/identity';
|
||||
import { KeyReference, KeyStoreInMemory } from 'verifiablecredentials-crypto-sdk-typescript-keystore';
|
||||
import { CryptoFactoryScope, Subtle } from 'verifiablecredentials-crypto-sdk-typescript-plugin';
|
||||
import { CryptoFactoryKeyVault, KeyStoreKeyVault } from '../src';
|
||||
|
||||
describe('CryptoFactoryKeyVault', () => {
|
||||
it('should create a CryptoFactoryKeyVault', () => {
|
||||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential('tenant', 'clientid', 'secret');
|
||||
const keyStore = new KeyStoreKeyVault(credential, 'https://example.vault.com', cache);
|
||||
const subtle = new Subtle();
|
||||
|
||||
const crypto = new CryptoFactoryKeyVault(keyStore, subtle);
|
||||
expect(crypto.getMessageSigner('ES256K', CryptoFactoryScope.Private, new KeyReference('key', 'key')).constructor.name).toEqual('SubtleCryptoKeyVault');
|
||||
expect(crypto.getMessageSigner('ECDSA', CryptoFactoryScope.Private, new KeyReference('key', 'key')).constructor.name).toEqual('SubtleCryptoKeyVault');
|
||||
expect(crypto.getKeyEncrypter('RSA-OAEP-256', CryptoFactoryScope.Private, new KeyReference('key', 'key')).constructor.name).toEqual('SubtleCryptoKeyVault');
|
||||
expect(crypto.getKeyEncrypter('RSA-OAEP', CryptoFactoryScope.Private, new KeyReference('key', 'key')).constructor.name).toEqual('SubtleCryptoKeyVault');
|
||||
expect(crypto.getMessageSigner('RSASSA-PKCS1-v1_5', CryptoFactoryScope.Private, new KeyReference('key', 'key')).constructor.name).toEqual('Subtle');
|
||||
})
|
||||
});
|
|
@ -46,11 +46,11 @@ afterEach(() => {
|
|||
describe('KeyStoreKeyVault', () => {
|
||||
const alg = { name: 'ECDSA', namedCurve: 'SECP256K1', hash: { name: 'SHA-256' } };
|
||||
if (!keyVaultEnable) {
|
||||
console.log('Key vault is enabled. Add your credentials to Credentials.ts')
|
||||
console.log('Key vault is not enabled. Add your credentials to Credentials.ts')
|
||||
return;
|
||||
}
|
||||
|
||||
it('should create an instance', () =>{
|
||||
it('should create an instance', () => {
|
||||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
let vault = 'https://example.keyvault.com';
|
||||
|
@ -74,6 +74,7 @@ describe('KeyStoreKeyVault', () => {
|
|||
expect(list[name]).toBeDefined();
|
||||
// Two requests should hit cache
|
||||
let key = await keyStore.get(new KeyReference(name, 'key'), new KeyStoreOptions({ latestVersion: false }));
|
||||
key = await keyStore.get(new KeyReference(name, 'key'), new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(key).toBeDefined();
|
||||
expect((await cache.list())[name]).toBeDefined();
|
||||
} finally {
|
||||
|
@ -88,11 +89,11 @@ describe('KeyStoreKeyVault', () => {
|
|||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
try {
|
||||
const secret1 = base64url.encode(name);
|
||||
const secret2 = base64url.encode(name+'2');
|
||||
const secret2 = base64url.encode(name + '2');
|
||||
|
||||
//save two versions
|
||||
await keyStore.save( new KeyReference(name), secret1);
|
||||
await keyStore.save( new KeyReference(name), secret2);
|
||||
await keyStore.save(new KeyReference(name), secret1);
|
||||
await keyStore.save(new KeyReference(name), secret2);
|
||||
|
||||
let list = await keyStore.list('secret', new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(list[name]).toBeDefined();
|
||||
|
@ -111,6 +112,7 @@ describe('KeyStoreKeyVault', () => {
|
|||
}
|
||||
});
|
||||
it('should list a named stored secret with EC', async () => {
|
||||
let cleaned = false;
|
||||
const name = 'KvTest-KeyStoreKeyVault' + Math.random().toString(10).substr(2);
|
||||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
|
@ -122,18 +124,19 @@ describe('KeyStoreKeyVault', () => {
|
|||
const jwk: any = await subtle.exportKey('jwk', keyPair.privateKey);
|
||||
|
||||
//save two versions
|
||||
await keyStore.save( new KeyReference(name), jwk);
|
||||
await keyStore.save(new KeyReference(name), jwk);
|
||||
|
||||
// save okp version
|
||||
let okp = clone(jwk);
|
||||
okp.kty = 'OKP';
|
||||
await keyStore.save( new KeyReference(name), jwk);
|
||||
await keyStore.save(new KeyReference(name), jwk);
|
||||
|
||||
let list = await keyStore.list('secret', new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(list[name]).toBeDefined();
|
||||
|
||||
// get latest version only
|
||||
// get latest version only, second should
|
||||
let key = await keyStore.get(new KeyReference(name, 'secret'), new KeyStoreOptions({ latestVersion: true }));
|
||||
key = await keyStore.get(new KeyReference(name, 'secret'), new KeyStoreOptions({ latestVersion: true }));
|
||||
expect(key.keys.length).toEqual(1);
|
||||
//TODO BUG. k is reported as object
|
||||
expect((await cache.list())[name]).toBeDefined();
|
||||
|
@ -147,17 +150,22 @@ describe('KeyStoreKeyVault', () => {
|
|||
expect(key.keys.length).toEqual(1);
|
||||
|
||||
// negative cases
|
||||
/** ROB TODO
|
||||
getKeyStoreClientSpy: jasmine.Spy = spyOn(keyStore, 'getKeyStoreClient').and.callFake(() => () => {
|
||||
return {
|
||||
keys: {
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
cleaned = true;
|
||||
await (<SecretClient>keyStore.getKeyStoreClient('secret')).beginDeleteSecret(name);
|
||||
const getKeyStoreClientSpy: jasmine.Spy = spyOn(keyStore, 'getKeyStoreClient').and.callFake(() => {
|
||||
throw new Error('some error');
|
||||
});
|
||||
try {
|
||||
await keyStore.get(new KeyReference(name, 'secret'), new KeyStoreOptions({ latestVersion: true }));
|
||||
fail('get should have thrown');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('some error');
|
||||
|
||||
}
|
||||
} finally {
|
||||
await (<SecretClient>keyStore.getKeyStoreClient('secret')).beginDeleteSecret(name);
|
||||
if (!cleaned) {
|
||||
await (<SecretClient>keyStore.getKeyStoreClient('secret')).beginDeleteSecret(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -173,11 +181,11 @@ describe('KeyStoreKeyVault', () => {
|
|||
await provider.onGenerateKey(alg, false, ['sign'], { keyReference: new KeyReference(name) });
|
||||
|
||||
let parts = (<any>keyPair.publicKey.algorithm).kid.split('/');
|
||||
const keyName = `${parts[parts.length-2]}/${parts[parts.length-1]}`;
|
||||
const keyName = `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
|
||||
|
||||
let list = await keyStore.list('key', new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(list[name].kids[0].includes(keyName) || list[name].kids[1].includes(keyName)).toBeTruthy();
|
||||
const key = await keyStore.get(new KeyReference(name, 'key',keyName), new KeyStoreOptions({ latestVersion: false }));
|
||||
const key = await keyStore.get(new KeyReference(name, 'key', keyName), new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(key.keys.length).toEqual(1);
|
||||
console.log(`name: ${keyName}`);
|
||||
console.log(`${JSON.stringify(key.keys[0])}`);
|
||||
|
@ -209,17 +217,20 @@ describe('KeyStoreKeyVault', () => {
|
|||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
let throwed = false;
|
||||
await keyStore.save(new KeyReference(name, 'secret'), 'abcdefg');
|
||||
let list = await keyStore.list('secret', new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(list[name]).toBeDefined();
|
||||
try {
|
||||
await keyStore.save(new KeyReference(name, 'secret'), 'abcdefg');
|
||||
let list = await keyStore.list('secret', new KeyStoreOptions({ latestVersion: false }));
|
||||
expect(list[name]).toBeDefined();
|
||||
await cache.get(new KeyReference(name, 'secret'));
|
||||
expect(throwed).toBeTruthy();
|
||||
fail('Should have thrown during get: should set a secret');
|
||||
} catch (err) {
|
||||
throwed = true;
|
||||
expect(err.message).toEqual(`${name} not found`)
|
||||
|
||||
}
|
||||
try {
|
||||
await keyStore.save(<any>undefined, '');
|
||||
fail('Should have thrown during save: should set a secret');
|
||||
} catch (err) {
|
||||
expect(err.message).toEqual(`Key reference needs to be specified`)
|
||||
} finally {
|
||||
await (<SecretClient>keyStore.getKeyStoreClient('secret')).beginDeleteSecret(name);
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import KeyVaultEcdsaProvider from '../src/plugin/KeyVaultEcdsaProvider';
|
|||
import KeyVaultRsaOaepProvider from '../src/plugin/KeyVaultRsaOaepProvider';
|
||||
import { KeyStoreOptions, KeyStoreInMemory, KeyReference } from 'verifiablecredentials-crypto-sdk-typescript-keystore';
|
||||
import { KeyClient } from '@azure/keyvault-keys';
|
||||
import { Subtle, CryptoFactoryScope, IKeyGenerationOptions } from 'verifiablecredentials-crypto-sdk-typescript-plugin';
|
||||
import { Subtle, IKeyGenerationOptions } from 'verifiablecredentials-crypto-sdk-typescript-plugin';
|
||||
import Credentials from './Credentials';
|
||||
import { KeyVaultProvider, CryptoFactoryKeyVault, SubtleCryptoKeyVault } from '../src';
|
||||
import { KeyVaultProvider, SubtleCryptoKeyVault } from '../src';
|
||||
const clone = require('clone');
|
||||
|
||||
// Sample config
|
||||
|
@ -20,7 +20,7 @@ const clientSecret = encodeURI(Credentials.clientSecret);
|
|||
const vaultUri = Credentials.vaultUri;
|
||||
const keyVaultEnable = vaultUri.startsWith('https://');
|
||||
|
||||
const subtle = new Subtle();
|
||||
const subtleCrypto = new Subtle();
|
||||
const random = (length: number) => Math.random().toString(36).substring(2, length + 2);
|
||||
const logging = require('adal-node').Logging;
|
||||
logging.setLoggingOptions({
|
||||
|
@ -43,7 +43,7 @@ afterEach(() => {
|
|||
|
||||
describe('KeyVaultPlugin', () => {
|
||||
if (!keyVaultEnable) {
|
||||
console.log('Key vault is enabled. Add your credentials to Credentials.ts')
|
||||
console.log('Key vault is not enabled. Add your credentials to Credentials.ts')
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -53,13 +53,25 @@ describe('KeyVaultPlugin', () => {
|
|||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
try {
|
||||
const result: CryptoKeyPair = await plugin.onGenerateKey(alg, false, ['sign']);
|
||||
expect((<any>result.publicKey).algorithm.namedCurve).toEqual('K-256');
|
||||
expect(result.publicKey.algorithm.name).toEqual('ECDSA');
|
||||
expect((<any>result.publicKey.algorithm).kid.startsWith('https')).toBeTruthy();
|
||||
expect((<any>result.publicKey.algorithm).kid.includes(name)).toBeTruthy();
|
||||
const keypair: CryptoKeyPair = await plugin.onGenerateKey(alg, false, ['sign']);
|
||||
expect((<any>keypair.publicKey).algorithm.namedCurve).toEqual('K-256');
|
||||
expect(keypair.publicKey.algorithm.name).toEqual('ECDSA');
|
||||
expect((<any>keypair.publicKey.algorithm).kid.startsWith('https')).toBeTruthy();
|
||||
expect((<any>keypair.publicKey.algorithm).kid.includes(name)).toBeTruthy();
|
||||
|
||||
const jwk: any = await plugin.exportKey('jwk', keypair.publicKey);
|
||||
expect(jwk.kid.startsWith('https://')).toBeTruthy();
|
||||
|
||||
// negative cases
|
||||
try {
|
||||
await plugin.exportKey('raw', keypair.publicKey);
|
||||
fail('export key raw should fail');
|
||||
} catch(exception) {
|
||||
expect(exception.message).toEqual('Export key only supports jwk');
|
||||
}
|
||||
|
||||
} finally {
|
||||
await (<KeyClient>keyStore.getKeyStoreClient('key')).beginDeleteKey(name);
|
||||
}
|
||||
|
@ -70,7 +82,7 @@ describe('KeyVaultPlugin', () => {
|
|||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
try {
|
||||
let keyReference = new KeyReference(name, 'key');
|
||||
let curve = 'P-256K';
|
||||
|
@ -91,7 +103,7 @@ describe('KeyVaultPlugin', () => {
|
|||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
try {
|
||||
|
||||
let keyReference = new KeyReference(name, 'key', remoteName);
|
||||
|
@ -113,19 +125,42 @@ describe('KeyVaultPlugin', () => {
|
|||
const cache = new KeyStoreInMemory();
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
const subtle = new SubtleCryptoKeyVault(new Subtle(), keyStore);
|
||||
const subtleKv = new SubtleCryptoKeyVault(new Subtle(), keyStore);
|
||||
try {
|
||||
|
||||
const keyReference = new KeyReference(name, 'key', remoteName);
|
||||
const curve = 'P-256K';
|
||||
const alg = { name: 'ECDSA', namedCurve: 'secp256k1', hash: { name: 'SHA-256' } };
|
||||
const keypair = await subtle.generateKey(alg, false, ['sign', 'verify'], { keyReference, curve });
|
||||
const keypair = await subtleKv.generateKey(alg, false, ['sign', 'verify'], { keyReference, curve });
|
||||
const payload = Buffer.from('hello Houston');
|
||||
const signature = await subtle.sign(alg, keypair.publicKey, payload);
|
||||
const signature = await subtleKv.sign(alg, keypair.publicKey, payload);
|
||||
expect(signature.byteLength).toEqual(64);
|
||||
|
||||
const jwk = await subtle.exportKey('jwk', keypair.publicKey);
|
||||
const jwk = await subtleKv.exportKey('jwk', keypair.publicKey);
|
||||
expect(jwk.kty).toEqual('EC');
|
||||
|
||||
// negative cases
|
||||
let publicKey = clone(keypair.publicKey);
|
||||
delete (<any>publicKey.algorithm).kid;
|
||||
try {
|
||||
await subtleKv.sign(alg, publicKey, payload);
|
||||
fail('sign should throw');
|
||||
} catch(exception) {
|
||||
expect(exception.message).toEqual('Missing kid in algortihm');
|
||||
}
|
||||
|
||||
let getCryptoClientSpy: jasmine.Spy = spyOn(keyStore, 'getCryptoClient').and.callFake(() => {
|
||||
return {
|
||||
sign: () => Promise.reject(new Error('spy signing error'))
|
||||
};
|
||||
});
|
||||
try {
|
||||
await subtleKv.sign(alg, keypair.publicKey, payload);
|
||||
fail('sign should throw');
|
||||
} catch(exception) {
|
||||
expect(exception.message).toEqual('spy signing error');
|
||||
}
|
||||
|
||||
} finally {
|
||||
await (<KeyClient>keyStore.getKeyStoreClient('key')).beginDeleteKey(remoteName);
|
||||
}
|
||||
|
@ -139,7 +174,7 @@ describe('KeyVaultPlugin', () => {
|
|||
try {
|
||||
let list = await keyStore.list('key', new KeyStoreOptions({ latestVersion: false }));
|
||||
const versions = list[name];
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
|
||||
// Generate EC
|
||||
let keyPair: CryptoKeyPair = await plugin.onGenerateKey(alg, false, ['sign', 'verify']);
|
||||
|
@ -183,7 +218,7 @@ describe('KeyVaultPlugin', () => {
|
|||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
try {
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
|
||||
const payload = Buffer.from('test');
|
||||
console.log(payload);
|
||||
|
@ -198,8 +233,8 @@ describe('KeyVaultPlugin', () => {
|
|||
const webCryptoAlg = clone(alg);
|
||||
webCryptoAlg.namedCurve = 'K-256';
|
||||
const jwk = await (await cache.get(new KeyReference(name, 'key'), keyPair.publicKey)).getKey<JsonWebKey>();
|
||||
const cryptoKey = await subtle.importKey('jwk', jwk, webCryptoAlg, true, ['verify']);
|
||||
const result = await subtle.verify(webCryptoAlg, cryptoKey, Buffer.from(signature), payload);
|
||||
const cryptoKey = await subtleCrypto.importKey('jwk', jwk, webCryptoAlg, true, ['verify']);
|
||||
const result = await subtleCrypto.verify(webCryptoAlg, cryptoKey, Buffer.from(signature), payload);
|
||||
expect(result).toBeTruthy();
|
||||
expect((await cache.list())[name]).toBeDefined();
|
||||
} finally {
|
||||
|
@ -215,15 +250,15 @@ describe('KeyVaultPlugin', () => {
|
|||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
try {
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
|
||||
const payload = Buffer.from('test');
|
||||
console.log(payload);
|
||||
|
||||
// import reference key
|
||||
const keyReference = new KeyReference(name, 'key');
|
||||
let cryptoKey: any = <CryptoKey>await subtle.generateKey(alg, true, ['sign'], { keyReference });
|
||||
let jwk: any = await subtle.exportKey('jwk', cryptoKey.privateKey);
|
||||
let cryptoKey: any = <CryptoKey>await subtleCrypto.generateKey(alg, true, ['sign'], { keyReference });
|
||||
let jwk: any = await subtleCrypto.exportKey('jwk', cryptoKey.privateKey);
|
||||
jwk.kid = name;
|
||||
|
||||
await keyStore.save(keyReference, jwk, new KeyStoreOptions());
|
||||
|
@ -231,17 +266,65 @@ describe('KeyVaultPlugin', () => {
|
|||
|
||||
const cachedPublic = await (await cache.get(keyReference)).getKey<JsonWebKey>();
|
||||
|
||||
cryptoKey = await plugin.importKey('jwk', cachedPublic, alg, false, ['sign', 'verify']);
|
||||
const signature = await plugin.onSign(alg, cryptoKey, payload);
|
||||
cryptoKey = await plugin.importKey('jwk', cachedPublic, alg, false, ['sign']);
|
||||
const signature = await plugin.sign(alg, cryptoKey, payload);
|
||||
|
||||
// Set verify key
|
||||
const webCryptoAlg = clone(alg);
|
||||
webCryptoAlg.namedCurve = 'K-256';
|
||||
jwk = (await cache.get(new KeyReference(name, 'key'), new KeyStoreOptions({ publicKeyOnly: true }))).getKey<JsonWebKey>();
|
||||
cryptoKey = await subtle.importKey('jwk', jwk, webCryptoAlg, true, ['verify']);
|
||||
const result = await subtle.verify(webCryptoAlg, cryptoKey, signature, payload);
|
||||
cryptoKey = await subtleCrypto.importKey('jwk', jwk, webCryptoAlg, true, ['verify']);
|
||||
const result = await subtleCrypto.verify(webCryptoAlg, cryptoKey, signature, payload);
|
||||
expect(result).toBeTruthy();
|
||||
expect((await cache.list())[name]).toBeDefined();
|
||||
|
||||
// negative cases
|
||||
try {
|
||||
await plugin.importKey('raw', new Uint8Array([1,2,3,4]), webCryptoAlg, true, ['sign']);
|
||||
fail('import raw should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Import key only supports jwk');
|
||||
}
|
||||
let clonedJwk = clone(jwk);
|
||||
clonedJwk.kty = 'RSA'
|
||||
try {
|
||||
await plugin.importKey('jwk', clonedJwk, webCryptoAlg, true, ['sign']);
|
||||
fail('import RSA should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Import key only supports kty EC');
|
||||
}
|
||||
clonedJwk = clone(jwk);
|
||||
clonedJwk.crv = 'ed25519';
|
||||
try {
|
||||
await plugin.importKey('jwk', clonedJwk, webCryptoAlg, true, ['sign']);
|
||||
fail('import crv should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Import key only supports crv P-256K');
|
||||
}
|
||||
clonedJwk = clone(jwk);
|
||||
delete clonedJwk.kid;
|
||||
try {
|
||||
await plugin.importKey('jwk', clonedJwk, webCryptoAlg, true, ['sign']);
|
||||
fail('import crv should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Imported key must have a kid in the format https://<vault>/keys/<name>/<version>');
|
||||
}
|
||||
clonedJwk = clone(jwk);
|
||||
clonedJwk.kid = 'vaultUri';
|
||||
try {
|
||||
await plugin.importKey('jwk', clonedJwk, webCryptoAlg, true, ['sign']);
|
||||
fail('import crv should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Imported key must have a kid in the format https://<vault>/keys/<name>/<version>');
|
||||
}
|
||||
clonedJwk = clone(jwk);
|
||||
clonedJwk.kid = 'https://vault.com';
|
||||
try {
|
||||
await plugin.importKey('jwk', clonedJwk, webCryptoAlg, true, ['sign']);
|
||||
fail('import crv should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Imported key must be of type keys or secrets');
|
||||
}
|
||||
} finally {
|
||||
await (<KeyClient>keyStore.getKeyStoreClient('key')).beginDeleteKey(name);
|
||||
}
|
||||
|
@ -266,7 +349,7 @@ describe('KeyVaultPlugin', () => {
|
|||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
try {
|
||||
const plugin = new KeyVaultEcdsaProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultEcdsaProvider(subtleCrypto, keyStore);
|
||||
|
||||
// Generate EC
|
||||
let keyReference = new KeyReference(name, 'key');
|
||||
|
@ -303,19 +386,31 @@ describe('rsa-oaep', () => {
|
|||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
try {
|
||||
const plugin = new KeyVaultRsaOaepProvider(subtle, keyStore);
|
||||
const plugin = new KeyVaultRsaOaepProvider(subtleCrypto, keyStore);
|
||||
const payload = Buffer.from('hello houston');
|
||||
|
||||
// generate key
|
||||
const keyPair: CryptoKeyPair = await plugin.onGenerateKey(alg, false, ['decrypt', 'encrypt']);
|
||||
|
||||
// Encrypt with subtle
|
||||
const cipher = await subtle.encrypt(alg, keyPair.publicKey, payload);
|
||||
const cipher = await subtleCrypto.encrypt(alg, keyPair.publicKey, payload);
|
||||
|
||||
// decrypt with key vault
|
||||
const decrypt = await plugin.onDecrypt(alg, keyPair.publicKey, cipher);
|
||||
expect(Buffer.from(decrypt)).toEqual(payload);
|
||||
expect((await cache.list())[name]).toBeDefined();
|
||||
|
||||
// negative cases
|
||||
let clonedPk = clone(keyPair.publicKey);
|
||||
delete clonedPk.algorithm.kid;
|
||||
|
||||
try {
|
||||
await plugin.decrypt(alg, clonedPk, cipher);
|
||||
fail('decrypt RSA should fail');
|
||||
} catch (exception) {
|
||||
expect(exception.message).toEqual('Missing kid in algortihm');
|
||||
}
|
||||
|
||||
} finally {
|
||||
await (<KeyClient>keyStore.getKeyStoreClient('key')).beginDeleteKey(name);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { KeyStoreInMemory } from 'verifiablecredentials-crypto-sdk-typescript-keystore';
|
||||
import { KeyStoreKeyVault, SubtleCryptoKeyVault } from '../src';
|
||||
import { ClientSecretCredential } from '@azure/identity';
|
||||
import { Subtle } from 'verifiablecredentials-crypto-sdk-typescript-plugin';
|
||||
import Credentials from './Credentials';
|
||||
|
||||
describe('SubtleCryptoKeyVault', () => {
|
||||
// Sample config
|
||||
const tenantId = Credentials.tenantGuid;
|
||||
const clientId = Credentials.clientId;
|
||||
const clientSecret = encodeURI(Credentials.clientSecret);
|
||||
const vaultUri = Credentials.vaultUri;
|
||||
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
||||
const keyVaultEnable = vaultUri.startsWith('https://');
|
||||
|
||||
const cache = new KeyStoreInMemory();
|
||||
const keyStore = new KeyStoreKeyVault(credential, vaultUri, cache);
|
||||
const subtle = new Subtle();
|
||||
const subtleKv: any = new SubtleCryptoKeyVault(subtle, keyStore);
|
||||
|
||||
if (!keyVaultEnable) {
|
||||
console.log('Key vault is not enabled. Add your credentials to Credentials.ts')
|
||||
return;
|
||||
}
|
||||
|
||||
const genKey = async () => {
|
||||
const cryptoKey = await subtleKv.generateKey(<EcKeyGenParams>{ name: "ECDSA", hash: { name: "SHA-256" }, namedCurve: 'secp256k1' }, true, ["sign", "verify"]);
|
||||
return cryptoKey;
|
||||
}
|
||||
|
||||
it('should create instance', () => {
|
||||
let subtleKv: any = new SubtleCryptoKeyVault(subtle, keyStore);
|
||||
expect(subtleKv.getSubtleCrypto().constructor.name).toEqual('SubtleCryptoKeyVault');
|
||||
});
|
||||
|
||||
it('should generate key', async () => {
|
||||
const cryptoKey = await genKey();
|
||||
expect(cryptoKey).toBeDefined();
|
||||
});
|
||||
|
||||
it('should test algorithmTransform', () => {
|
||||
let alg: any = {test: 'name'};
|
||||
expect(subtleKv.algorithmTransform(alg)).toEqual(alg);
|
||||
alg = {foo: 'fighters'};
|
||||
expect(subtleKv.algorithmTransform(alg)).toEqual(alg);
|
||||
});
|
||||
it('should test keyImportTransform', () => {
|
||||
let jwk: any = { test: 'name' };
|
||||
expect(subtleKv.keyImportTransform(jwk)).toEqual(jwk);
|
||||
jwk = { foo: 'fighters' };
|
||||
expect(subtleKv.keyImportTransform(jwk)).toEqual(jwk);
|
||||
jwk = { crv: 'P-256K' };
|
||||
expect(subtleKv.keyImportTransform(jwk)).toEqual({ crv: 'SECP256K1' });
|
||||
jwk = { crv: 'SECP256K1' };
|
||||
expect(subtleKv.keyImportTransform(jwk)).toEqual({ crv: 'SECP256K1' });
|
||||
jwk = { crv: 'XXX' };
|
||||
expect(subtleKv.keyImportTransform(jwk)).toEqual({ crv: 'XXX' });
|
||||
|
||||
});
|
||||
it('should test keyExportTransform', () => {
|
||||
let jwk: any = { test: 'name' };
|
||||
expect(subtleKv.keyExportTransform(jwk)).toEqual(jwk);
|
||||
jwk = { foo: 'fighters' };
|
||||
expect(subtleKv.keyExportTransform(jwk)).toEqual(jwk);
|
||||
jwk = { crv: 'P-256K' };
|
||||
expect(subtleKv.keyExportTransform(jwk)).toEqual({ crv: 'SECP256K1' });
|
||||
jwk = { crv: 'K-256' };
|
||||
expect(subtleKv.keyExportTransform(jwk)).toEqual({ crv: 'SECP256K1' });
|
||||
jwk = { crv: 'SECP256K1' };
|
||||
expect(subtleKv.keyExportTransform(jwk)).toEqual({ crv: 'SECP256K1' });
|
||||
});
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-plugin",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"description": "Package for plugeable crypto based on subtle crypto.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -35,8 +35,8 @@
|
|||
"typescript": "4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"@peculiar/webcrypto": "1.1.3",
|
||||
"@types/node": "14.6.2",
|
||||
"base64url": "^3.0.1",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-protocol-jose",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -39,11 +39,11 @@
|
|||
"typescript": "4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocols-common": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocols-common": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.1",
|
||||
"base64url": "^3.0.1",
|
||||
"typescript-map": "0.0.7",
|
||||
"webcrypto-core": "1.1.8"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript-protocols-common",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -39,9 +39,9 @@
|
|||
"typescript": "4.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"base64url": "3.0.1",
|
||||
"typescript-map": "0.0.7",
|
||||
"webcrypto-core": "1.1.8"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "verifiablecredentials-crypto-sdk-typescript",
|
||||
"version": "1.1.12-preview.0",
|
||||
"version": "1.1.12-preview.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/VerifiableCredentials-Crypto-SDK-Typescript.git"
|
||||
|
@ -53,15 +53,15 @@
|
|||
"jsonld": "2.0.2",
|
||||
"typescript-map": "0.0.7",
|
||||
"uuid": "^8.3.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-factory": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-keyvault": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocol-jose": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocols-common": "1.1.12-preview.0",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keys": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-keystore": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-cryptofactory-suites": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-elliptic": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-factory": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-plugin-keyvault": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocol-jose": "1.1.12-preview.1",
|
||||
"verifiablecredentials-crypto-sdk-typescript-protocols-common": "1.1.12-preview.1",
|
||||
"webcrypto-core": "1.1.8"
|
||||
},
|
||||
"nyc": {
|
||||
|
|
Загрузка…
Ссылка в новой задаче