Skip to content

Commit

Permalink
fix import of receiver pub jwk in hpke encrypt
Browse files Browse the repository at this point in the history
  • Loading branch information
Olivia Thet committed Feb 28, 2024
1 parent 487de21 commit f4483d7
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 53 deletions.
61 changes: 36 additions & 25 deletions import/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
textarea {
#wallet-mnemonic-plaintext {
width: 400px;
margin: 0.5em;
font-size: .875rem;
Expand All @@ -32,7 +32,7 @@

<body>
<form>
<textarea name="wallet-bundle" id="wallet-bundle"></textarea>
<textarea name="wallet-mnemonic-plaintext" id="wallet-mnemonic-plaintext"></textarea>
</form>

<!--
Expand Down Expand Up @@ -154,7 +154,6 @@
}
}


return {
importTargetKey,
setItemWithExpiry,
Expand Down Expand Up @@ -207,31 +206,42 @@

/**
* Function triggered when INJECT_IMPORT_BUNDLE event is received.
* Parses the `import_bundle` and stores the target public key as a JWK
* in local storage. Sends true upon success.
* @param {string} bundle
* Example: {"targetPublic":"0491ccb68758b822a6549257f87769eeed37c6cb68a6c6255c5f238e2b6e6e61838c8ac857f2e305970a6435715f84e5a2e4b02a4d1e5289ba7ec7910e47d2d50f","targetPublicSignature":"3045022100cefc333c330c9fa300d1aa10a439a76539b4d6967301638ab9edc9fd9468bfdb0220339bba7e2b00b45d52e941d068ecd3bfd16fd1926da69dd7769893268990d62f"}
* Example bundle: {"targetPublic":"0491ccb68758b822a6549257f87769eeed37c6cb68a6c6255c5f238e2b6e6e61838c8ac857f2e305970a6435715f84e5a2e4b02a4d1e5289ba7ec7910e47d2d50f","targetPublicSignature":"3045022100cefc333c330c9fa300d1aa10a439a76539b4d6967301638ab9edc9fd9468bfdb0220339bba7e2b00b45d52e941d068ecd3bfd16fd1926da69dd7769893268990d62f"}
*/
const onInjectImportBundle = async bundle => {
// Parse the import bundle
const bundleObj = JSON.parse(bundle);
const targetPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublic);
const onInjectImportBundle = async bundle => {
// Parse the import bundle
const bundleObj = JSON.parse(bundle);
const targetPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublic);

// Import target public key generated from enclave and set in local storage
const targetPublicKeyJwk = await TKHQ.importTargetKey(new Uint8Array(targetPublicBuf));
TKHQ.setTargetEmbeddedKey(targetPublicKeyJwk);
// Import target public key generated from enclave and set in local storage
const targetPublicKeyJwk = await TKHQ.importTargetKey(new Uint8Array(targetPublicBuf));
TKHQ.setTargetEmbeddedKey(targetPublicKeyJwk);

// todo(olivia): verify the signature with the enclave quorum public key once returned in server messages
// const targetSignatureBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublicSignature);
// const quorumPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.enclaveQuorumPublic);
// const quorumKey = TKHQ.importTargetKey(new Uint8Array(quorumPublicBuf));
// const verified = await crypto.subtle.verify(quorumKey, targetSignatureBuf, targetPublicBuf);
// if (verified === false) {
// throw new Error("verification failed");
// }
// todo(olivia): verify the signature with the enclave quorum public key once returned in server messages
// const targetSignatureBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublicSignature);
// const quorumPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.enclaveQuorumPublic);
// const quorumKey = TKHQ.importTargetKey(new Uint8Array(quorumPublicBuf));
// const verified = await crypto.subtle.verify(quorumKey, targetSignatureBuf, targetPublicBuf);
// if (verified === false) {
// throw new Error("verification failed");
// }

// Send up BUNDLE_INJECTED message
TKHQ.sendMessageUp("BUNDLE_INJECTED", true)
// Send up BUNDLE_INJECTED message
TKHQ.sendMessageUp("BUNDLE_INJECTED", true)
}

/**
* Function triggered when EXTRACT_WALLET_ENCRYPTED_BUNDLE event is received.
* Prerequisite: This function uses the target public key in local storage that is imported
* from the INJECT_IMPORT_BUNDLE event.
* Uses the target public key in local storage to encrypt the text entered in the
* `wallet-mnemonic-plaintext` textarea element. Upon successful encryption, sends
* an `encrypted_bundle` containing the ciphertext and encapped public key.
* Example bundle: {"encappedPublic":"0497f33f3306f67f4402d4824e15b63b04786b6558d417aac2fef69051e46fa7bfbe776b142e4ded4f02097617a7588e93c53b71f900a4a8831a31be6f95e5f60f","ciphertext":"c17c3085505f3c094f0fa61791395b83ab1d8c90bdf9f12a64fc6e2e9cba266beb528f65c88bd933e36e6203752a9b63e6a92290a0ab6bf0ed591cf7bfa08006001e2cc63870165dc99ec61554ffdc14dea7d567e62cceed29314ae6c71a013843f5c06146dee5bf9c1d"}
*/
const onExtractWalletEncryptedBundle = async () => {
// Get target embedded key from previous step (onInjectImportBundle)
const targetPublicKeyJwk = TKHQ.getTargetEmbeddedKey();
Expand All @@ -240,7 +250,7 @@
}

