Skip to content

Commit

Permalink
feat: add support for secp256k1 publicKeyJwk (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
yhuard authored Apr 22, 2021
1 parent d4c0906 commit 1d578ba
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
9 changes: 9 additions & 0 deletions src/VerifierAlgorithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ function extractPublicKeyBytes(pk: VerificationMethod): Uint8Array {
return base64ToBytes((<LegacyVerificationMethod>pk).publicKeyBase64)
} else if (pk.publicKeyHex) {
return hexToBytes(pk.publicKeyHex)
} else if (pk.publicKeyJwk && pk.publicKeyJwk.crv === 'secp256k1') {
return hexToBytes(
secp256k1
.keyFromPublic({
x: bytesToHex(base64ToBytes(pk.publicKeyJwk.x)),
y: bytesToHex(base64ToBytes(pk.publicKeyJwk.y))
})
.getPublic('hex')
)
}
return new Uint8Array()
}
Expand Down
26 changes: 25 additions & 1 deletion src/__tests__/VerifierAlgorithm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createJWT } from '../JWT'
import { toEthereumAddress } from '../Digest'
import nacl from 'tweetnacl'
import { ec as EC } from 'elliptic'
import { base64ToBytes, bytesToBase58, bytesToBase64, hexToBytes } from '../util'
import { base64ToBytes, bytesToBase58, bytesToBase64, hexToBytes, bytesToBase64url } from '../util'
import * as u8a from 'uint8arrays'
import { EdDSASigner } from '../signers/EdDSASigner'
import { ES256KSigner } from '../signers/ES256KSigner'
Expand Down Expand Up @@ -36,6 +36,12 @@ const publicKey = String(kp.getPublic('hex'))
const compressedPublicKey = String(kp.getPublic().encode('hex', true))
const publicKeyBase64 = bytesToBase64(hexToBytes(publicKey))
const publicKeyBase58 = bytesToBase58(hexToBytes(publicKey))
const publicKeyJwk = {
crv: 'secp256k1',
kty: 'EC',
x: bytesToBase64url(hexToBytes(kp.getPublic().getX().toString('hex'))),
y: bytesToBase64url(hexToBytes(kp.getPublic().getY().toString('hex')))
}
const address = toEthereumAddress(publicKey)
const signer = ES256KSigner(privateKey)
const recoverySigner = ES256KSigner(privateKey, true)
Expand Down Expand Up @@ -154,6 +160,15 @@ describe('ES256K', () => {
return expect(verifier(parts[1], parts[2], [pubkey])).toEqual(pubkey)
})

it('validates with publicKeyJwk', async () => {
expect.assertions(1)
const jwt = await createJWT({ bla: 'bla' }, { issuer: did, signer })
const parts = jwt.match(/^([a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/)
const pubkey = Object.assign({ publicKeyJwk }, ecKey2)
delete pubkey.publicKeyHex
return expect(verifier(parts[1], parts[2], [pubkey])).toEqual(pubkey)
})

it('validates signature with compressed public key and picks correct public key', async () => {
expect.assertions(1)
const jwt = await createJWT({ bla: 'bla' }, { issuer: did, signer })
Expand Down Expand Up @@ -261,6 +276,15 @@ describe('ES256K-R', () => {
return expect(verifier(parts[1], parts[2], [pubkey])).toEqual(pubkey)
})

it('validates with publicKeyJwk', async () => {
expect.assertions(1)
const jwt = await createJWT({ bla: 'bla' }, { issuer: did, signer: recoverySigner, alg: 'ES256K-R' })
const parts = jwt.match(/^([a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+)\.([a-zA-Z0-9_-]+)$/)
const pubkey = Object.assign({ publicKeyJwk }, ecKey2)
delete pubkey.publicKeyHex
return expect(verifier(parts[1], parts[2], [pubkey])).toEqual(pubkey)
})

it('throws error if invalid signature', async () => {
expect.assertions(1)
const jwt = await createJWT({ bla: 'bla' }, { issuer: did, signer: recoverySigner, alg: 'ES256K-R' })
Expand Down

0 comments on commit 1d578ba

Please sign in to comment.