did-jwt
Version:
Library for Signing and Verifying JWTs that use DIDs as issuers and JWEs that use DIDs as recipients
489 lines (438 loc) • 13.6 kB
text/typescript
import MockDate from 'mockdate'
import { createMultisignatureJWT, verifyJWT } from '../JWT.js'
// add declarations for ES256 Tests
import { createResolver, createSigner } from './ConditionalAlgorithmResolverHelper.js'
import { PrivateKey } from '@greymass/eosio'
import { JWT_ERROR } from '../Errors.js'
const NOW = 1485321133
MockDate.set(NOW * 1000 + 123)
const account = 'jack'
const network = 'eos'
const did = `did:antelope:${network}:${account}`
export const privateKeys = [
'5JAJ7BfYKdRnrSQCsdcBqrCcBVQQSuQ77fuRAJ5fcbQ3UDhuLLZ',
'5JcKy5rAp4rTnE9za1CNm5xBG4DnJ2T29cYpz87kRVRdQqv1K8x',
'5JibpxxNpkqdejc38KD9xZF3fKHtTUonKCAYiZbwNPsgoKbw6FQ',
'5KFVyCULqHQ82PCvCpCa4XGzTs8SGrRnts8t9LQMsv7hiCp7oBq',
'5JQ8U8WS2isz3fiCXcFyZyiPfUXB4PXwDUK5tvWiqLAmUyqaXpe',
]
const publicKeys = privateKeys.map((privKey) => {
return PrivateKey.from(privKey).toPublic().toString()
})
describe('createMultisignatureJWT()', () => {
describe('ConditionalProof - multisignature', () => {
it('creates a valid signed JWT that satisfies 1 of 1 signature', async () => {
expect.assertions(2)
const issuers = [
{
issuer: did,
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 1 verification method that requires 1 of 1 signatures
const resolver = createResolver({
threshold: 1,
keys: [publicKeys[0]].map((key) => {
return { key, weight: 1 }
}),
accounts: [],
})
const verified = await verifyJWT(jwt, { resolver })
expect(verified.verified).toBe(true)
expect(verified.payload.requested).toEqual(['name', 'phone'])
})
it('creates a valid signed JWT that satisfies 2 of 2 signature', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did,
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
{
issuer: did,
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 1 verification method that requires 2 of 2 signatures
const resolver = createResolver({
threshold: 2,
keys: [publicKeys[0], publicKeys[1]].map((key) => {
return { key, weight: 1 }
}),
accounts: [],
})
const verified = await verifyJWT(jwt, { resolver })
expect(verified.verified).toBe(true)
})
it('creates a valid signed JWT that satisfies 2 of 3 signature', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did,
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
{
issuer: did,
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 1 verification method that requires 2 of 3 signatures
const resolver = createResolver({
threshold: 2,
keys: [publicKeys[0], publicKeys[1], publicKeys[2]].map((key) => {
return { key, weight: 1 }
}),
accounts: [],
})
const verified = await verifyJWT(jwt, { resolver })
expect(verified.verified).toBe(true)
})
it('creates a valid signed JWT with only one signature that fails to satisfy 2 of 3 signature', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did,
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 1 verification method that requires 2 of 3 signatures
const resolver = createResolver({
threshold: 2,
keys: [publicKeys[0], publicKeys[1], publicKeys[2]].map((key) => {
return { key, weight: 1 }
}),
accounts: [],
})
await expect(verifyJWT(jwt, { resolver })).rejects.toThrow(JWT_ERROR.INVALID_SIGNATURE)
})
})
describe('ConditionalProof - delegated signatures', () => {
it('creates a valid signed JWT that satisfies 1 delegation', async () => {
expect.assertions(2)
const issuers = [
{
issuer: did + '#permission1',
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 2 verification methods
// - one that requires 1 of 1 signatures
// - one that delegates to the first
const resolver = createResolver([
{
threshold: 1,
keys: [
{
key: publicKeys[0],
weight: 1,
},
],
accounts: [],
},
{
threshold: 1,
keys: [],
accounts: [
{
permission: {
permission: 'permission0',
actor: account,
},
weight: 1,
},
],
},
])
const verified = await verifyJWT(jwt, { resolver })
expect(verified.verified).toBe(true)
expect(verified.signer.id).toBe(did + '#permission1')
})
it('creates a valid signed JWT that fails satisfies 1 delegation when the signing key is incorrect', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did,
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 2 verification methods
// - one that requires 1 of 1 signatures
// - one that delegates to the first
const resolver = createResolver([
{
threshold: 1,
keys: [
{
key: publicKeys[0],
weight: 1,
},
],
accounts: [],
},
{
threshold: 1,
keys: [],
accounts: [
{
permission: {
permission: 'permission0',
actor: account,
},
weight: 1,
},
],
},
])
await expect(verifyJWT(jwt, { resolver })).rejects.toThrow(JWT_ERROR.INVALID_SIGNATURE)
})
})
describe('ConditionalProof - combination key and delegated signatures', () => {
it('creates a valid signed JWT that satisfies 3 threshold and 2 keys and 2 delegated signature check', async () => {
expect.assertions(2)
const issuers = [
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[2]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 3 verification methods
// - one of 3 threshold with 2 signature (privateKey[0] and privateKey[1]) and 2 delegations to the 2nd and 3rd verification method
// - one with 1 signature requirement of privateKey[2]
// - one with 1 signature requirement of privateKey[3]
const resolver = createResolver([
{
threshold: 3,
keys: [
{
key: publicKeys[0],
weight: 1,
},
{
key: publicKeys[1],
weight: 1,
},
],
accounts: [
{
permission: {
permission: 'permission1',
actor: account,
},
weight: 1,
},
{
permission: {
permission: 'permission2',
actor: account,
},
weight: 1,
},
],
},
{
threshold: 1,
keys: [
{
key: publicKeys[2],
weight: 1,
},
],
accounts: [],
},
{
threshold: 1,
keys: [
{
key: publicKeys[3],
weight: 1,
},
],
accounts: [],
},
])
const verified = await verifyJWT(jwt, { resolver })
expect(verified.verified).toBe(true)
expect(verified.signer.id).toBe(did + '#permission0')
})
it('creates a valid signed JWT that fails satisfies 3 threshold and 2 keys and 2 delegated signature check, with a bad key', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[4]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[2]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 3 verification methods
// - one of 3 threshold with 2 signature (privateKey[0] and privateKey[1]) and 2 delegations to the 2nd and 3rd verification method
// - one with 1 signature requirement of privateKey[2]
// - one with 1 signature requirement of privateKey[3]
const resolver = createResolver([
{
threshold: 3,
keys: [
{
key: publicKeys[0],
weight: 1,
},
{
key: publicKeys[1],
weight: 1,
},
],
accounts: [
{
permission: {
permission: 'permission1',
actor: account,
},
weight: 1,
},
{
permission: {
permission: 'permission2',
actor: account,
},
weight: 1,
},
],
},
{
threshold: 1,
keys: [
{
key: publicKeys[2],
weight: 1,
},
],
accounts: [],
},
{
threshold: 1,
keys: [
{
key: publicKeys[3],
weight: 1,
},
],
accounts: [],
},
])
await expect(verifyJWT(jwt, { resolver })).rejects.toThrow(JWT_ERROR.INVALID_SIGNATURE)
})
it('creates a valid signed JWT that fails satisfies 3 threshold and 2 keys and 2 delegated signature check, with a bad delegate', async () => {
expect.assertions(1)
const issuers = [
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[0]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[1]),
alg: 'ES256K-R',
},
{
issuer: did + '#permission0',
signer: createSigner(privateKeys[4]),
alg: 'ES256K-R',
},
]
const jwt = await createMultisignatureJWT({ requested: ['name', 'phone'] }, {}, issuers)
// resolves to a DID Document with 3 verification methods
// - one of 3 threshold with 2 signature (privateKey[0] and privateKey[1]) and 2 delegations to the 2nd and 3rd verification method
// - one with 1 signature requirement of privateKey[2]
// - one with 1 signature requirement of privateKey[3]
const resolver = createResolver([
{
threshold: 3,
keys: [
{
key: publicKeys[0],
weight: 1,
},
{
key: publicKeys[1],
weight: 1,
},
],
accounts: [
{
permission: {
permission: 'permission1',
actor: account,
},
weight: 1,
},
{
permission: {
permission: 'permission2',
actor: account,
},
weight: 1,
},
],
},
{
threshold: 1,
keys: [
{
key: publicKeys[2],
weight: 1,
},
],
accounts: [],
},
{
threshold: 1,
keys: [
{
key: publicKeys[3],
weight: 1,
},
],
accounts: [],
},
])
await expect(verifyJWT(jwt, { resolver })).rejects.toThrow(JWT_ERROR.INVALID_SIGNATURE)
})
})
})