@credo-ts/core
Version:
<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1
121 lines (120 loc) • 4.51 kB
JavaScript
import { CredoError } from "../../error/CredoError.mjs";
import "../../error/index.mjs";
import "../../agent/index.mjs";
import { PublicJwk } from "../../modules/kms/jwk/PublicJwk.mjs";
import { KeyManagementApi } from "../../modules/kms/KeyManagementApi.mjs";
import "../../modules/kms/index.mjs";
import { CredoWebCrypto } from "../webcrypto/CredoWebCrypto.mjs";
import { X509Certificate } from "../../modules/x509/X509Certificate.mjs";
import { X509Service } from "../../modules/x509/X509Service.mjs";
import "../index.mjs";
import { getMac0Context } from "./mac0Context.mjs";
import { getSign1Context } from "./sign1Context.mjs";
import { CoseKey } from "@owf/mdoc";
//#region src/crypto/contexts/mdocContext.ts
/**
* HPKE suites the mdoc library can request, mapped to the JOSE-HPKE style algorithm identifiers the
* KMS uses. ISO 18013-7 Annex C only uses the first entry.
*/
const hpkeSuiteToJwaAlgorithm = {
"dhkem-p256-hkdf-sha256/hkdf-sha256/aes-128-gcm": "HPKE-0",
"dhkem-p256-hkdf-sha256/hkdf-sha256/aes-256-gcm": "HPKE-7",
"dhkem-x25519-hkdf-sha256/hkdf-sha256/aes-128-gcm": "HPKE-3"
};
function jwaAlgorithmForHpkeSuite(suite) {
const algorithm = hpkeSuiteToJwaAlgorithm[suite];
if (!algorithm) throw new CredoError(`Unsupported HPKE suite '${suite}'`);
return algorithm;
}
const getMdocContext = (agentContext, { now } = {}) => {
const crypto = new CredoWebCrypto(agentContext);
const kms = agentContext.resolve(KeyManagementApi);
return {
fetch: agentContext.config.agentDependencies.fetch,
crypto: {
digest: async (input) => {
const { bytes, digestAlgorithm } = input;
return new Uint8Array(crypto.digest(digestAlgorithm, new Uint8Array(bytes).buffer));
},
random: (length) => {
return crypto.getRandomValues(new Uint8Array(length));
},
hdkf: async () => {
throw new CredoError("mdoc device MAC authentication is not supported. Only device signature authentication is currently implemented.");
},
hpke: {
suites: Object.keys(hpkeSuiteToJwaAlgorithm),
seal: async (input) => {
const { encrypted, encapsulatedKey } = await kms.encrypt({
key: { keyAgreement: {
algorithm: jwaAlgorithmForHpkeSuite(input.suite),
externalPublicJwk: PublicJwk.fromUnknown(input.recipientPublicKey.jwk).toJson(),
info: input.info
} },
encryption: {
algorithm: "HPKE",
aad: input.aad
},
data: input.plaintext
});
if (!encapsulatedKey) throw new CredoError("Key management service did not return an encapsulated key for HPKE seal");
return {
enc: encapsulatedKey,
ciphertext: encrypted
};
},
open: async (input) => {
const { keyId } = input.recipientKey;
if (!keyId) throw new CredoError("Missing required keyId on the recipient key for HPKE open");
const { data } = await kms.decrypt({
key: { keyAgreement: {
algorithm: jwaAlgorithmForHpkeSuite(input.suite),
keyId,
encapsulatedKey: input.enc,
info: input.info
} },
decryption: {
algorithm: "HPKE",
aad: input.aad
},
encrypted: input.ciphertext
});
return data;
}
}
},
cose: {
mac0: getMac0Context(agentContext),
sign1: getSign1Context(agentContext)
},
x509: {
getSubjectNameField: (input) => {
return X509Certificate.fromRawCertificate(input.certificate).getSubjectNameField(input.field);
},
getPublicKey: async (input) => {
const certificate = X509Certificate.fromRawCertificate(input.certificate);
return CoseKey.fromJwk(certificate.publicJwk.toJson());
},
verifyCertificateChain: async (input) => {
const certificateChain = input.x5chain.map((cert) => X509Certificate.fromRawCertificate(cert).toString("pem"));
const trustedCertificates = input.trustedCertificates.map((cert) => X509Certificate.fromRawCertificate(cert).toString("pem"));
return { chain: (await X509Service.validateCertificateChain(agentContext, {
certificateChain,
trustedCertificates,
verificationDate: input.now ?? now
})).map((cert) => cert.rawCertificate).reverse() };
},
getCertificateData: async (input) => {
const { certificate } = input;
const x509Certificate = X509Certificate.fromRawCertificate(certificate);
return {
...x509Certificate.data,
thumbprint: await x509Certificate.getThumbprintInHex(agentContext)
};
}
}
};
};
//#endregion
export { getMdocContext };
//# sourceMappingURL=mdocContext.mjs.map