Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tkhq/sdk/llms.txt
Use this file to discover all available pages before exploring further.
@turnkey/crypto provides pure-JS cryptographic primitives used internally across Turnkey SDK packages. It covers P-256 (secp256r1) key generation, HPKE (Hybrid Public Key Encryption) encrypt/decrypt, signature format conversion, and bundle encryption/decryption for wallet import and export flows.
This is primarily an internal package. Most application developers do not need to import it directly. If you are building a wallet import/export UI, use the higher-level helpers in @turnkey/sdk-browser or @turnkey/iframe-stamper instead of calling these functions yourself.
Installation
npm install @turnkey/crypto
Key generation
generateP256KeyPair
Generates a random P-256 key pair. Returns hex-encoded keys in compressed and uncompressed forms.
import { generateP256KeyPair } from "@turnkey/crypto";
const keyPair = generateP256KeyPair();
// keyPair.privateKey — 64-char hex string
// keyPair.publicKey — 66-char hex string (compressed, 02 or 03 prefix)
// keyPair.publicKeyUncompressed — 130-char hex string (04 prefix)
32-byte private key as a hex string.
33-byte compressed public key as a hex string.
65-byte uncompressed public key as a hex string (prefixed with 04).
getPublicKey
Derives a P-256 public key from a private key.
import { getPublicKey } from "@turnkey/crypto";
const publicKey = getPublicKey(privateKeyBytes, true); // compressed
const pubKeyUncompressed = getPublicKey(privateKeyBytes, false); // uncompressed
privateKey
Uint8Array | string
required
The private key as a Uint8Array or hex string.
Whether to return a compressed (33-byte) or uncompressed (65-byte) public key. Defaults to true.
compressRawPublicKey / uncompressRawPublicKey
Convert between compressed and uncompressed public key formats.
import { compressRawPublicKey, uncompressRawPublicKey } from "@turnkey/crypto";
// 65-byte uncompressed → 33-byte compressed
const compressed = compressRawPublicKey(uncompressedBytes);
// 33-byte compressed → 65-byte uncompressed
const uncompressed = uncompressRawPublicKey(compressedBytes);
// Second argument specifies curve: "CURVE_P256" (default) or "CURVE_SECP256K1"
const uncompressedK1 = uncompressRawPublicKey(compressedBytes, "CURVE_SECP256K1");
HPKE encryption
HPKE (RFC 9180) is used to encrypt key material for Turnkey’s wallet import and export flows.
hpkeEncrypt
Encrypts a plaintext buffer to an uncompressed P-256 target public key using an ephemeral sender key pair (standard HPKE mode).
import { hpkeEncrypt } from "@turnkey/crypto";
const encryptedBuf = hpkeEncrypt({
plainTextBuf: new TextEncoder().encode("secret"),
targetKeyBuf: receiverPublicKeyUncompressed, // Uint8Array, uncompressed
});
// Returns: Uint8Array — first 33 bytes are compressed sender public key,
// remaining bytes are the ciphertext
hpkeAuthEncrypt
Encrypts with an authenticated sender private key (authenticated HPKE mode).
import { hpkeAuthEncrypt } from "@turnkey/crypto";
const encryptedBuf = hpkeAuthEncrypt({
plainTextBuf: new TextEncoder().encode("secret"),
targetKeyBuf: receiverPublicKeyUncompressed,
senderPriv: senderKeyPair.privateKey, // hex string
});
hpkeDecrypt
Decrypts a ciphertext encrypted with hpkeEncrypt or hpkeAuthEncrypt.
import { hpkeDecrypt } from "@turnkey/crypto";
const decryptedData = hpkeDecrypt({
ciphertextBuf, // Uint8Array
encappedKeyBuf, // Uint8Array — uncompressed sender public key
receiverPriv, // hex string — receiver private key
});
Formats the output of hpkeEncrypt / hpkeAuthEncrypt into a JSON string with separated encappedPublic and ciphertext hex fields, as expected by Turnkey bundle APIs.
import { formatHpkeBuf } from "@turnkey/crypto";
const bundle = formatHpkeBuf(encryptedBuf);
// Returns: JSON string: { "encappedPublic": "<hex>", "ciphertext": "<hex>" }
End-to-end HPKE example
import {
generateP256KeyPair,
uncompressRawPublicKey,
hpkeEncrypt,
hpkeDecrypt,
} from "@turnkey/crypto";
import { uint8ArrayFromHexString } from "@turnkey/encoding";
const senderKeyPair = generateP256KeyPair();
const receiverKeyPair = generateP256KeyPair();
const receiverPublicKeyUncompressed = uncompressRawPublicKey(
uint8ArrayFromHexString(receiverKeyPair.publicKey),
);
const plainText = "Hello, this is a secure message!";
const plainTextBuf = new TextEncoder().encode(plainText);
const encryptedData = hpkeEncrypt({
plainTextBuf,
targetKeyBuf: receiverPublicKeyUncompressed,
});
// Extract the encapsulated key buffer and the ciphertext
const encappedKeyBuf = encryptedData.slice(0, 33);
const ciphertextBuf = encryptedData.slice(33);
const decryptedData = hpkeDecrypt({
ciphertextBuf,
encappedKeyBuf: uncompressRawPublicKey(encappedKeyBuf),
receiverPriv: receiverKeyPair.privateKey,
});
const decryptedText = new TextDecoder().decode(decryptedData);
// decryptedText === "Hello, this is a secure message!"
Bundle utilities
These higher-level functions handle the full bundle encrypt/decrypt flow including enclave signature verification.
encryptPrivateKeyToBundle
Encrypts a raw private key for import into Turnkey. Verifies the enclave signature before encrypting.
import { encryptPrivateKeyToBundle } from "@turnkey/crypto";
const bundle = await encryptPrivateKeyToBundle({
privateKey: "<hex or base58 private key>",
keyFormat: "HEXADECIMAL", // or "SOLANA"
importBundle: "<JSON import bundle from Turnkey API>",
userId: "<user-id>",
organizationId: "<org-id>",
});
encryptWalletToBundle
Encrypts a BIP-39 mnemonic for wallet import.
import { encryptWalletToBundle } from "@turnkey/crypto";
const bundle = await encryptWalletToBundle({
mnemonic: "word1 word2 ... word24",
importBundle: "<JSON import bundle from Turnkey API>",
userId: "<user-id>",
organizationId: "<org-id>",
});
decryptExportBundle
Decrypts an encrypted export bundle returned by the Turnkey API. Verifies the enclave signature.
import { decryptExportBundle } from "@turnkey/crypto";
const mnemonic = await decryptExportBundle({
exportBundle: "<JSON export bundle from Turnkey API>",
embeddedKey: "<receiver private key hex>",
organizationId: "<org-id>",
returnMnemonic: true, // false returns raw hex private key
keyFormat: "HEXADECIMAL", // or "SOLANA"
});
decryptCredentialBundle
Decrypts an email auth or OAuth credential bundle.
import { decryptCredentialBundle } from "@turnkey/crypto";
const credential = decryptCredentialBundle(
credentialBundle, // bs58check-encoded bundle
embeddedKey, // receiver private key hex
);
// Returns decrypted data as a hex string
Signature utilities
verifyStampSignature
Verifies an ECDSA P-256 signature from a Turnkey stamp.
import { verifyStampSignature } from "@turnkey/crypto";
const isValid = await verifyStampSignature(
publicKey, // hex string
signature, // DER-encoded ECDSA signature hex string
signedData, // the original data that was signed
);
toDerSignature / fromDerSignature
Convert between raw (r‖s) and ASN.1 DER-encoded ECDSA signature formats.
import { toDerSignature, fromDerSignature } from "@turnkey/crypto";
// Raw hex r||s → DER hex
const derHex = toDerSignature(rawSignatureHex);
// DER hex → raw Uint8Array (r||s)
const rawBytes = fromDerSignature(derSignatureHex);
verifySessionJwtSignature
Verifies a session JWT signature against Turnkey’s production notarizer key.
import { verifySessionJwtSignature } from "@turnkey/crypto";
const isValid = await verifySessionJwtSignature(jwt);
Attestation verification
For advanced use cases, @turnkey/crypto also exports functions for verifying Turnkey enclave attestation proofs:
import {
verify, // Verify app proof + boot proof pair
verifyAppProofSignature, // Verify only the app proof signature
verifyCertificateChain, // Verify AWS Nitro certificate chain
verifyCoseSign1Sig, // Verify COSE_Sign1 attestation signature
} from "@turnkey/crypto";
See Turnkey’s whitepaper for details on the attestation model.