Skip to content

Commit

Permalink
Merge pull request #226 from tkhq/olivia/key-format-param
Browse files Browse the repository at this point in the history
Apply key formatting
  • Loading branch information
Olivia Thet authored Mar 14, 2024
2 parents 24b0ace + 0a805e4 commit 7018e91
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/polite-eagles-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@turnkey/iframe-stamper": minor
---

Add optional keyFormat and publicKey parameters to injectKeyExportBundle. Add extractKeyEncryptedBundle.
80 changes: 75 additions & 5 deletions packages/iframe-stamper/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,22 @@ export enum IframeEventType {
InjectCredentialBundle = "INJECT_CREDENTIAL_BUNDLE",
// Event sent by the parent to inject a private key export bundle into the iframe.
// Value: the bundle to inject
// Key Format (optional): the key format to encode the private key in after it's exported and decrypted: HEXADECIMAL or SOLANA. Defaults to HEXADECIMAL.
// Public Key (optional): the public key of the exported private key. Required when the key format is SOLANA.
InjectKeyExportBundle = "INJECT_KEY_EXPORT_BUNDLE",
// Event sent by the parent to inject a wallet export bundle into the iframe.
// Value: the bundle to inject
InjectWalletExportBundle = "INJECT_WALLET_EXPORT_BUNDLE",
// Event sent by the parent to inject an import bundle into the iframe.
// Value: the bundle to inject
InjectImportBundle = "INJECT_IMPORT_BUNDLE",
// Event sent by the parent to extract an encrypted bundle from the iframe.
// Value: the bundle to inject
// Event sent by the parent to extract an encrypted wallet bundle from the iframe.
// Value: none
ExtractWalletEncryptedBundle = "EXTRACT_WALLET_ENCRYPTED_BUNDLE",
// Event sent by the parent to extract an encrypted private key bundle from the iframe.
// Value: none
// Key Format (optional): the key format to decode the private key in before it's encrypted for import: HEXADECIMAL or SOLANA. Defaults to HEXADECIMAL.
ExtractKeyEncryptedBundle = "EXTRACT_KEY_ENCRYPTED_BUNDLE",
// Event sent by the iframe to its parent when `InjectBundle` is successful
// Value: true (boolean)
BundleInjected = "BUNDLE_INJECTED",
Expand All @@ -40,6 +46,15 @@ export enum IframeEventType {
Error = "ERROR",
}

// Set of constants for private key formats. These formats map to the encoding type used on a private key before encrypting and importing it
// or after exporting it and decrypting it.
export enum KeyFormat {
// 64 hexadecimal digits. Key format used by MetaMask, MyEtherWallet, Phantom, Ledger, and Trezor for Ethereum and Tron keys
Hexadecimal = "HEXADECIMAL",
// Key format used by Phantom and Solflare for Solana keys
Solana = "SOLANA",
}

type TStamp = {
stampHeaderName: string;
stampHeaderValue: string;
Expand Down Expand Up @@ -171,13 +186,21 @@ export class IframeStamper {
* Function to inject an export bundle into the iframe
* The bundle should be encrypted to the iframe's initial public key
* Encryption should be performed with HPKE (RFC 9180).
* This is used during export flows.
* The key format to encode the private key in after it's exported and decrypted: HEXADECIMAL or SOLANA. Defaults to HEXADECIMAL.
* The public key of the exported private key. Required when the key format is SOLANA.
* This is used during the private key export flow.
*/
async injectKeyExportBundle(bundle: string): Promise<boolean> {
async injectKeyExportBundle(
bundle: string,
keyFormat?: KeyFormat,
publicKey?: string
): Promise<boolean> {
this.iframe.contentWindow?.postMessage(
{
type: IframeEventType.InjectKeyExportBundle,
value: bundle,
keyFormat: keyFormat,
publicKey: publicKey,
},
"*"
);
Expand Down Expand Up @@ -207,7 +230,7 @@ export class IframeStamper {
* Function to inject an export bundle into the iframe
* The bundle should be encrypted to the iframe's initial public key
* Encryption should be performed with HPKE (RFC 9180).
* This is used during export flows.
* This is used during the wallet export flow.
*/
async injectWalletExportBundle(bundle: string): Promise<boolean> {
this.iframe.contentWindow?.postMessage(
Expand Down Expand Up @@ -239,6 +262,10 @@ export class IframeStamper {
});
}

/**
* Function to inject an import bundle into the iframe
* This is used to initiate either the wallet import flow or the private key import flow.
*/
async injectImportBundle(bundle: string): Promise<boolean> {
this.iframe.contentWindow?.postMessage(
{
Expand Down Expand Up @@ -269,6 +296,12 @@ export class IframeStamper {
});
}

/**
* Function to extract an encrypted bundle from the iframe
* The bundle should be encrypted to Turnkey's Signer enclave's initial public key
* Encryption should be performed with HPKE (RFC 9180).
* This is used during the wallet import flow.
*/
async extractWalletEncryptedBundle(): Promise<string> {
this.iframe.contentWindow?.postMessage(
{
Expand Down Expand Up @@ -298,6 +331,43 @@ export class IframeStamper {
});
}

/**
* Function to extract an encrypted bundle from the iframe
* The bundle should be encrypted to Turnkey's Signer enclave's initial public key
* Encryption should be performed with HPKE (RFC 9180).
* The key format to encode the private key in before it's encrypted and imported: HEXADECIMAL or SOLANA. Defaults to HEXADECIMAL.
* This is used during the private key import flow.
*/
async extractKeyEncryptedBundle(keyFormat?: KeyFormat): Promise<string> {
this.iframe.contentWindow?.postMessage(
{
type: IframeEventType.ExtractKeyEncryptedBundle,
keyFormat: keyFormat,
},
"*"
);

return new Promise((resolve, reject) => {
window.addEventListener(
"message",
(event) => {
if (event.origin !== this.iframeOrigin) {
// There might be other things going on in the window, for example: react dev tools, other extensions, etc.
// Instead of erroring out we simply return. Not our event!
return;
}
if (event.data?.type === IframeEventType.EncryptedBundleExtracted) {
resolve(event.data["value"]);
}
if (event.data?.type === IframeEventType.Error) {
reject(event.data["value"]);
}
},
false
);
});
}

/**
* Function to sign a payload with the underlying iframe
*/
Expand Down

0 comments on commit 7018e91

Please sign in to comment.