From 12e2b887f74312b0735b8790182b7a220191ad8c Mon Sep 17 00:00:00 2001 From: Mircea Nistor Date: Tue, 8 Dec 2020 17:21:03 +0100 Subject: [PATCH] fix(verifyJWT): fix verification of JWT using EdDSA alg (#142) fixes #141 --- src/JWT.ts | 7 +++-- src/__tests__/JWT-test.ts | 1 - src/__tests__/didkey-test.ts | 61 ++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/__tests__/didkey-test.ts diff --git a/src/JWT.ts b/src/JWT.ts index ccf3a41a..c2387cd5 100644 --- a/src/JWT.ts +++ b/src/JWT.ts @@ -75,9 +75,10 @@ export interface PublicKeyTypes { [name: string]: string[] } export const SUPPORTED_PUBLIC_KEY_TYPES: PublicKeyTypes = { - ES256K: ['Secp256k1VerificationKey2018', 'Secp256k1SignatureVerificationKey2018', 'EcdsaPublicKeySecp256k1'], - 'ES256K-R': ['Secp256k1VerificationKey2018', 'Secp256k1SignatureVerificationKey2018', 'EcdsaPublicKeySecp256k1'], - Ed25519: ['ED25519SignatureVerification'] + ES256K: ['Secp256k1VerificationKey2018', 'Secp256k1SignatureVerificationKey2018', 'EcdsaPublicKeySecp256k1', 'EcdsaSecp256k1VerificationKey2019'], + 'ES256K-R': ['Secp256k1VerificationKey2018', 'Secp256k1SignatureVerificationKey2018', 'EcdsaPublicKeySecp256k1', 'EcdsaSecp256k1VerificationKey2019'], + Ed25519: ['ED25519SignatureVerification', 'Ed25519VerificationKey2018'], + EdDSA: ['ED25519SignatureVerification', 'Ed25519VerificationKey2018'] } const defaultAlg = 'ES256K' diff --git a/src/__tests__/JWT-test.ts b/src/__tests__/JWT-test.ts index c89072d8..d2872595 100644 --- a/src/__tests__/JWT-test.ts +++ b/src/__tests__/JWT-test.ts @@ -342,7 +342,6 @@ describe('verifyJWT()', () => { }) describe('JWS', () => { - it('createJWS works with JSON payload', async () => { const payload = { some: 'data' } const jws = await createJWS(payload, signer) diff --git a/src/__tests__/didkey-test.ts b/src/__tests__/didkey-test.ts new file mode 100644 index 00000000..3224a146 --- /dev/null +++ b/src/__tests__/didkey-test.ts @@ -0,0 +1,61 @@ +import VerifierAlgorithm from '../VerifierAlgorithm' +import { verifyJWT } from '../JWT' + +const edKey58 = { + id: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM#z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + type: 'Ed25519VerificationKey2018', + controller: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + publicKeyBase58: 'A12q688RGRdqshXhL9TW8QXQaX9H82ejU9DnqztLaAgy' +} + +describe('Ed25519', () => { + const verifier = VerifierAlgorithm('Ed25519') + + it('validates hardcoded jwt', async () => { + const jwt = + 'eyJhbGciOiJFZERTQSJ9.eyJleHAiOjE3NjQ4Nzg5MDgsImlzcyI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNIiwibmJmIjoxNjA3MTEyNTA4LCJzdWIiOiJkaWQ6a2V5Ono2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly9pZGVudGl0eS5mb3VuZGF0aW9uLy53ZWxsLWtub3duL2RpZC1jb25maWd1cmF0aW9uL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rb1RIc2dOTnJieThKekNOUTFpUkx5VzVRUTZSOFh1dTZBQThpZ0dyTVZQVU0iLCJvcmlnaW4iOiJpZGVudGl0eS5mb3VuZGF0aW9uIn0sImV4cGlyYXRpb25EYXRlIjoiMjAyNS0xMi0wNFQxNDowODoyOC0wNjowMCIsImlzc3VhbmNlRGF0ZSI6IjIwMjAtMTItMDRUMTQ6MDg6MjgtMDY6MDAiLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJEb21haW5MaW5rYWdlQ3JlZGVudGlhbCJdfX0.6ovgQ-T_rmYueviySqXhzMzgqJMAizOGUKAObQr2iikoRNsb8DHfna4rh1puwWqYwgT3QJVpzdO_xZARAYM9Dw' + const parts = jwt.match(/^([a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/) + return expect(verifier(parts[1], parts[2], [edKey58])).toEqual(edKey58) + }) + + it('handles EdDSA algorithm with did:key', async () => { + const resolver = { + resolve: jest.fn().mockReturnValue({ + '@context': 'https://w3id.org/did/v1', + id: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + publicKey: [ + { + id: + 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM#z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + type: 'Ed25519VerificationKey2018', + controller: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + publicKeyBase58: 'A12q688RGRdqshXhL9TW8QXQaX9H82ejU9DnqztLaAgy' + } + ] + }) + } + const jwt = + 'eyJhbGciOiJFZERTQSJ9.eyJleHAiOjE3NjQ4Nzg5MDgsImlzcyI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNIiwibmJmIjoxNjA3MTEyNTA4LCJzdWIiOiJkaWQ6a2V5Ono2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly9pZGVudGl0eS5mb3VuZGF0aW9uLy53ZWxsLWtub3duL2RpZC1jb25maWd1cmF0aW9uL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImlkIjoiZGlkOmtleTp6Nk1rb1RIc2dOTnJieThKekNOUTFpUkx5VzVRUTZSOFh1dTZBQThpZ0dyTVZQVU0iLCJvcmlnaW4iOiJpZGVudGl0eS5mb3VuZGF0aW9uIn0sImV4cGlyYXRpb25EYXRlIjoiMjAyNS0xMi0wNFQxNDowODoyOC0wNjowMCIsImlzc3VhbmNlRGF0ZSI6IjIwMjAtMTItMDRUMTQ6MDg6MjgtMDY6MDAiLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJEb21haW5MaW5rYWdlQ3JlZGVudGlhbCJdfX0.6ovgQ-T_rmYueviySqXhzMzgqJMAizOGUKAObQr2iikoRNsb8DHfna4rh1puwWqYwgT3QJVpzdO_xZARAYM9Dw' + const { payload } = await verifyJWT(jwt, { resolver }) + return expect(payload).toMatchObject({ + exp: 1764878908, + iss: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + nbf: 1607112508, + sub: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + vc: { + '@context': [ + 'https://www.w3.org/2018/credentials/v1', + 'https://identity.foundation/.well-known/did-configuration/v1' + ], + credentialSubject: { + id: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + origin: 'identity.foundation' + }, + expirationDate: '2025-12-04T14:08:28-06:00', + issuanceDate: '2020-12-04T14:08:28-06:00', + issuer: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM', + type: ['VerifiableCredential', 'DomainLinkageCredential'] + } + }) + }) +})