Skip to content

Commit

Permalink
fix(credential-eip712): add support for all did methods that use secp…
Browse files Browse the repository at this point in the history
…256k (#1011)

fixes #991
  • Loading branch information
andyv09 committed Oct 3, 2022
1 parent 1b02e2a commit 9940068
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 17 deletions.
6 changes: 3 additions & 3 deletions packages/core/plugin.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3224,7 +3224,7 @@
"save": {
"type": "boolean",
"description": "Optional. If set to `true`, the message will be saved using\n {@link @veramo/core#IDataStore.dataStoreSaveMessage | dataStoreSaveMessage } \n<p/><p/>",
"deprecated": "Please call {@link @veramo/core#IDataStore.dataStoreSaveMessage | dataStoreSaveMessage()} after\nhandling the message and determining that it must be saved."
"deprecated": "Please call {@link @veramo/core#IDataStore.dataStoreSaveMessage | dataStoreSaveMessage()} after\r\nhandling the message and determining that it must be saved."
}
},
"required": [
Expand Down Expand Up @@ -3560,7 +3560,7 @@
"save": {
"type": "boolean",
"description": "If this parameter is true, the resulting VerifiablePresentation is sent to the\n {@link @veramo/core#IDataStore | storage plugin } to be saved.",
"deprecated": "Please call\n{@link @veramo/core#IDataStore.dataStoreSaveVerifiableCredential | dataStoreSaveVerifiableCredential()} to save\nthe credential after creating it."
"deprecated": "Please call\r\n{@link @veramo/core#IDataStore.dataStoreSaveVerifiableCredential | dataStoreSaveVerifiableCredential()} to save\r\nthe credential after creating it."
},
"proofFormat": {
"$ref": "#/components/schemas/ProofFormat",
Expand Down Expand Up @@ -3763,7 +3763,7 @@
"save": {
"type": "boolean",
"description": "If this parameter is true, the resulting VerifiablePresentation is sent to the\n {@link @veramo/core#IDataStore | storage plugin } to be saved. <p/><p/>",
"deprecated": "Please call\n{@link @veramo/core#IDataStore.dataStoreSaveVerifiablePresentation | dataStoreSaveVerifiablePresentation()} to\nsave the credential after creating it."
"deprecated": "Please call\r\n{@link @veramo/core#IDataStore.dataStoreSaveVerifiablePresentation | dataStoreSaveVerifiablePresentation()} to\r\nsave the credential after creating it."
},
"challenge": {
"type": "string",
Expand Down
4 changes: 2 additions & 2 deletions packages/credential-eip712/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
"dependencies": {
"@metamask/eth-sig-util": "^5.0.0",
"@veramo/core": "^4.0.0",
"@veramo/utils": "^4.0.0",
"debug": "^4.3.3",
"eip-712-types-generation": "^0.1.6"
"eip-712-types-generation": "^0.1.6",
"@veramo/utils": "^4.0.0"
},
"devDependencies": {
"@types/debug": "4.1.7",
Expand Down
9 changes: 6 additions & 3 deletions packages/credential-eip712/src/agent/CredentialEIP712.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ export class CredentialIssuerEIP712 implements IAgentPlugin {
if (!extendedKey)
throw Error('key_not_found: The signing key is not available in the issuer DID document')

const chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod)
let chainId = 1
if (identifier.did.split(':')[1] === 'ethr')
chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod)

const credential: CredentialPayload = {
...args?.credential,
Expand Down Expand Up @@ -235,8 +237,9 @@ export class CredentialIssuerEIP712 implements IAgentPlugin {
const extendedKey = extendedKeys.find((key) => key.kid === keyRef)
if (!extendedKey)
throw Error('key_not_found: The signing key is not available in the issuer DID document')

const chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod)
let chainId = 1
if (identifier.did.split(':')[1] === 'ethr')
chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod)
presentation['proof'] = {
verificationMethod: extendedKey.meta.verificationMethod.id,
created: issuanceDate,
Expand Down
2 changes: 1 addition & 1 deletion packages/did-comm/plugin.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@
"required": [
"data"
],
"deprecated": "Please use {@link IDIDComm.sendDIDCommMessage } instead. This will be removed in Veramo 4.0.\nInput arguments for {@link IDIDComm.sendMessageDIDCommAlpha1 }"
"deprecated": "Please use {@link IDIDComm.sendDIDCommMessage } instead. This will be removed in Veramo 4.0.\r\nInput arguments for {@link IDIDComm.sendMessageDIDCommAlpha1 }"
},
"IMessage": {
"type": "object",
Expand Down
4 changes: 2 additions & 2 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
"did-jwt-vc": "^3.1.0",
"did-resolver": "^4.0.0",
"uint8arrays": "^3.0.0",
"uuid": "^9.0.0"
"elliptic": "^6.5.4"
},
"devDependencies": {
"@types/debug": "4.1.7",
"@types/uuid": "8.3.4",
"typescript": "4.7.3"
"@types/elliptic": "6.4.14"
},
"files": [
"build/**/*",
Expand Down
53 changes: 47 additions & 6 deletions packages/utils/src/did-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
} from './types/utility-types'
import { isDefined } from './type-utils'
import * as u8a from 'uint8arrays'
import elliptic from 'elliptic'
import Debug from 'debug'
import { hexToBytes, bytesToHex, base64ToBytes, base58ToBytes } from './encodings'

const debug = Debug('veramo:utils')

Expand Down Expand Up @@ -80,11 +82,12 @@ export function compressIdentifierSecp256k1Keys(identifier: IIdentifier): IKey[]
*
* @beta This API may change without a BREAKING CHANGE notice.
*/
function compareBlockchainAccountId(
localKey: IKey,
verificationMethod: _NormalizedVerificationMethod,
): boolean {
if (verificationMethod.type !== 'EcdsaSecp256k1RecoveryMethod2020' || localKey.type !== 'Secp256k1') {
function compareBlockchainAccountId(localKey: IKey, verificationMethod: VerificationMethod): boolean {
if (
(verificationMethod.type !== 'EcdsaSecp256k1RecoveryMethod2020' &&
verificationMethod.type !== 'EcdsaSecp256k1RecoveryMethod2019') ||
localKey.type !== 'Secp256k1'
) {
return false
}
let vmEthAddr = getEthereumAddress(verificationMethod)
Expand All @@ -105,17 +108,55 @@ function compareBlockchainAccountId(
*
* @beta This API may change without a BREAKING CHANGE notice.
*/
export function getEthereumAddress(verificationMethod: _NormalizedVerificationMethod): string | undefined {
export function getEthereumAddress(verificationMethod: VerificationMethod): string | undefined {
let vmEthAddr = verificationMethod.ethereumAddress?.toLowerCase()
if (!vmEthAddr) {
if (verificationMethod.blockchainAccountId?.includes('@eip155')) {
vmEthAddr = verificationMethod.blockchainAccountId?.split('@eip155')[0].toLowerCase()
} else if (verificationMethod.blockchainAccountId?.startsWith('eip155')) {
vmEthAddr = verificationMethod.blockchainAccountId.split(':')[2]?.toLowerCase()
} else if (
verificationMethod.publicKeyHex ||
verificationMethod.publicKeyBase58 ||
verificationMethod.publicKeyBase64
) {
const pbBytes = extractPublicKeyBytes(verificationMethod)
const pbHex = computePublicKey(pbBytes, false)

vmEthAddr = computeAddress(pbHex).toLowerCase()
}
}
return vmEthAddr
}
interface LegacyVerificationMethod extends VerificationMethod {
publicKeyBase64: string
}

function extractPublicKeyBytes(pk: VerificationMethod): Uint8Array {
if (pk.publicKeyBase58) {
return base58ToBytes(pk.publicKeyBase58)
} else if ((<LegacyVerificationMethod>pk).publicKeyBase64) {
return base64ToBytes((<LegacyVerificationMethod>pk).publicKeyBase64)
} else if (pk.publicKeyHex) {
return hexToBytes(pk.publicKeyHex)
} else if (
pk.publicKeyJwk &&
pk.publicKeyJwk.crv === 'secp256k1' &&
pk.publicKeyJwk.x &&
pk.publicKeyJwk.y
) {
const secp256k1 = new elliptic.ec('secp256k1')
return hexToBytes(
secp256k1
.keyFromPublic({
x: bytesToHex(base64ToBytes(pk.publicKeyJwk.x)),
y: bytesToHex(base64ToBytes(pk.publicKeyJwk.y)),
})
.getPublic('hex'),
)
}
return new Uint8Array()
}

/**
* Extracts the chain ID from a {@link did-resolver#VerificationMethod | verification method} supporting legacy
Expand Down
13 changes: 13 additions & 0 deletions packages/utils/src/encodings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,16 @@ export function bytesToHex(byteArray: Uint8Array, prefix: boolean = false): stri
const result = u8a.toString(byteArray, 'base16')
return prefix ? `0x${result}` : result
}

/**
* Converts a base58 string to the Uint8Array it represents.
*
* @param s - the string to be converted
*
* @throws if the string is not formatted correctly.
*
* @public
*/
export function base58ToBytes(s: string): Uint8Array {
return u8a.fromString(s, 'base58btc')
}
14 changes: 14 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4645,6 +4645,13 @@
dependencies:
"@types/node" "*"

"@types/bn.js@*":
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682"
integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==
dependencies:
"@types/node" "*"

"@types/bn.js@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
Expand Down Expand Up @@ -4704,6 +4711,13 @@
dependencies:
"@types/ms" "*"

"@types/elliptic@6.4.14":
version "6.4.14"
resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.14.tgz#7bbaad60567a588c1f08b10893453e6b9b4de48e"
integrity sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ==
dependencies:
"@types/bn.js" "*"

"@types/eslint-scope@^3.7.3":
version "3.7.3"
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
Expand Down

0 comments on commit 9940068

Please sign in to comment.