From a221a838b257eb52519879ba9a145b8c25439e64 Mon Sep 17 00:00:00 2001 From: AdriGeorge Date: Wed, 20 Nov 2024 13:53:18 +0200 Subject: [PATCH] fix: types --- src/@types/IssuerSignature.ts | 59 ++++++++++++++++++++++++----------- src/utils/SignDDO.ts | 32 ++++++------------- test/unit/SignDDO.test.ts | 31 +++++++++++++++--- 3 files changed, 78 insertions(+), 44 deletions(-) diff --git a/src/@types/IssuerSignature.ts b/src/@types/IssuerSignature.ts index 32ec7aa8c..36b50a046 100644 --- a/src/@types/IssuerSignature.ts +++ b/src/@types/IssuerSignature.ts @@ -1,28 +1,51 @@ +/** + * Represents a JSON Web Token (JWT) used in cryptographic operations. + */ export interface JWT { - kty: string - d: string - crv: string - kid: string - x: string + kty: string // Key type (e.g., 'EC' for Elliptic Curve) + d: string // Private key (base64url encoded) + crv: string // Cryptographic curve (e.g., 'secp256k1') + kid: string // Key ID + x: string // X-coordinate of the public key (base64url encoded) } +/** + * Represents a key used by an issuer to sign credentials. + */ export interface IssuerKey { - type: string - jwk: JWT + type: string // Type of the key (e.g., 'JWK') + jwk: JWT // The JSON Web Token associated with the issuer's key } +/** + * Represents the result of signing a credential. + */ export interface SignedCredential { - jws: string - header: Record - issuer: string + jws: string // JSON Web Signature (JWS) of the credential + header: Record // Protected header used in the JWS + issuer: string // DID or public key of the issuer } -export interface IssuerKeyJWK { - kty: string - crv: string - d: string - x: string - y: string - alg: string - use: string +/** + * Represents the common properties of a JSON Web Key (JWK). + */ +interface BaseJWK { + kty: string // Key type (e.g., 'EC' for Elliptic Curve) + crv: string // Cryptographic curve (e.g., 'secp256k1') + x: string // X-coordinate of the public key (base64url encoded) + y: string // Y-coordinate of the public key (base64url encoded) + alg: string // Algorithm used (e.g., 'ES256K') + use: string // Intended use of the key (e.g., 'sig' for signing) } + +/** + * Represents a JSON Web Key (JWK) for private signing operations. + */ +export interface IssuerKeyJWK extends BaseJWK { + d: string // Private key (base64url encoded) +} + +/** + * Represents a JSON Web Key (JWK) for public verification operations. + */ +export interface IssuerPublicKeyJWK extends BaseJWK {} diff --git a/src/utils/SignDDO.ts b/src/utils/SignDDO.ts index d0553862b..e0247093e 100644 --- a/src/utils/SignDDO.ts +++ b/src/utils/SignDDO.ts @@ -1,6 +1,11 @@ -import { base64url, importJWK, JWTPayload, jwtVerify, SignJWT } from 'jose' +import { importJWK, JWTPayload, jwtVerify, SignJWT } from 'jose' import axios from 'axios' -import { IssuerKey, IssuerKeyJWK, SignedCredential } from '../@types/IssuerSignature' +import { + IssuerKey, + IssuerKeyJWK, + IssuerPublicKeyJWK, + SignedCredential +} from '../@types/IssuerSignature' /** * Signs a verifiable credential using Walt.id's issuer API. @@ -66,32 +71,15 @@ export async function signCredential( /** * Verifies a verifiable credential's JWS using the issuer's public key. * @param {string} jws - The JSON Web Signature (JWS) to verify. - * @param {string} issuerPublicKey - The public key of the issuer in hexadecimal format. + * @param {IssuerPublicKeyJWK} issuerPublicKeyJWK - The public key JWK of the issuer. * @returns {Promise} - The verified payload of the credential. * @throws {Error} If the verification fails. */ export async function verifyCredential( jws: string, - issuerPublicKey: string + issuerPublicKeyJWK: IssuerPublicKeyJWK ): Promise { - const publicKeyBuffer = Buffer.from(issuerPublicKey.substring(2), 'hex') - const xBuffer = publicKeyBuffer.slice(1, 33) - const yBuffer = publicKeyBuffer.slice(33, 65) - - const x = base64url.encode(xBuffer as any as Uint8Array) - const y = base64url.encode(yBuffer as any as Uint8Array) - - const publicJwk = { - kty: 'EC', - crv: 'secp256k1', - x, - y, - alg: 'ES256K', - use: 'sig' - } - - const key = await importJWK(publicJwk, 'ES256K') - + const key = await importJWK(issuerPublicKeyJWK, 'ES256K') try { const { payload } = await jwtVerify(jws, key) return payload diff --git a/test/unit/SignDDO.test.ts b/test/unit/SignDDO.test.ts index ad7737d80..6248939c5 100644 --- a/test/unit/SignDDO.test.ts +++ b/test/unit/SignDDO.test.ts @@ -2,7 +2,7 @@ import { assert } from 'chai' import { ethers } from 'ethers' import { base64url } from 'jose' import { signCredential, verifyCredential } from '../../src/utils' -import { IssuerKeyJWK } from '../../src/@types/IssuerSignature' +import { IssuerKeyJWK, IssuerPublicKeyJWK } from '../../src/@types/IssuerSignature' const mockVerifiableCredential = { '@context': ['https://www.w3.org/2018/credentials/v1'], @@ -18,7 +18,6 @@ describe('Credential Signing and Verification Functions', () => { const privateKey = '0xc494c6e5def4bab63ac29eed19a134c130355f74f019bc74b8f4389df2837a57' const wallet = new ethers.Wallet(privateKey) - const { publicKey } = wallet._signingKey() const privateKeyBuffer = Buffer.from(privateKey.substring(2), 'hex') const publicKeyHex = wallet._signingKey().publicKey const publicKeyBuffer = Buffer.from(publicKeyHex.substring(2), 'hex') @@ -44,7 +43,16 @@ describe('Credential Signing and Verification Functions', () => { publicKeyHex ) - const payload = await verifyCredential(jws, publicKey) + const publicJwk = { + kty: 'EC', + crv: 'secp256k1', + x, + y, + alg: 'ES256K', + use: 'sig' + } + + const payload = await verifyCredential(jws, publicJwk) assert.deepEqual( { type: payload.type, @@ -95,8 +103,23 @@ describe('Credential Signing and Verification Functions', () => { publicKey ) + const invalidPublicKeyBuffer = Buffer.from(invalidPublicKey.substring(2), 'hex') + const invalidXBuffer = invalidPublicKeyBuffer.slice(1, 33) + const invalidYBuffer = invalidPublicKeyBuffer.slice(33, 65) + + const invalidX = base64url.encode(invalidXBuffer as any as Uint8Array) + const invalidY = base64url.encode(invalidYBuffer as any as Uint8Array) + const publicJwk: IssuerPublicKeyJWK = { + kty: 'EC', + crv: 'secp256k1', + x: invalidX, + y: invalidY, + alg: 'ES256K', + use: 'sig' + } + try { - await verifyCredential(jws, invalidPublicKey) + await verifyCredential(jws, publicJwk) assert.fail('Expected error to be thrown') } catch (error) { assert.include(