Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions export-and-sign/dist/bundle.0cbce8a7d6902b1580a4.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions export-and-sign/dist/bundle.0cbce8a7d6902b1580a4.js.map

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions export-and-sign/dist/bundle.3337eb869c87d66e1eae.js

This file was deleted.

1 change: 0 additions & 1 deletion export-and-sign/dist/bundle.3337eb869c87d66e1eae.js.map

This file was deleted.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions export-and-sign/dist/bundle.91d8af54dfd168462387.js.map

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion export-and-sign/dist/bundle.a9ffbcf10c56fb6b6ec3.js.map

This file was deleted.

2 changes: 1 addition & 1 deletion export-and-sign/dist/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html class="no-js"><head><link rel="icon" type="image/svg+xml" href="./favicon.svg"/><meta charset="utf-8"/><title>Turnkey Export</title><meta name="viewport" content="width=device-width,initial-scale=1"/><meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; base-uri 'self'; object-src 'none'; form-action 'none'"><link href="/styles.e084a69a94c0575bc6ba.css" rel="stylesheet"></head><body><h2>Export Key Material</h2><p><em>This public key will be sent along with a private key ID or wallet ID inside of a new <code>EXPORT_PRIVATE_KEY</code> or <code>EXPORT_WALLET</code> activity</em></p><form><label>Embedded key</label> <input name="embedded-key" id="embedded-key" disabled="disabled"/> <button id="reset">Reset Key</button></form><br/><br/><br/><h2>Inject Key Export Bundle</h2><p><em>The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on <a target="_blank" href="https://datatracker.ietf.org/doc/rfc9180/">HPKE (RFC 9180)</a></em>.</p><form><label>Bundle</label> <input name="key-export-bundle" id="key-export-bundle"/> <button id="inject-key">Inject Bundle</button><br/><label>Key Format</label> <select id="key-export-format" name="key-export-format"><option value="HEXADECIMAL">Hexadecimal (Default)</option><option value="SOLANA">Solana</option></select><br/><label>Organization Id</label> <input name="key-organization-id" id="key-organization-id"/></form><br/><br/><h2>Inject Wallet Export Bundle</h2><p><em>The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on <a target="_blank" href="https://datatracker.ietf.org/doc/rfc9180/">HPKE (RFC 9180)</a></em>.</p><form><label>Bundle</label> <input name="wallet-export-bundle" id="wallet-export-bundle"/> <button id="inject-wallet">Inject Bundle</button><br/><label>Organization Id</label> <input name="wallet-organization-id" id="wallet-organization-id"/></form><br/><br/><h2>Sign Transaction</h2><p><em>Input a serialized transaction to sign.</em></p><form><label>Transaction</label> <input name="transaction-to-sign" id="transaction-to-sign"/> <button id="sign-transaction">Sign</button></form><br/><br/><h2>Sign Message</h2><p><em>Input a serialized message to sign.</em></p><form><label>Message</label> <input name="message-to-sign" id="message-to-sign"/> <button id="sign-message">Sign</button></form><br/><br/><h2>Message log</h2><p><em>Below we display a log of the messages sent / received. The forms above send messages, and the code communicates results by sending events via the <code>postMessage</code> API.</em></p><div id="message-log"></div><div id="key-div"></div><script defer="defer" src="/bundle.a9ffbcf10c56fb6b6ec3.js"></script><script defer="defer" src="/bundle.3337eb869c87d66e1eae.js"></script></body></html>
<!doctype html><html class="no-js"><head><link rel="icon" type="image/svg+xml" href="./favicon.svg"/><meta charset="utf-8"/><title>Turnkey Export</title><meta name="viewport" content="width=device-width,initial-scale=1"/><meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self'; base-uri 'self'; object-src 'none'; form-action 'none'"><link href="/styles.e084a69a94c0575bc6ba.css" rel="stylesheet"></head><body><h2>Export Key Material</h2><p><em>This public key will be sent along with a private key ID or wallet ID inside of a new <code>EXPORT_PRIVATE_KEY</code> or <code>EXPORT_WALLET</code> activity</em></p><form><label>Embedded key</label> <input name="embedded-key" id="embedded-key" disabled="disabled"/> <button id="reset">Reset Key</button></form><br/><br/><br/><h2>Inject Key Export Bundle</h2><p><em>The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on <a target="_blank" href="https://datatracker.ietf.org/doc/rfc9180/">HPKE (RFC 9180)</a></em>.</p><form><label>Bundle</label> <input name="key-export-bundle" id="key-export-bundle"/> <button id="inject-key">Inject Bundle</button><br/><label>Key Format</label> <select id="key-export-format" name="key-export-format"><option value="HEXADECIMAL">Hexadecimal (Default)</option><option value="SOLANA">Solana</option></select><br/><label>Organization Id</label> <input name="key-organization-id" id="key-organization-id"/></form><br/><br/><h2>Inject Wallet Export Bundle</h2><p><em>The export bundle comes from the parent page and is composed of a public key and an encrypted payload. The payload is encrypted to this document's embedded key (stored in local storage and displayed above). The scheme relies on <a target="_blank" href="https://datatracker.ietf.org/doc/rfc9180/">HPKE (RFC 9180)</a></em>.</p><form><label>Bundle</label> <input name="wallet-export-bundle" id="wallet-export-bundle"/> <button id="inject-wallet">Inject Bundle</button><br/><label>Organization Id</label> <input name="wallet-organization-id" id="wallet-organization-id"/></form><br/><br/><h2>Sign Transaction</h2><p><em>Input a serialized transaction to sign.</em></p><form><label>Transaction</label> <input name="transaction-to-sign" id="transaction-to-sign"/> <button id="sign-transaction">Sign</button></form><br/><br/><h2>Sign Message</h2><p><em>Input a serialized message to sign.</em></p><form><label>Message</label> <input name="message-to-sign" id="message-to-sign"/> <button id="sign-message">Sign</button></form><br/><br/><h2>Message log</h2><p><em>Below we display a log of the messages sent / received. The forms above send messages, and the code communicates results by sending events via the <code>postMessage</code> API.</em></p><div id="message-log"></div><div id="key-div"></div><script defer="defer" src="/bundle.91d8af54dfd168462387.js"></script><script defer="defer" src="/bundle.0cbce8a7d6902b1580a4.js"></script></body></html>
26 changes: 1 addition & 25 deletions export-and-sign/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions export-and-sign/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
"@noble/ed25519": "2.0.0",
"@noble/hashes": "1.3.2",
"@solana/web3.js": "1.98.4",
"@turnkey/crypto": "2.8.6",
"tweetnacl": "1.0.3",
"tweetnacl-util": "0.15.1"
"@turnkey/crypto": "2.8.6"
},
"devDependencies": {
"@babel/core": "7.23.0",
Expand Down
17 changes: 13 additions & 4 deletions export-and-sign/src/event-handlers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { TKHQ } from "./turnkey-core.js";
import { Keypair, VersionedTransaction } from "@solana/web3.js";
import nacl from "tweetnacl";
import * as nobleEd25519 from "@noble/ed25519";
import * as nobleHashes from "@noble/hashes/sha512";

import { HpkeDecrypt } from "./crypto-utils.js";

// Persist keys in memory via mapping of { address --> pk }
Expand Down Expand Up @@ -264,9 +266,16 @@ async function onSignMessage(requestId, serializedMessage, address) {
const keypair = await getOrCreateKeypair(key);

if (messageType === "SOLANA") {
// Sign the message
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);

// Set up sha512 for nobleEd25519 (required for signing)
nobleEd25519.etc.sha512Sync = (...m) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tiny nit: can we rename this variable (...m) for clarity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair, not pinning this on you

nobleHashes.sha512(nobleEd25519.etc.concatBytes(...m));

// Extract the 32-byte private key from the 64-byte secretKey
// Solana keypair.secretKey format: [32-byte private key][32-byte public key]
const privateKey = keypair.secretKey.slice(0, 32);
// Sign the message using nobleEd25519
const signature = nobleEd25519.sign(messageBytes, privateKey);

// Note: Signature verification is skipped for performance. The signature will always be valid if signing succeeds with a valid keypair.
// Clients can verify the signature returned.

Expand Down
Loading