// Get plaintext wallet seedphrase
const plaintext = document.getElementById("wallet-bundle").value;
const plaintext = document.getElementById("wallet-mnemonic-plaintext").value;
const plaintextBuf = new TextEncoder().encode(plaintext);

// Encrypt the bundle using the enclave target public key
Expand All @@ -266,18 +276,19 @@

const senderCtx = await suite.createSenderContext({
recipientPublicKey: receiverPub,
info: new TextEncoder().encode("turnkey_hpke"),
});

// Need to import the key again as a JWK to export as a raw key, the format needed to
// create the aad with the newly generated raw encapped key.
const receiverPubCryptoKey = await crypto.subtle.importKey("jwk", receiverPubJwk, {
name: 'ECDH',
name: 'ECDSA',
namedCurve: 'P-256',
}, true, []);
const receiverPubRaw = await crypto.subtle.exportKey("raw", receiverPubCryptoKey);
const receiverPubBuf = new Uint8Array(receiverPubRaw);

const encappedKeyBuf = senderCtx.enc;
const encappedKeyBuf = new Uint8Array(senderCtx.enc);

const aad = TKHQ.additionalAssociatedData(encappedKeyBuf, receiverPubBuf);

Expand All @@ -289,7 +300,7 @@
}

const ciphertextHex = TKHQ.uint8arrayToHexString(new Uint8Array(ciphertextBuf));
const encappedKeyBufHex = TKHQ.uint8arrayToHexString(new Uint8Array(encappedKeyBuf));
const encappedKeyBufHex = TKHQ.uint8arrayToHexString(encappedKeyBuf);
const encryptedBundle = JSON.stringify({ encappedPublic: encappedKeyBufHex, ciphertext: ciphertextHex })
return encryptedBundle
}
Expand Down
70 changes: 42 additions & 28 deletions import/standalone.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ <h2>Bundles</h2>
<br>
<form>
<label>Encrypted Bundle</label>
<input type="text" name="wallet-bundle" id="wallet-bundle"/>
<input type="text" name="wallet-mnemonic-plaintext" id="wallet-mnemonic-plaintext"/>
<button id="encrypt-wallet-bundle">Encrypt Bundle</button>
</form>
<br>
Expand Down Expand Up @@ -277,43 +277,53 @@ <h2>Message log</h2>
e.preventDefault();
window.postMessage({
"type": "EXTRACT_WALLET_ENCRYPTED_BUNDLE",
"value": document.getElementById("wallet-bundle").value,
"value": document.getElementById("wallet-mnemonic-plaintext").value,
})
}, false);
}, false);

/**
* Function triggered when INJECT_IMPORT_BUNDLE event is received.
* Parses the `import_bundle` and stores the target public key as a JWK
* in local storage. Sends true upon success.
* @param {string} bundle
* Example: {"targetPublic":"0491ccb68758b822a6549257f87769eeed37c6cb68a6c6255c5f238e2b6e6e61838c8ac857f2e305970a6435715f84e5a2e4b02a4d1e5289ba7ec7910e47d2d50f","targetPublicSignature":"3045022100cefc333c330c9fa300d1aa10a439a76539b4d6967301638ab9edc9fd9468bfdb0220339bba7e2b00b45d52e941d068ecd3bfd16fd1926da69dd7769893268990d62f"}
* Example bundle: {"targetPublic":"0491ccb68758b822a6549257f87769eeed37c6cb68a6c6255c5f238e2b6e6e61838c8ac857f2e305970a6435715f84e5a2e4b02a4d1e5289ba7ec7910e47d2d50f","targetPublicSignature":"3045022100cefc333c330c9fa300d1aa10a439a76539b4d6967301638ab9edc9fd9468bfdb0220339bba7e2b00b45d52e941d068ecd3bfd16fd1926da69dd7769893268990d62f"}
*/
const onInjectImportBundle = async bundle => {
// Parse the import bundle
const bundleObj = JSON.parse(bundle);
const targetPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublic);
const onInjectImportBundle = async bundle => {
// Parse the import bundle
const bundleObj = JSON.parse(bundle);
const targetPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublic);

// Import target public key generated from enclave and set in local storage
const targetKeyJwk = await TKHQ.importTargetKey(new Uint8Array(targetPublicBuf));
TKHQ.setTargetEmbeddedKey(targetKeyJwk);
// Import target public key generated from enclave and set in local storage
const targetPublicKeyJwk = await TKHQ.importTargetKey(new Uint8Array(targetPublicBuf));
TKHQ.setTargetEmbeddedKey(targetPublicKeyJwk);

