{"version":3,"file":"gcp-kms-client.mjs","names":["#client","#versionName","#publicKey"],"sources":["../../src/gcp/gcp-kms-client.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\nimport { KeyManagementServiceClient } from '@google-cloud/kms';\nimport type { PublicKey, SignatureFlag } from '@mysten/sui/cryptography';\nimport { SIGNATURE_FLAG_TO_SCHEME, Signer } from '@mysten/sui/cryptography';\nimport { Secp256k1PublicKey } from '@mysten/sui/keypairs/secp256k1';\nimport { Secp256r1PublicKey } from '@mysten/sui/keypairs/secp256r1';\nimport { fromBase64 } from '@mysten/sui/utils';\n\nimport { getConcatenatedSignature, publicKeyFromDER } from '../utils/utils.js';\n\n/**\n * Configuration options for initializing the GcpKmsSigner.\n */\nexport interface GcpKmsSignerOptions {\n\t/** The version name generated from `client.cryptoKeyVersionPath()` */\n\tversionName: string;\n\t/** Options for setting up the GCP KMS client */\n\tclient: KeyManagementServiceClient;\n\t/** Public key */\n\tpublicKey: PublicKey;\n}\n\n/**\n * GCP KMS Signer integrates GCP Key Management Service (KMS) with the Sui blockchain\n * to provide signing capabilities using GCP-managed cryptographic keys.\n */\nexport class GcpKmsSigner extends Signer {\n\t#publicKey: PublicKey;\n\t/** GCP KMS client instance */\n\t#client: KeyManagementServiceClient;\n\t/** GCP KMS version name (generated from `client.cryptoKeyVersionPath()`) */\n\t#versionName: string;\n\n\t/**\n\t * Creates an instance of GcpKmsSigner. It's expected to call the static `fromOptions`\n\t * or `fromVersionName` method to create an instance.\n\t * For example:\n\t * ```\n\t * const signer = await GcpKmsSigner.fromVersionName(versionName);\n\t * ```\n\t * @throws Will throw an error if required GCP credentials are not provided.\n\t */\n\tconstructor({ versionName, client, publicKey }: GcpKmsSignerOptions) {\n\t\tsuper();\n\t\tif (!versionName) throw new Error('Version name is required');\n\n\t\tthis.#client = client;\n\t\tthis.#versionName = versionName;\n\t\tthis.#publicKey = publicKey;\n\t}\n\n\t/**\n\t * Retrieves the key scheme used by this signer.\n\t * @returns GCP supports only `Secp256k1` and `Secp256r1` schemes.\n\t */\n\tgetKeyScheme() {\n\t\treturn SIGNATURE_FLAG_TO_SCHEME[this.#publicKey.flag() as SignatureFlag];\n\t}\n\n\t/**\n\t * Retrieves the public key associated with this signer.\n\t * @returns The Secp256k1PublicKey instance.\n\t * @throws Will throw an error if the public key has not been initialized.\n\t */\n\tgetPublicKey() {\n\t\treturn this.#publicKey;\n\t}\n\n\t/**\n\t * Signs the given data using GCP KMS.\n\t * @param bytes - The data to be signed as a Uint8Array.\n\t * @returns A promise that resolves to the signature as a Uint8Array.\n\t * @throws Will throw an error if the public key is not initialized or if signing fails.\n\t */\n\tasync sign(bytes: Uint8Array): Promise<Uint8Array<ArrayBuffer>> {\n\t\tconst [signResponse] = await this.#client.asymmetricSign({\n\t\t\tname: this.#versionName,\n\t\t\tdata: bytes,\n\t\t});\n\n\t\tif (!signResponse.signature) {\n\t\t\tthrow new Error('No signature returned from GCP KMS');\n\t\t}\n\n\t\treturn getConcatenatedSignature(signResponse.signature as Uint8Array, this.getKeyScheme());\n\t}\n\n\t/**\n\t * Creates a GCP KMS signer from the provided options.\n\t * Expects the credentials file to be set as an env variable\n\t * (GOOGLE_APPLICATION_CREDENTIALS).\n\t */\n\tstatic async fromOptions(options: {\n\t\tprojectId: string;\n\t\tlocation: string;\n\t\tkeyRing: string;\n\t\tcryptoKey: string;\n\t\tcryptoKeyVersion: string;\n\t}) {\n\t\tconst client = new KeyManagementServiceClient();\n\n\t\tconst versionName = client.cryptoKeyVersionPath(\n\t\t\toptions.projectId,\n\t\t\toptions.location,\n\t\t\toptions.keyRing,\n\t\t\toptions.cryptoKey,\n\t\t\toptions.cryptoKeyVersion,\n\t\t);\n\n\t\treturn new GcpKmsSigner({\n\t\t\tversionName,\n\t\t\tclient,\n\t\t\tpublicKey: await getPublicKey(client, versionName),\n\t\t});\n\t}\n\n\tstatic async fromVersionName(versionName: string) {\n\t\tconst client = new KeyManagementServiceClient();\n\t\treturn new GcpKmsSigner({\n\t\t\tversionName,\n\t\t\tclient,\n\t\t\tpublicKey: await getPublicKey(client, versionName),\n\t\t});\n\t}\n}\n\n/**\n * Retrieves the public key associated with the given version name.\n */\nasync function getPublicKey(\n\tclient: KeyManagementServiceClient,\n\tversionName: string,\n): Promise<PublicKey> {\n\tconst [publicKey] = await client.getPublicKey({ name: versionName });\n\n\tconst { algorithm, pem } = publicKey;\n\n\tif (!pem) throw new Error('No PEM key returned from GCP KMS');\n\n\tconst base64 = pem\n\t\t.replace('-----BEGIN PUBLIC KEY-----', '')\n\t\t.replace('-----END PUBLIC KEY-----', '')\n\t\t.replace(/\\s/g, '');\n\n\tconst compressedKey = publicKeyFromDER(fromBase64(base64));\n\n\tswitch (algorithm) {\n\t\tcase 'EC_SIGN_SECP256K1_SHA256':\n\t\t\treturn new Secp256k1PublicKey(compressedKey);\n\t\tcase 'EC_SIGN_P256_SHA256':\n\t\t\treturn new Secp256r1PublicKey(compressedKey);\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported algorithm: ${algorithm}`);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;AA2BA,IAAa,eAAb,MAAa,qBAAqB,OAAO;CACxC;;CAEA;;CAEA;;;;;;;;;;CAWA,YAAY,EAAE,aAAa,QAAQ,aAAkC;AACpE,SAAO;AACP,MAAI,CAAC,YAAa,OAAM,IAAI,MAAM,2BAA2B;AAE7D,QAAKA,SAAU;AACf,QAAKC,cAAe;AACpB,QAAKC,YAAa;;;;;;CAOnB,eAAe;AACd,SAAO,yBAAyB,MAAKA,UAAW,MAAM;;;;;;;CAQvD,eAAe;AACd,SAAO,MAAKA;;;;;;;;CASb,MAAM,KAAK,OAAqD;EAC/D,MAAM,CAAC,gBAAgB,MAAM,MAAKF,OAAQ,eAAe;GACxD,MAAM,MAAKC;GACX,MAAM;GACN,CAAC;AAEF,MAAI,CAAC,aAAa,UACjB,OAAM,IAAI,MAAM,qCAAqC;AAGtD,SAAO,yBAAyB,aAAa,WAAyB,KAAK,cAAc,CAAC;;;;;;;CAQ3F,aAAa,YAAY,SAMtB;EACF,MAAM,SAAS,IAAI,4BAA4B;EAE/C,MAAM,cAAc,OAAO,qBAC1B,QAAQ,WACR,QAAQ,UACR,QAAQ,SACR,QAAQ,WACR,QAAQ,iBACR;AAED,SAAO,IAAI,aAAa;GACvB;GACA;GACA,WAAW,MAAM,aAAa,QAAQ,YAAY;GAClD,CAAC;;CAGH,aAAa,gBAAgB,aAAqB;EACjD,MAAM,SAAS,IAAI,4BAA4B;AAC/C,SAAO,IAAI,aAAa;GACvB;GACA;GACA,WAAW,MAAM,aAAa,QAAQ,YAAY;GAClD,CAAC;;;;;;AAOJ,eAAe,aACd,QACA,aACqB;CACrB,MAAM,CAAC,aAAa,MAAM,OAAO,aAAa,EAAE,MAAM,aAAa,CAAC;CAEpE,MAAM,EAAE,WAAW,QAAQ;AAE3B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mCAAmC;CAO7D,MAAM,gBAAgB,iBAAiB,WALxB,IACb,QAAQ,8BAA8B,GAAG,CACzC,QAAQ,4BAA4B,GAAG,CACvC,QAAQ,OAAO,GAAG,CAEqC,CAAC;AAE1D,SAAQ,WAAR;EACC,KAAK,2BACJ,QAAO,IAAI,mBAAmB,cAAc;EAC7C,KAAK,sBACJ,QAAO,IAAI,mBAAmB,cAAc;EAC7C,QACC,OAAM,IAAI,MAAM,0BAA0B,YAAY"}