From 8e288a5a7f49c613a8b40adf7046095a70413b86 Mon Sep 17 00:00:00 2001 From: Mohammad Cheikh Date: Sat, 7 Dec 2024 19:32:48 -0500 Subject: [PATCH 1/2] add keyformat functionality to decryption --- packages/crypto/src/turnkey.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/crypto/src/turnkey.ts b/packages/crypto/src/turnkey.ts index 15eb55f22..dd0298ee6 100644 --- a/packages/crypto/src/turnkey.ts +++ b/packages/crypto/src/turnkey.ts @@ -18,11 +18,14 @@ import { uncompressRawPublicKey, } from "./crypto"; +import { ed25519 } from '@noble/curves/ed25519'; + interface DecryptExportBundleParams { exportBundle: string; organizationId: string; embeddedKey: string; dangerouslyOverrideSignerPublicKey?: string; // Optional override for signer key + keyFormat?: "SOLANA" | "HEXADECIMAL"; returnMnemonic: boolean; } interface EncryptPrivateKeyToBundleParams { @@ -99,6 +102,7 @@ export const decryptExportBundle = async ({ embeddedKey, organizationId, dangerouslyOverrideSignerPublicKey, + keyFormat, returnMnemonic, }: DecryptExportBundleParams): Promise => { try { @@ -139,13 +143,32 @@ export const decryptExportBundle = async ({ receiverPriv: embeddedKey, }); + if (keyFormat === "SOLANA" && !returnMnemonic) { + if (decryptedData.length !== 32) { + throw new Error( + `invalid private key length. Expected 32 bytes. Got ${decryptedData.length}.` + ); + } + const publicKeyBytes = ed25519.getPublicKey(decryptedData); + if (publicKeyBytes.length !== 32) { + throw new Error( + `invalid public key length. Expected 32 bytes. Got ${publicKeyBytes.length}.` + ); + } + const concatenatedBytes = new Uint8Array(64); + concatenatedBytes.set(decryptedData, 0); + concatenatedBytes.set(publicKeyBytes, 32); + return bs58.encode(concatenatedBytes); + } + const decryptedDataHex = uint8ArrayToHexString(decryptedData); return returnMnemonic ? hexToAscii(decryptedDataHex) : decryptedDataHex; } catch (error) { - throw new Error(`"Error decrypting bundle:", ${error}`); + throw new Error(`Error decrypting bundle: ${error}`); } }; + /** * Verifies a signature from a Turnkey stamp using ECDSA and SHA-256. * From 668edfacaa46f427798716320a1aeb80d91d765f Mon Sep 17 00:00:00 2001 From: Mohammad Cheikh Date: Sat, 7 Dec 2024 19:34:35 -0500 Subject: [PATCH 2/2] prettier and changeset --- .changeset/curly-eyes-cover.md | 5 +++++ packages/crypto/src/turnkey.ts | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .changeset/curly-eyes-cover.md diff --git a/.changeset/curly-eyes-cover.md b/.changeset/curly-eyes-cover.md new file mode 100644 index 000000000..9aeae84c2 --- /dev/null +++ b/.changeset/curly-eyes-cover.md @@ -0,0 +1,5 @@ +--- +"@turnkey/crypto": minor +--- + +Add keyformat to decryptExportBundle for displaying Solana private keys diff --git a/packages/crypto/src/turnkey.ts b/packages/crypto/src/turnkey.ts index dd0298ee6..bc3573354 100644 --- a/packages/crypto/src/turnkey.ts +++ b/packages/crypto/src/turnkey.ts @@ -18,7 +18,7 @@ import { uncompressRawPublicKey, } from "./crypto"; -import { ed25519 } from '@noble/curves/ed25519'; +import { ed25519 } from "@noble/curves/ed25519"; interface DecryptExportBundleParams { exportBundle: string; @@ -168,7 +168,6 @@ export const decryptExportBundle = async ({ } }; - /** * Verifies a signature from a Turnkey stamp using ECDSA and SHA-256. *