Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(credential-eip712): add support for all did methods that use secp256k #1011

Merged
merged 6 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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": "^4.0.1",
"@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
6 changes: 4 additions & 2 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
"did-jwt-vc": "^3.1.0",
"did-resolver": "^4.0.0",
"uint8arrays": "^3.0.0",
"uuid": "^8.3.0"
"uuid": "^8.3.0",
"elliptic": "^6.5.4"
},
"devDependencies": {
"@types/debug": "4.1.7",
"@types/uuid": "8.3.4",
"typescript": "4.7.3"
"typescript": "4.7.3",
"@types/elliptic": "6.4.14"
},
"files": [
"build/**/*",
Expand Down
55 changes: 49 additions & 6 deletions packages/utils/src/did-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import {
} from './types/utility-types'
import { isDefined } from './type-utils'
import * as u8a from 'uint8arrays'
import elliptic from 'elliptic'
import Debug from 'debug'
import sha3 from 'js-sha3'
import { publicKeyConvert } from 'secp256k1'
mirceanis marked this conversation as resolved.
Show resolved Hide resolved
import { hexToBytes, bytesToHex, base64ToBytes, base58ToBytes } from './encodings'

const debug = Debug('veramo:utils')

Expand Down Expand Up @@ -80,11 +84,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 +110,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 @@ -4594,6 +4594,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@^4.11.3":
version "4.11.6"
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
Expand Down Expand Up @@ -4660,6 +4667,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