@tanglelabs/resolver-did-key
Version:
Fork of Sphereon did:key resolver with BBS+/BLS and EBSI support.
116 lines (109 loc) • 3.91 kB
text/typescript
import * as u8a from 'uint8arrays'
import { DIDDocument } from 'did-resolver'
// import { edwardsToMontgomery } from '@noble/curves/ed25519'
import { convertPublicKeyToX25519 } from '@stablelib/ed25519'
import { DID_LD_JSON, KeyToDidDocArgs } from '../types'
function encodeKey(key: Uint8Array, encodeKey?: number) {
const bytes = new Uint8Array(key.length + 2)
bytes[0] = encodeKey ?? 0xec
// The multicodec is encoded as a varint so we need to add this.
// See js-multicodec for a general implementation
bytes[1] = 0x01
bytes.set(key, 2)
return `z${u8a.toString(bytes, 'base58btc')}`
}
export const keyToDidDoc = (args: KeyToDidDocArgs) => {
const { options } = args
if (!options?.publicKeyFormat) {
return keyToDidDoc2020(args)
}
switch (options.publicKeyFormat) {
case 'Ed25519VerificationKey2018':
case 'X25519KeyAgreementKey2019':
return keyToDidDoc2018_2019(args)
case 'Ed25519VerificationKey2020':
case 'X25519KeyAgreementKey2020':
case 'Multikey':
return keyToDidDoc2020(args)
default:
throw Error(`${options.publicKeyFormat} not supported yet for the ed25519 driver`)
}
}
const keyToDidDoc2018_2019 = ({ pubKeyBytes, fingerprint, contentType }: KeyToDidDocArgs): DIDDocument => {
const did = `did:key:${fingerprint}`
const keyId = `${did}#${fingerprint}`
//todo: Move to noble lib. x25519 values differ between below methods. Current implementation is correct according to DID:key spec
// const pubKeyHex = u8a.toString(pubKeyBytes, 'base16')
// const x25519PubBytes = edwardsToMontgomery(pubKeyHex)
const x25519PubBytes = convertPublicKeyToX25519(pubKeyBytes)
const x25519KeyId = `${did}#${encodeKey(x25519PubBytes)}`
return {
...(contentType === DID_LD_JSON && {
'@context': [
'https://www.w3.org/ns/did/v1',
'https://w3id.org/security/suites/ed25519-2018/v1',
'https://w3id.org/security/suites/x25519-2019/v1',
],
}),
id: did,
verificationMethod: [
{
id: keyId,
type: 'Ed25519VerificationKey2018',
controller: did,
publicKeyBase58: u8a.toString(pubKeyBytes, 'base58btc'),
},
{
id: x25519KeyId,
type: 'X25519KeyAgreementKey2019',
controller: did,
publicKeyBase58: u8a.toString(x25519PubBytes, 'base58btc'),
},
],
authentication: [keyId],
assertionMethod: [keyId],
capabilityDelegation: [keyId],
capabilityInvocation: [keyId],
keyAgreement: [x25519KeyId],
}
}
const keyToDidDoc2020 = ({ pubKeyBytes, fingerprint, contentType }: KeyToDidDocArgs): DIDDocument => {
const did = `did:key:${fingerprint}`
const keyId = `${did}#${fingerprint}`
//todo: Move to noble lib. x25519 values differ between below methods. Current implementation is correct according to DID:key spec
// const pubKeyHex = u8a.toString(pubKeyBytes, 'base16')
// const x25519PubBytes = edwardsToMontgomery(pubKeyBytes)
const x25519PubBytes = convertPublicKeyToX25519(pubKeyBytes)
const x25519KeyId = `${did}#${encodeKey(x25519PubBytes)}`
return {
...(contentType === DID_LD_JSON && {
'@context': [
'https://www.w3.org/ns/did/v1',
'https://w3id.org/security/suites/ed25519-2020/v1',
'https://w3id.org/security/suites/x25519-2020/v1',
],
}),
id: did,
verificationMethod: [
{
id: keyId,
type: 'Ed25519VerificationKey2020',
controller: did,
publicKeyMultibase: encodeKey(pubKeyBytes, 0xed),
},
],
authentication: [keyId],
assertionMethod: [keyId],
capabilityDelegation: [keyId],
capabilityInvocation: [keyId],
keyAgreement: [
{
id: x25519KeyId,
type: 'X25519KeyAgreementKey2020',
controller: did,
publicKeyMultibase: encodeKey(x25519PubBytes, 0xec),
},
],
}
}
export default { keyToDidDoc }