Skip to content
Open
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
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
'export-and-sign',
'oauth-origin',
'oauth-redirect',
'shared',
]

steps:
Expand Down Expand Up @@ -56,6 +57,7 @@ jobs:
'export-and-sign',
'oauth-origin',
'oauth-redirect',
'shared',
]

steps:
Expand Down Expand Up @@ -88,6 +90,7 @@ jobs:
'export-and-sign',
'oauth-origin',
'oauth-redirect',
'shared',
]

steps:
Expand Down Expand Up @@ -127,6 +130,10 @@ jobs:
with:
node-version: 20

- name: Install Dependencies for shared
working-directory: ./shared
run: npm install

- name: Install Dependencies for ${{ matrix.directory }}
working-directory: ./${{ matrix.directory }}
run: npm install
Expand Down
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ FROM node:18-bullseye-slim AS builder

WORKDIR /app

# Copy shared directory first (needed by export-and-sign and import)
COPY shared ./shared/
RUN cd shared && npm ci

# Copy export-and-sign module and build
COPY export-and-sign ./export-and-sign/
RUN cd export-and-sign && npm ci && npm run build
Expand Down
3 changes: 0 additions & 3 deletions export-and-sign/dist/bundle.097e0ebaa457290cf7ae.js

This file was deleted.

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

This file was deleted.

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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,6 @@ See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */

/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
Expand Down
1 change: 1 addition & 0 deletions export-and-sign/dist/bundle.37504fa28b8650ea5862.js.map

Large diffs are not rendered by default.

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

This file was deleted.

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

This file was deleted.

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

Large diffs are not rendered by default.

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

Large diffs are not rendered by default.

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" integrity="sha384-uIrxQTbBoDAwjgotQ+GUHgbxFM2iajB5QKNa4WuL9wn/Ou+2383e3dM2FCWOAq9m" crossorigin="anonymous"></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.a4914ea66ee78b95f2e4.js" integrity="sha384-m+x1rhXXvkLoGv9xomRsrJbUk7MLDp/73HeX5mp9nUtuVwRJr/fqj2i0+cgwS8tY" crossorigin="anonymous"></script><script defer="defer" src="/bundle.097e0ebaa457290cf7ae.js" integrity="sha384-D+pFv2oBVVDPOi5euMko5l16r/lvWCZQB8YqIo8IasJIforNx2BGNsP1XlrOS1dw" crossorigin="anonymous"></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" integrity="sha384-uIrxQTbBoDAwjgotQ+GUHgbxFM2iajB5QKNa4WuL9wn/Ou+2383e3dM2FCWOAq9m" crossorigin="anonymous"></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.37504fa28b8650ea5862.js" integrity="sha384-jg2exvgXMuysxOkDLxkx3QdkSi0CFq6QmFvWMH61H6Kgo8SUEnST3y6yCzatCDqm" crossorigin="anonymous"></script><script defer="defer" src="/bundle.b7cebf9fa57ae3a80e45.js" integrity="sha384-Wr6lxQIg/U9Rr0GHR4+rIkG4rWi1vEwcgsASEVIfYOjtDolu5KWBqvKJGWQZjhyq" crossorigin="anonymous"></script></body></html>
5 changes: 5 additions & 0 deletions export-and-sign/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
const path = require("path");

module.exports = {
clearMocks: true,
setupFilesAfterEnv: ["regenerator-runtime/runtime"],
testPathIgnorePatterns: ["/node_modules/"],
transformIgnorePatterns: ["node_modules/(?!(@noble|@hpke)/)"],
moduleNameMapper: {
"^@shared/(.*)$": path.resolve(__dirname, "../shared/$1"),
},
};
46 changes: 5 additions & 41 deletions export-and-sign/package-lock.json

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

3 changes: 2 additions & 1 deletion export-and-sign/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"dependencies": {
"@hpke/core": "1.7.5",
"@noble/ed25519": "2.0.0",
"@noble/hashes": "1.3.2",
"@noble/hashes": "1.8.0",
"@solana/web3.js": "1.98.4",
"@turnkey/crypto": "2.8.6"
},
Expand Down Expand Up @@ -50,6 +50,7 @@
"@hpke/common": "1.8.1",
"@noble/ciphers": "1.3.0",
"@noble/curves": "1.9.7",
"@noble/hashes": "1.8.0",
"@peculiar/x509": "1.12.3",
"@solana/buffer-layout": "4.0.1",
"@solana/codecs-numbers": "2.3.0",
Expand Down
54 changes: 2 additions & 52 deletions export-and-sign/src/crypto-utils.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,2 @@
import { TKHQ } from "./turnkey-core.js";
import {
CipherSuite,
DhkemP256HkdfSha256,
HkdfSha256,
Aes256Gcm,
} from "@hpke/core";

// Pre-compute const (for perf)
const TURNKEY_HPKE_INFO = new TextEncoder().encode("turnkey_hpke");

/**
* Decrypt the ciphertext (ArrayBuffer) given an encapsulation key (ArrayBuffer)
* and the receivers private key (JSON Web Key).
*/
export async function HpkeDecrypt({
ciphertextBuf,
encappedKeyBuf,
receiverPrivJwk,
}) {
const kemContext = new DhkemP256HkdfSha256();
var receiverPriv = await kemContext.importKey(
"jwk",
{ ...receiverPrivJwk },
false
);

var suite = new CipherSuite({
kem: kemContext,
kdf: new HkdfSha256(),
aead: new Aes256Gcm(),
});

var recipientCtx = await suite.createRecipientContext({
recipientKey: receiverPriv,
enc: encappedKeyBuf,
info: TURNKEY_HPKE_INFO,
});

var receiverPubBuf = await TKHQ.p256JWKPrivateToPublic(receiverPrivJwk);
var aad = TKHQ.additionalAssociatedData(encappedKeyBuf, receiverPubBuf);
var res;
try {
res = await recipientCtx.open(ciphertextBuf, aad);
} catch (e) {
throw new Error(
"unable to decrypt bundle using embedded key. the bundle may be incorrect. failed with error: " +
e.toString()
);
}
return res;
}
// Re-export from shared crypto-utils
export { HpkeDecrypt } from "@shared/crypto-utils.js";
Loading
Loading