@sphereon/ssi-sdk-ext.kms-musap-rn
Version:
Sphereon SSI-SDK react-native plugin for management of keys with musap.
239 lines (238 loc) • 8.31 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/MusapKeyManagerSystem.ts
import { PEMToBinary } from "@sphereon/ssi-sdk-ext.x509-utils";
import { isSignatureAlgorithmType, MusapClient, signatureAlgorithmFromKeyAlgorithm } from "@sphereon/musap-react-native";
import { AbstractKeyManagementSystem } from "@veramo/key-manager";
import { Loggers } from "@sphereon/ssi-types";
import { asn1DerToRawPublicKey, calculateJwkThumbprintForKey, hexStringFromUint8Array, isAsn1Der, isRawCompressedPublicKey, toRawCompressedHexPublicKey } from "@sphereon/ssi-sdk-ext.key-utils";
import * as u8a from "uint8arrays";
var { fromString, toString } = u8a;
var logger = Loggers.DEFAULT.get("sphereon:musap-rn-kms");
var MusapKeyManagementSystem = class extends AbstractKeyManagementSystem {
static {
__name(this, "MusapKeyManagementSystem");
}
musapClient;
sscdType;
sscdId;
defaultKeyAttributes;
defaultSignAttributes;
constructor(sscdType, sscdId, opts) {
super();
try {
this.musapClient = MusapClient;
this.sscdType = sscdType ? sscdType : "TEE";
this.sscdId = sscdId ?? this.sscdType;
this.defaultKeyAttributes = opts?.defaultKeyAttributes;
this.defaultSignAttributes = opts?.defaultSignAttributes;
const enabledSscds = this.musapClient.listEnabledSscds();
if (!enabledSscds.some((value) => value.sscdId == sscdId)) {
this.musapClient.enableSscd(this.sscdType, this.sscdId, opts?.externalSscdSettings);
}
} catch (e) {
console.error("enableSscd", e);
throw Error("enableSscd failed");
}
}
async listKeys() {
const keysJson = this.musapClient.listKeys();
return keysJson.map((key) => this.asMusapKeyInfo(key));
}
async createKey(args) {
const { type, meta } = args;
if (meta === void 0 || !("keyAlias" in meta)) {
return Promise.reject(Error("a unique keyAlias field is required for MUSAP"));
}
if (this.sscdType == "EXTERNAL") {
const existingKeys = this.musapClient.listKeys();
const extKey = existingKeys.find((musapKey) => musapKey.sscdType === "External Signature");
if (extKey) {
extKey.algorithm = "eccp256r1";
return this.asMusapKeyInfo(extKey);
}
return Promise.reject(Error(`No external key was bound yet for sscd ${this.sscdId}`));
}
const keyGenReq = {
keyAlgorithm: this.mapKeyTypeToAlgorithmType(type),
keyUsage: "keyUsage" in meta ? meta.keyUsage : "sign",
keyAlias: meta.keyAlias,
attributes: this.recordToKeyAttributes({
...this.defaultKeyAttributes,
..."attributes" in meta ? meta.attributes : {}
}),
role: "role" in meta ? meta.role : "administrator"
};
try {
const generatedKeyUri = await this.musapClient.generateKey(this.sscdType, keyGenReq);
if (generatedKeyUri) {
logger.debug("Generated key:", generatedKeyUri);
const key = this.musapClient.getKeyByUri(generatedKeyUri);
return this.asMusapKeyInfo(key);
} else {
return Promise.reject(new Error("Failed to generate key. No key URI"));
}
} catch (error) {
logger.error("An error occurred:", error);
throw error;
}
}
mapKeyTypeToAlgorithmType = /* @__PURE__ */ __name((type) => {
switch (type) {
case "Secp256k1":
return "ECCP256K1";
case "Secp256r1":
return "ECCP256R1";
case "RSA":
return "RSA2K";
default:
throw new Error(`Key type ${type} is not supported by MUSAP`);
}
}, "mapKeyTypeToAlgorithmType");
mapAlgorithmTypeToKeyType = /* @__PURE__ */ __name((type) => {
switch (type) {
case "eccp256k1":
return "Secp256k1";
case "eccp256r1":
return "Secp256r1";
case "ecc_ed25519":
return "Ed25519";
case "rsa2k":
case "rsa4k":
return "RSA";
default:
throw new Error(`Key type ${type} is not supported.`);
}
}, "mapAlgorithmTypeToKeyType");
async deleteKey({ kid }) {
try {
const key = this.musapClient.getKeyById(kid);
if (key.sscdType === "External Signature") {
return true;
}
void this.musapClient.removeKey(kid);
return true;
} catch (error) {
console.warn("Failed to delete key:", error);
return false;
}
}
determineAlgorithm(providedAlgorithm, keyAlgorithm) {
if (providedAlgorithm === void 0) {
return signatureAlgorithmFromKeyAlgorithm(keyAlgorithm);
}
if (isSignatureAlgorithmType(providedAlgorithm)) {
return providedAlgorithm;
}
return signatureAlgorithmFromKeyAlgorithm(providedAlgorithm);
}
async sign(args) {
if (!args.keyRef) {
throw new Error("key_not_found: No key ref provided");
}
const data = Array.from(args.data);
const dataBase64 = toString(args.data, "base64pad");
const key = this.musapClient.getKeyById(args.keyRef.kid);
if (key.sscdType === "External Signature") {
key.algorithm = "eccp256r1";
}
const signatureReq = {
keyUri: key.keyUri,
data,
dataBase64,
algorithm: this.determineAlgorithm(args.algorithm, key.algorithm),
displayText: args.displayText,
transId: args.transId,
format: args.format ?? "RAW",
attributes: this.recordToSignatureAttributes({
...this.defaultSignAttributes,
...args.attributes
})
};
return this.musapClient.sign(signatureReq);
}
async importKey(args) {
throw new Error("importKey is not implemented for MusapKeyManagementSystem.");
}
decodeMusapPublicKey = /* @__PURE__ */ __name((args) => {
const { publicKey, keyType } = args;
const pemBinary = PEMToBinary(publicKey.pem);
const pemString = toString(pemBinary, "utf8");
const isDoubleEncoded = pemBinary.length > 0 && typeof pemString === "string" && pemString.startsWith("MF");
if (isDoubleEncoded) {
const actualDerBytes = fromString(pemString, "base64");
const keyDataStart = 24;
const keyData = actualDerBytes.slice(keyDataStart);
let publicKeyHex = toString(keyData, "hex");
if (publicKeyHex.length <= 128 && !publicKeyHex.startsWith("04")) {
publicKeyHex = "04" + publicKeyHex;
}
while (publicKeyHex.startsWith("04") && publicKeyHex.length < 130) {
publicKeyHex = publicKeyHex + "0";
}
if (publicKeyHex.startsWith("04") && publicKeyHex.length === 130) {
const xCoord = fromString(publicKeyHex.slice(2, 66), "hex");
const yCoord = fromString(publicKeyHex.slice(66, 130), "hex");
const prefix = new Uint8Array([
yCoord[31] % 2 === 0 ? 2 : 3
]);
const compressedKey = new Uint8Array(33);
compressedKey.set(prefix, 0);
compressedKey.set(xCoord, 1);
return toString(compressedKey, "hex");
}
return publicKeyHex;
}
const publicKeyBinary = isAsn1Der(pemBinary) ? asn1DerToRawPublicKey(pemBinary, keyType) : pemBinary;
return isRawCompressedPublicKey(publicKeyBinary) ? hexStringFromUint8Array(publicKeyBinary) : toRawCompressedHexPublicKey(publicKeyBinary, keyType);
}, "decodeMusapPublicKey");
asMusapKeyInfo(args) {
const { keyId, publicKey, ...metadata } = {
...args
};
const keyType = this.mapAlgorithmTypeToKeyType(args.algorithm);
const publicKeyHex = this.decodeMusapPublicKey({
publicKey,
keyType
});
const keyInfo = {
kid: keyId,
type: keyType,
publicKeyHex,
meta: metadata
};
const jwkThumbprint = calculateJwkThumbprintForKey({
key: keyInfo
});
keyInfo.meta = {
...keyInfo.meta,
jwkThumbprint
};
return keyInfo;
}
sharedSecret(args) {
throw new Error("Not supported.");
}
recordToKeyAttributes(record) {
if (!record) {
return [];
}
return Object.entries(record).map(([key, value]) => ({
name: key,
value
}));
}
recordToSignatureAttributes(record) {
if (!record) {
return [];
}
return Object.entries(record).map(([key, value]) => ({
name: key,
value
}));
}
};
export {
MusapKeyManagementSystem
};
//# sourceMappingURL=index.js.map