// todo(olivia): verify the signature with the enclave quorum public key
// const targetSignatureBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublicSignature);
// const quorumPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.quorumPublic);
// const quorumKey = TKHQ.importTargetKey(new Uint8Array(quorumPublicBuf));
// const verified = await crypto.subtle.verify(quorumKey, targetSignatureBuf, targetPublicBuf);
// if (verified === false) {
// throw new Error("verification failed: " + e);
// }
// todo(olivia): verify the signature with the enclave quorum public key once returned in server messages
// const targetSignatureBuf = TKHQ.uint8arrayFromHexString(bundleObj.targetPublicSignature);
// const quorumPublicBuf = TKHQ.uint8arrayFromHexString(bundleObj.enclaveQuorumPublic);
// const quorumKey = TKHQ.importTargetKey(new Uint8Array(quorumPublicBuf));
// const verified = await crypto.subtle.verify(quorumKey, targetSignatureBuf, targetPublicBuf);
// if (verified === false) {
// throw new Error("verification failed");
// }

// Send up BUNDLE_INJECTED message
TKHQ.sendMessageUp("BUNDLE_INJECTED", true)
// Send up BUNDLE_INJECTED message
TKHQ.sendMessageUp("BUNDLE_INJECTED", true)
}

// todo: make a pretty box that is to be displayed
/**
* Function triggered when EXTRACT_WALLET_ENCRYPTED_BUNDLE event is received.
* Prerequisite: This function uses the target public key in local storage that is imported
* from the INJECT_IMPORT_BUNDLE event.
* Uses the target public key in local storage to encrypt the text entered in the
* `wallet-mnemonic-plaintext` textarea element. Upon successful encryption, sends
* an `encrypted_bundle` containing the ciphertext and encapped public key.
* Example bundle: {"encappedPublic":"0497f33f3306f67f4402d4824e15b63b04786b6558d417aac2fef69051e46fa7bfbe776b142e4ded4f02097617a7588e93c53b71f900a4a8831a31be6f95e5f60f","ciphertext":"c17c3085505f3c094f0fa61791395b83ab1d8c90bdf9f12a64fc6e2e9cba266beb528f65c88bd933e36e6203752a9b63e6a92290a0ab6bf0ed591cf7bfa08006001e2cc63870165dc99ec61554ffdc14dea7d567e62cceed29314ae6c71a013843f5c06146dee5bf9c1d"}
*/
const onExtractWalletEncryptedBundle = async bundle => {
// Get target embedded key from previous step (onInjectImportBundle)
const targetKeyJwk = TKHQ.getTargetEmbeddedKey();
if (targetKeyJwk == null) {
const targetPublicKeyJwk = TKHQ.getTargetEmbeddedKey();
if (targetPublicKeyJwk == null) {
throw new Error("no target key found");
}

Expand All @@ -322,7 +332,7 @@ <h2>Message log</h2>
const encryptedBundle = await HpkeEncrypt(
{
plaintextBuf,
receiverPubJwk: targetKeyJwk,
receiverPubJwk: targetPublicKeyJwk,
});

// Send up ENCRYPTED_BUNDLE_EXTRACTED message
Expand All @@ -341,16 +351,20 @@ <h2>Message log</h2>

const senderCtx = await suite.createSenderContext({
recipientPublicKey: receiverPub,
info: new TextEncoder().encode("turnkey_hpke"),
});

const encappedKeyBuf = senderCtx.enc;
// Need to import the key again as a JWK to export as a raw key, the format needed to
// create the aad with the newly generated raw encapped key.
const receiverPubCryptoKey = await crypto.subtle.importKey("jwk", receiverPubJwk, {
name: 'ECDH',
name: 'ECDSA',
namedCurve: 'P-256',
}, true, []);
const receiverPubRaw = await crypto.subtle.exportKey("raw", receiverPubCryptoKey);
const receiverPubBuf = new Uint8Array(receiverPubRaw);

const encappedKeyBuf = new Uint8Array(senderCtx.enc);

const aad = TKHQ.additionalAssociatedData(encappedKeyBuf, receiverPubBuf);

var ciphertextBuf;
Expand All @@ -361,10 +375,10 @@ <h2>Message log</h2>
}

const ciphertextHex = TKHQ.uint8arrayToHexString(new Uint8Array(ciphertextBuf));
const encappedKeyBufHex = TKHQ.uint8arrayToHexString(new Uint8Array(encappedKeyBuf));
const encappedKeyBufHex = TKHQ.uint8arrayToHexString(encappedKeyBuf);
const encryptedBundle = JSON.stringify({ encappedPublic: encappedKeyBufHex, ciphertext: ciphertextHex })
return encryptedBundle
}
</script>
</body>
</html>
</html>

0 comments on commit f4483d7

Please sign in to comment.