@veramo/credential-eip712
Advanced tools
Comparing version 4.3.1-next.4 to 4.3.1-next.7
@@ -10,3 +10,345 @@ import { IAgentPlugin, VerifiableCredential, VerifiablePresentation } from '@veramo/core'; | ||
readonly methods: ICredentialIssuerEIP712; | ||
readonly schema: any; | ||
readonly schema: { | ||
components: { | ||
schemas: { | ||
ICreateVerifiableCredentialEIP712Args: { | ||
type: string; | ||
properties: { | ||
credential: { | ||
$ref: string; | ||
description: string; | ||
}; | ||
keyRef: { | ||
type: string; | ||
description: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
CredentialPayload: { | ||
type: string; | ||
properties: { | ||
issuer: { | ||
$ref: string; | ||
}; | ||
credentialSubject: { | ||
$ref: string; | ||
}; | ||
type: { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
"@context": { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
issuanceDate: { | ||
$ref: string; | ||
}; | ||
expirationDate: { | ||
$ref: string; | ||
}; | ||
credentialStatus: { | ||
$ref: string; | ||
}; | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
IssuerType: { | ||
anyOf: ({ | ||
type: string; | ||
properties: { | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
} | { | ||
type: string; | ||
properties?: undefined; | ||
required?: undefined; | ||
})[]; | ||
description: string; | ||
}; | ||
CredentialSubject: { | ||
type: string; | ||
properties: { | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
description: string; | ||
}; | ||
DateType: { | ||
type: string; | ||
description: string; | ||
}; | ||
CredentialStatusReference: { | ||
type: string; | ||
properties: { | ||
id: { | ||
type: string; | ||
}; | ||
type: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
VerifiableCredential: { | ||
type: string; | ||
properties: { | ||
proof: { | ||
$ref: string; | ||
}; | ||
issuer: { | ||
$ref: string; | ||
}; | ||
credentialSubject: { | ||
$ref: string; | ||
}; | ||
type: { | ||
anyOf: ({ | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
} | { | ||
type: string; | ||
items?: undefined; | ||
})[]; | ||
}; | ||
"@context": { | ||
anyOf: ({ | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
} | { | ||
type: string; | ||
items?: undefined; | ||
})[]; | ||
}; | ||
issuanceDate: { | ||
type: string; | ||
}; | ||
expirationDate: { | ||
type: string; | ||
}; | ||
credentialStatus: { | ||
$ref: string; | ||
}; | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
ProofType: { | ||
type: string; | ||
properties: { | ||
type: { | ||
type: string; | ||
}; | ||
}; | ||
description: string; | ||
}; | ||
ICreateVerifiablePresentationEIP712Args: { | ||
type: string; | ||
properties: { | ||
presentation: { | ||
$ref: string; | ||
description: string; | ||
}; | ||
keyRef: { | ||
type: string; | ||
description: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
PresentationPayload: { | ||
type: string; | ||
properties: { | ||
holder: { | ||
type: string; | ||
}; | ||
verifiableCredential: { | ||
type: string; | ||
items: { | ||
$ref: string; | ||
}; | ||
}; | ||
type: { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
"@context": { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
verifier: { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
issuanceDate: { | ||
$ref: string; | ||
}; | ||
expirationDate: { | ||
$ref: string; | ||
}; | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
W3CVerifiableCredential: { | ||
anyOf: { | ||
$ref: string; | ||
}[]; | ||
description: string; | ||
}; | ||
CompactJWT: { | ||
type: string; | ||
description: string; | ||
}; | ||
VerifiablePresentation: { | ||
type: string; | ||
properties: { | ||
proof: { | ||
$ref: string; | ||
}; | ||
holder: { | ||
type: string; | ||
}; | ||
verifiableCredential: { | ||
type: string; | ||
items: { | ||
$ref: string; | ||
}; | ||
}; | ||
type: { | ||
anyOf: ({ | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
} | { | ||
type: string; | ||
items?: undefined; | ||
})[]; | ||
}; | ||
"@context": { | ||
anyOf: ({ | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
} | { | ||
type: string; | ||
items?: undefined; | ||
})[]; | ||
}; | ||
verifier: { | ||
type: string; | ||
items: { | ||
type: string; | ||
}; | ||
}; | ||
issuanceDate: { | ||
type: string; | ||
}; | ||
expirationDate: { | ||
type: string; | ||
}; | ||
id: { | ||
type: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
IVerifyCredentialEIP712Args: { | ||
type: string; | ||
properties: { | ||
credential: { | ||
$ref: string; | ||
description: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
IVerifyPresentationEIP712Args: { | ||
type: string; | ||
properties: { | ||
presentation: { | ||
$ref: string; | ||
description: string; | ||
}; | ||
}; | ||
required: string[]; | ||
description: string; | ||
}; | ||
}; | ||
methods: { | ||
createVerifiableCredentialEIP712: { | ||
description: string; | ||
arguments: { | ||
$ref: string; | ||
}; | ||
returnType: { | ||
$ref: string; | ||
}; | ||
}; | ||
createVerifiablePresentationEIP712: { | ||
description: string; | ||
arguments: { | ||
$ref: string; | ||
}; | ||
returnType: { | ||
$ref: string; | ||
}; | ||
}; | ||
verifyCredentialEIP712: { | ||
description: string; | ||
arguments: { | ||
$ref: string; | ||
}; | ||
returnType: { | ||
type: string; | ||
}; | ||
}; | ||
verifyPresentationEIP712: { | ||
description: string; | ||
arguments: { | ||
$ref: string; | ||
}; | ||
returnType: { | ||
type: string; | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
constructor(); | ||
@@ -13,0 +355,0 @@ /** {@inheritdoc ICredentialIssuerEIP712.createVerifiableCredentialEIP712} */ |
@@ -1,28 +0,5 @@ | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __rest = (this && this.__rest) || function (s, e) { | ||
var t = {}; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) | ||
t[p] = s[p]; | ||
if (s != null && typeof Object.getOwnPropertySymbols === "function") | ||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { | ||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) | ||
t[p[i]] = s[p[i]]; | ||
} | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CredentialIssuerEIP712 = void 0; | ||
const utils_1 = require("@veramo/utils"); | ||
const index_1 = require("../index"); | ||
const eth_sig_util_1 = require("@metamask/eth-sig-util"); | ||
const eip_712_types_generation_1 = require("eip-712-types-generation"); | ||
import { extractIssuer, getChainIdForDidEthr, getEthereumAddress, isDefined, MANDATORY_CREDENTIAL_CONTEXT, mapIdentifierKeysToDoc, processEntryToArray, resolveDidOrThrow, } from '@veramo/utils'; | ||
import schema from "../plugin.schema.json" assert { type: 'json' }; | ||
import { recoverTypedSignature, SignTypedDataVersion } from '@metamask/eth-sig-util'; | ||
import { getEthTypesFromInputDoc } from 'eip-712-types-generation'; | ||
/** | ||
@@ -33,5 +10,6 @@ * A Veramo plugin that implements the {@link ICredentialIssuerEIP712} methods. | ||
*/ | ||
class CredentialIssuerEIP712 { | ||
export class CredentialIssuerEIP712 { | ||
methods; | ||
schema = schema.ICredentialIssuerEIP712; | ||
constructor() { | ||
this.schema = index_1.schema.ICredentialIssuerEIP712; | ||
this.methods = { | ||
@@ -45,215 +23,219 @@ createVerifiableCredentialEIP712: this.createVerifiableCredentialEIP712.bind(this), | ||
/** {@inheritdoc ICredentialIssuerEIP712.createVerifiableCredentialEIP712} */ | ||
createVerifiableCredentialEIP712(args, context) { | ||
var _a, _b, _c; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const credentialContext = (0, utils_1.processEntryToArray)((_a = args === null || args === void 0 ? void 0 : args.credential) === null || _a === void 0 ? void 0 : _a['@context'], utils_1.MANDATORY_CREDENTIAL_CONTEXT); | ||
const credentialType = (0, utils_1.processEntryToArray)((_b = args === null || args === void 0 ? void 0 : args.credential) === null || _b === void 0 ? void 0 : _b.type, 'VerifiableCredential'); | ||
let issuanceDate = ((_c = args === null || args === void 0 ? void 0 : args.credential) === null || _c === void 0 ? void 0 : _c.issuanceDate) || new Date().toISOString(); | ||
if (issuanceDate instanceof Date) { | ||
issuanceDate = issuanceDate.toISOString(); | ||
} | ||
const issuer = (0, utils_1.extractIssuer)(args.credential); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: credential.issuer must not be empty'); | ||
} | ||
let keyRef = args.keyRef; | ||
const identifier = yield context.agent.didManagerGet({ did: issuer }); | ||
if (!keyRef) { | ||
const key = identifier.keys.find((k) => { var _a, _b; return k.type === 'Secp256k1' && ((_b = (_a = k.meta) === null || _a === void 0 ? void 0 : _a.algorithms) === null || _b === void 0 ? void 0 : _b.includes('eth_signTypedData')); }); | ||
if (!key) | ||
throw Error('key_not_found: No suitable signing key is known for ' + identifier.did); | ||
keyRef = key.kid; | ||
} | ||
const extendedKeys = yield (0, utils_1.mapIdentifierKeysToDoc)(identifier, 'verificationMethod', context); | ||
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'); | ||
let chainId = 1; | ||
if (identifier.did.split(':')[1] === 'ethr') | ||
chainId = (0, utils_1.getChainIdForDidEthr)(extendedKey.meta.verificationMethod); | ||
const credential = Object.assign(Object.assign({}, args === null || args === void 0 ? void 0 : args.credential), { '@context': credentialContext, type: credentialType, issuanceDate, proof: { | ||
verificationMethod: extendedKey.meta.verificationMethod.id, | ||
created: issuanceDate, | ||
proofPurpose: 'assertionMethod', | ||
type: 'EthereumEip712Signature2021', | ||
} }); | ||
const message = credential; | ||
const domain = { | ||
chainId, | ||
name: 'VerifiableCredential', | ||
version: '1', | ||
}; | ||
const primaryType = 'VerifiableCredential'; | ||
const allTypes = (0, eip_712_types_generation_1.getEthTypesFromInputDoc)(credential, primaryType); | ||
const types = Object.assign({}, allTypes); | ||
const data = JSON.stringify({ domain, types, message, primaryType }); | ||
const signature = yield context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }); | ||
credential['proof']['proofValue'] = signature; | ||
credential['proof']['eip712'] = { | ||
domain, | ||
messageSchema: allTypes, | ||
primaryType, | ||
}; | ||
return credential; | ||
}); | ||
async createVerifiableCredentialEIP712(args, context) { | ||
const credentialContext = processEntryToArray(args?.credential?.['@context'], MANDATORY_CREDENTIAL_CONTEXT); | ||
const credentialType = processEntryToArray(args?.credential?.type, 'VerifiableCredential'); | ||
let issuanceDate = args?.credential?.issuanceDate || new Date().toISOString(); | ||
if (issuanceDate instanceof Date) { | ||
issuanceDate = issuanceDate.toISOString(); | ||
} | ||
const issuer = extractIssuer(args.credential); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: credential.issuer must not be empty'); | ||
} | ||
let keyRef = args.keyRef; | ||
const identifier = await context.agent.didManagerGet({ did: issuer }); | ||
if (!keyRef) { | ||
const key = identifier.keys.find((k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData')); | ||
if (!key) | ||
throw Error('key_not_found: No suitable signing key is known for ' + identifier.did); | ||
keyRef = key.kid; | ||
} | ||
const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context); | ||
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'); | ||
let chainId = 1; | ||
if (identifier.did.split(':')[1] === 'ethr') | ||
chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod); | ||
const credential = { | ||
...args?.credential, | ||
'@context': credentialContext, | ||
type: credentialType, | ||
issuanceDate, | ||
proof: { | ||
verificationMethod: extendedKey.meta.verificationMethod.id, | ||
created: issuanceDate, | ||
proofPurpose: 'assertionMethod', | ||
type: 'EthereumEip712Signature2021', | ||
}, | ||
}; | ||
const message = credential; | ||
const domain = { | ||
chainId, | ||
name: 'VerifiableCredential', | ||
version: '1', | ||
}; | ||
const primaryType = 'VerifiableCredential'; | ||
const allTypes = getEthTypesFromInputDoc(credential, primaryType); | ||
const types = { ...allTypes }; | ||
const data = JSON.stringify({ domain, types, message, primaryType }); | ||
const signature = await context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }); | ||
credential['proof']['proofValue'] = signature; | ||
credential['proof']['eip712'] = { | ||
domain, | ||
messageSchema: allTypes, | ||
primaryType, | ||
}; | ||
return credential; | ||
} | ||
/** {@inheritdoc ICredentialIssuerEIP712.verifyCredentialEIP712} */ | ||
verifyCredentialEIP712(args, context) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { credential } = args; | ||
if (!credential.proof || !credential.proof.proofValue) | ||
throw new Error('invalid_argument: proof is undefined'); | ||
if (!credential.proof.eip712 || !credential.proof.eip712.messageSchema || !credential.proof.eip712.domain) | ||
throw new Error('invalid_argument: proof.eip712 is missing expected properties'); | ||
const { proof } = credential, signingInput = __rest(credential, ["proof"]); | ||
const { proofValue, eip712 } = proof, verifyInputProof = __rest(proof, ["proofValue", "eip712"]); | ||
const verificationMessage = Object.assign(Object.assign({}, signingInput), { proof: verifyInputProof }); | ||
const objectToVerify = { | ||
message: verificationMessage, | ||
domain: eip712.domain, | ||
types: eip712.messageSchema, | ||
primaryType: eip712.primaryType, | ||
}; | ||
const recovered = (0, eth_sig_util_1.recoverTypedSignature)({ | ||
data: objectToVerify, | ||
signature: proofValue, | ||
version: eth_sig_util_1.SignTypedDataVersion.V4, | ||
}); | ||
const issuer = (0, utils_1.extractIssuer)(credential); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: credential.issuer must not be empty'); | ||
} | ||
const didDocument = yield (0, utils_1.resolveDidOrThrow)(issuer, context); | ||
if (didDocument.verificationMethod) { | ||
for (const verificationMethod of didDocument.verificationMethod) { | ||
if (((_a = (0, utils_1.getEthereumAddress)(verificationMethod)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === recovered.toLowerCase()) { | ||
return true; | ||
} | ||
async verifyCredentialEIP712(args, context) { | ||
const { credential } = args; | ||
if (!credential.proof || !credential.proof.proofValue) | ||
throw new Error('invalid_argument: proof is undefined'); | ||
if (!credential.proof.eip712 || !credential.proof.eip712.messageSchema || !credential.proof.eip712.domain) | ||
throw new Error('invalid_argument: proof.eip712 is missing expected properties'); | ||
const { proof, ...signingInput } = credential; | ||
const { proofValue, eip712, ...verifyInputProof } = proof; | ||
const verificationMessage = { | ||
...signingInput, | ||
proof: verifyInputProof, | ||
}; | ||
const objectToVerify = { | ||
message: verificationMessage, | ||
domain: eip712.domain, | ||
types: eip712.messageSchema, | ||
primaryType: eip712.primaryType, | ||
}; | ||
const recovered = recoverTypedSignature({ | ||
data: objectToVerify, | ||
signature: proofValue, | ||
version: SignTypedDataVersion.V4, | ||
}); | ||
const issuer = extractIssuer(credential); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: credential.issuer must not be empty'); | ||
} | ||
const didDocument = await resolveDidOrThrow(issuer, context); | ||
if (didDocument.verificationMethod) { | ||
for (const verificationMethod of didDocument.verificationMethod) { | ||
if (getEthereumAddress(verificationMethod)?.toLowerCase() === recovered.toLowerCase()) { | ||
return true; | ||
} | ||
} | ||
else { | ||
throw new Error('resolver_error: issuer DIDDocument does not contain any verificationMethods'); | ||
} | ||
return false; | ||
}); | ||
} | ||
else { | ||
throw new Error('resolver_error: issuer DIDDocument does not contain any verificationMethods'); | ||
} | ||
return false; | ||
} | ||
/** {@inheritdoc ICredentialIssuerEIP712.createVerifiablePresentationEIP712} */ | ||
createVerifiablePresentationEIP712(args, context) { | ||
var _a, _b, _c; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const presentationContext = (0, utils_1.processEntryToArray)((_a = args === null || args === void 0 ? void 0 : args.presentation) === null || _a === void 0 ? void 0 : _a['@context'], utils_1.MANDATORY_CREDENTIAL_CONTEXT); | ||
const presentationType = (0, utils_1.processEntryToArray)((_b = args === null || args === void 0 ? void 0 : args.presentation) === null || _b === void 0 ? void 0 : _b.type, 'VerifiablePresentation'); | ||
let issuanceDate = ((_c = args === null || args === void 0 ? void 0 : args.presentation) === null || _c === void 0 ? void 0 : _c.issuanceDate) || new Date().toISOString(); | ||
if (issuanceDate instanceof Date) { | ||
issuanceDate = issuanceDate.toISOString(); | ||
} | ||
const presentation = Object.assign(Object.assign({}, args === null || args === void 0 ? void 0 : args.presentation), { '@context': presentationContext, type: presentationType, issuanceDate }); | ||
if (!(0, utils_1.isDefined)(args.presentation.holder)) { | ||
throw new Error('invalid_argument: presentation.holder must not be empty'); | ||
} | ||
if (args.presentation.verifiableCredential) { | ||
const credentials = args.presentation.verifiableCredential.map((cred) => { | ||
// map JWT credentials to their canonical form | ||
if (typeof cred !== 'string' && cred.proof.jwt) { | ||
return cred.proof.jwt; | ||
} | ||
else { | ||
return JSON.stringify(cred); | ||
} | ||
}); | ||
presentation.verifiableCredential = credentials; | ||
} | ||
let identifier; | ||
try { | ||
identifier = yield context.agent.didManagerGet({ did: presentation.holder }); | ||
} | ||
catch (e) { | ||
throw new Error('invalid_argument: presentation.holder must be a DID managed by this agent'); | ||
} | ||
let keyRef = args.keyRef; | ||
if (!keyRef) { | ||
const key = identifier.keys.find((k) => { var _a, _b; return k.type === 'Secp256k1' && ((_b = (_a = k.meta) === null || _a === void 0 ? void 0 : _a.algorithms) === null || _b === void 0 ? void 0 : _b.includes('eth_signTypedData')); }); | ||
if (!key) | ||
throw Error('key_not_found: No suitable signing key is known for ' + identifier.did); | ||
keyRef = key.kid; | ||
} | ||
const extendedKeys = yield (0, utils_1.mapIdentifierKeysToDoc)(identifier, 'verificationMethod', context); | ||
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'); | ||
let chainId = 1; | ||
if (identifier.did.split(':')[1] === 'ethr') | ||
chainId = (0, utils_1.getChainIdForDidEthr)(extendedKey.meta.verificationMethod); | ||
presentation['proof'] = { | ||
verificationMethod: extendedKey.meta.verificationMethod.id, | ||
created: issuanceDate, | ||
proofPurpose: 'assertionMethod', | ||
type: 'EthereumEip712Signature2021', | ||
}; | ||
const message = presentation; | ||
const domain = { | ||
chainId, | ||
name: 'VerifiablePresentation', | ||
version: '1', | ||
}; | ||
const primaryType = 'VerifiablePresentation'; | ||
const allTypes = (0, eip_712_types_generation_1.getEthTypesFromInputDoc)(presentation, primaryType); | ||
const types = Object.assign({}, allTypes); | ||
const data = JSON.stringify({ domain, types, message }); | ||
const signature = yield context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }); | ||
presentation.proof.proofValue = signature; | ||
presentation.proof.eip712 = { | ||
domain, | ||
messageSchema: allTypes, | ||
primaryType, | ||
}; | ||
return presentation; | ||
}); | ||
async createVerifiablePresentationEIP712(args, context) { | ||
const presentationContext = processEntryToArray(args?.presentation?.['@context'], MANDATORY_CREDENTIAL_CONTEXT); | ||
const presentationType = processEntryToArray(args?.presentation?.type, 'VerifiablePresentation'); | ||
let issuanceDate = args?.presentation?.issuanceDate || new Date().toISOString(); | ||
if (issuanceDate instanceof Date) { | ||
issuanceDate = issuanceDate.toISOString(); | ||
} | ||
const presentation = { | ||
...args?.presentation, | ||
'@context': presentationContext, | ||
type: presentationType, | ||
issuanceDate, | ||
}; | ||
if (!isDefined(args.presentation.holder)) { | ||
throw new Error('invalid_argument: presentation.holder must not be empty'); | ||
} | ||
if (args.presentation.verifiableCredential) { | ||
const credentials = args.presentation.verifiableCredential.map((cred) => { | ||
// map JWT credentials to their canonical form | ||
if (typeof cred !== 'string' && cred.proof.jwt) { | ||
return cred.proof.jwt; | ||
} | ||
else { | ||
return JSON.stringify(cred); | ||
} | ||
}); | ||
presentation.verifiableCredential = credentials; | ||
} | ||
let identifier; | ||
try { | ||
identifier = await context.agent.didManagerGet({ did: presentation.holder }); | ||
} | ||
catch (e) { | ||
throw new Error('invalid_argument: presentation.holder must be a DID managed by this agent'); | ||
} | ||
let keyRef = args.keyRef; | ||
if (!keyRef) { | ||
const key = identifier.keys.find((k) => k.type === 'Secp256k1' && k.meta?.algorithms?.includes('eth_signTypedData')); | ||
if (!key) | ||
throw Error('key_not_found: No suitable signing key is known for ' + identifier.did); | ||
keyRef = key.kid; | ||
} | ||
const extendedKeys = await mapIdentifierKeysToDoc(identifier, 'verificationMethod', context); | ||
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'); | ||
let chainId = 1; | ||
if (identifier.did.split(':')[1] === 'ethr') | ||
chainId = getChainIdForDidEthr(extendedKey.meta.verificationMethod); | ||
presentation['proof'] = { | ||
verificationMethod: extendedKey.meta.verificationMethod.id, | ||
created: issuanceDate, | ||
proofPurpose: 'assertionMethod', | ||
type: 'EthereumEip712Signature2021', | ||
}; | ||
const message = presentation; | ||
const domain = { | ||
chainId, | ||
name: 'VerifiablePresentation', | ||
version: '1', | ||
}; | ||
const primaryType = 'VerifiablePresentation'; | ||
const allTypes = getEthTypesFromInputDoc(presentation, primaryType); | ||
const types = { ...allTypes }; | ||
const data = JSON.stringify({ domain, types, message }); | ||
const signature = await context.agent.keyManagerSign({ keyRef, data, algorithm: 'eth_signTypedData' }); | ||
presentation.proof.proofValue = signature; | ||
presentation.proof.eip712 = { | ||
domain, | ||
messageSchema: allTypes, | ||
primaryType, | ||
}; | ||
return presentation; | ||
} | ||
/** {@inheritdoc ICredentialIssuerEIP712.verifyPresentationEIP712} */ | ||
verifyPresentationEIP712(args, context) { | ||
var _a; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { presentation } = args; | ||
if (!presentation.proof || !presentation.proof.proofValue) | ||
throw new Error('Proof is undefined'); | ||
if (!presentation.proof.eip712 || | ||
!presentation.proof.eip712.messageSchema || | ||
!presentation.proof.eip712.domain) | ||
throw new Error('proof.eip712 is undefined'); | ||
const { proof } = presentation, signingInput = __rest(presentation, ["proof"]); | ||
const { proofValue, eip712 } = proof, verifyInputProof = __rest(proof, ["proofValue", "eip712"]); | ||
const verificationMessage = Object.assign(Object.assign({}, signingInput), { proof: verifyInputProof }); | ||
const objectToVerify = { | ||
message: verificationMessage, | ||
domain: eip712.domain, | ||
types: eip712.messageSchema, | ||
primaryType: eip712.primaryType, | ||
}; | ||
const recovered = (0, eth_sig_util_1.recoverTypedSignature)({ | ||
data: objectToVerify, | ||
signature: proofValue, | ||
version: eth_sig_util_1.SignTypedDataVersion.V4, | ||
}); | ||
const issuer = (0, utils_1.extractIssuer)(presentation); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: args.presentation.issuer must not be empty'); | ||
} | ||
const didDocument = yield (0, utils_1.resolveDidOrThrow)(issuer, context); | ||
if (didDocument.verificationMethod) { | ||
for (const verificationMethod of didDocument.verificationMethod) { | ||
if (((_a = (0, utils_1.getEthereumAddress)(verificationMethod)) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === recovered.toLowerCase()) { | ||
return true; | ||
} | ||
async verifyPresentationEIP712(args, context) { | ||
const { presentation } = args; | ||
if (!presentation.proof || !presentation.proof.proofValue) | ||
throw new Error('Proof is undefined'); | ||
if (!presentation.proof.eip712 || | ||
!presentation.proof.eip712.messageSchema || | ||
!presentation.proof.eip712.domain) | ||
throw new Error('proof.eip712 is undefined'); | ||
const { proof, ...signingInput } = presentation; | ||
const { proofValue, eip712, ...verifyInputProof } = proof; | ||
const verificationMessage = { | ||
...signingInput, | ||
proof: verifyInputProof, | ||
}; | ||
const objectToVerify = { | ||
message: verificationMessage, | ||
domain: eip712.domain, | ||
types: eip712.messageSchema, | ||
primaryType: eip712.primaryType, | ||
}; | ||
const recovered = recoverTypedSignature({ | ||
data: objectToVerify, | ||
signature: proofValue, | ||
version: SignTypedDataVersion.V4, | ||
}); | ||
const issuer = extractIssuer(presentation); | ||
if (!issuer || typeof issuer === 'undefined') { | ||
throw new Error('invalid_argument: args.presentation.issuer must not be empty'); | ||
} | ||
const didDocument = await resolveDidOrThrow(issuer, context); | ||
if (didDocument.verificationMethod) { | ||
for (const verificationMethod of didDocument.verificationMethod) { | ||
if (getEthereumAddress(verificationMethod)?.toLowerCase() === recovered.toLowerCase()) { | ||
return true; | ||
} | ||
} | ||
else { | ||
throw new Error('resolver_error: holder DIDDocument does not contain any verificationMethods'); | ||
} | ||
return false; | ||
}); | ||
} | ||
else { | ||
throw new Error('resolver_error: holder DIDDocument does not contain any verificationMethods'); | ||
} | ||
return false; | ||
} | ||
} | ||
exports.CredentialIssuerEIP712 = CredentialIssuerEIP712; | ||
//# sourceMappingURL=CredentialEIP712.js.map |
@@ -1,8 +0,3 @@ | ||
/** | ||
* @public | ||
*/ | ||
declare const schema: any; | ||
export { schema }; | ||
export { CredentialIssuerEIP712 } from './agent/CredentialEIP712'; | ||
export * from './types/ICredentialEIP712'; | ||
export { CredentialIssuerEIP712 } from './agent/CredentialEIP712.js'; | ||
export * from './types/ICredentialEIP712.js'; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,26 +0,3 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CredentialIssuerEIP712 = exports.schema = void 0; | ||
/** | ||
* @public | ||
*/ | ||
const schema = require('../plugin.schema.json'); | ||
exports.schema = schema; | ||
var CredentialEIP712_1 = require("./agent/CredentialEIP712"); | ||
Object.defineProperty(exports, "CredentialIssuerEIP712", { enumerable: true, get: function () { return CredentialEIP712_1.CredentialIssuerEIP712; } }); | ||
__exportStar(require("./types/ICredentialEIP712"), exports); | ||
export { CredentialIssuerEIP712 } from './agent/CredentialEIP712.js'; | ||
export * from './types/ICredentialEIP712.js'; | ||
//# sourceMappingURL=index.js.map |
@@ -8,5 +8,5 @@ // This file is read by tools that parse documentation comments conforming to the TSDoc standard. | ||
"packageName": "@microsoft/api-extractor", | ||
"packageVersion": "7.34.0" | ||
"packageVersion": "7.33.8" | ||
} | ||
] | ||
} |
@@ -1,3 +0,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
export {}; | ||
//# sourceMappingURL=ICredentialEIP712.js.map |
{ | ||
"name": "@veramo/credential-eip712", | ||
"description": "Veramo plugin for working with EIP712 Verifiable Credentials & Presentations.", | ||
"version": "4.3.1-next.4+1c521a67", | ||
"version": "4.3.1-next.7+b5cea3c0", | ||
"main": "build/index.js", | ||
"exports": { | ||
".": "./build/index.js", | ||
"./build/plugin.schema.json": "./build/plugin.schema.json" | ||
}, | ||
"types": "build/index.d.ts", | ||
"scripts": { | ||
"build": "tsc", | ||
"generate-plugin-schema": "pnpm exec veramo dev generate-plugin-schema" | ||
"generate-plugin-schema": "node ../cli/bin/veramo.js dev generate-plugin-schema" | ||
}, | ||
@@ -18,4 +22,4 @@ "veramo": { | ||
"@metamask/eth-sig-util": "^5.0.0", | ||
"@veramo/core": "^4.3.1-next.4+1c521a67", | ||
"@veramo/utils": "^4.3.1-next.4+1c521a67", | ||
"@veramo/core": "^4.3.1-next.7+b5cea3c0", | ||
"@veramo/utils": "^4.3.1-next.7+b5cea3c0", | ||
"debug": "^4.3.3", | ||
@@ -52,3 +56,8 @@ "eip-712-types-generation": "^0.1.6" | ||
"keywords": [], | ||
"gitHead": "1c521a6745756649028504ab239e3458462dfe37" | ||
"type": "module", | ||
"moduleDirectories": [ | ||
"node_modules", | ||
"src" | ||
], | ||
"gitHead": "b5cea3c0d80d900a47bd1d9eea68f84b70a35e7b" | ||
} |
@@ -19,3 +19,3 @@ import { | ||
} from '@veramo/utils' | ||
import { schema } from '../index' | ||
import schema from "../plugin.schema.json" assert { type: 'json' } | ||
@@ -22,0 +22,0 @@ import { recoverTypedSignature, SignTypedDataVersion } from '@metamask/eth-sig-util' |
@@ -1,7 +0,2 @@ | ||
/** | ||
* @public | ||
*/ | ||
const schema = require('../plugin.schema.json') | ||
export { schema } | ||
export { CredentialIssuerEIP712 } from './agent/CredentialEIP712' | ||
export * from './types/ICredentialEIP712' | ||
export { CredentialIssuerEIP712 } from './agent/CredentialEIP712.js' | ||
export * from './types/ICredentialEIP712.js' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
107939
20
2015
Yes
2