diff --git a/export/index.template.html b/export/index.template.html index c2b1af5..4b36709 100644 --- a/export/index.template.html +++ b/export/index.template.html @@ -328,8 +328,11 @@

Message log

/** * Function to verify enclave signature on import bundle received from the server. + * @param {string} enclaveQuorumPublic uncompressed public key for the quorum key which produced the signature + * @param {string} publicSignature signature bytes encoded as a hexadecimal string + * @param {string} signedData signed bytes encoded as a hexadecimal string. This could be public key bytes directly, or JSON-encoded bytes */ - async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { + async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, signedData) { /** Turnkey Signer enclave's public keys */ const TURNKEY_SIGNERS_ENCLAVES = { "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", @@ -355,8 +358,8 @@

Message log

// The ECDSA signature is ASN.1 DER encoded but WebCrypto uses raw format const publicSignatureBuf = fromDerSignature(publicSignature); - const publicKeyBuf = uint8arrayFromHexString(publicKey); - return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, publicKeyBuf); + const signedDataBuf = uint8arrayFromHexString(signedData); + return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, signedDataBuf); } /** @@ -742,7 +745,19 @@

Message log

if (!TKHQ.verifyEnclaveSignature) { throw new Error("method not loaded"); } - verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, bundleObj.data.encappedPublic); + + // Temporary solution to get the bytes signed by the enclave + var signedData = /"data":({[^}]+)/.exec(bundle); + if (signedData === null || signedData.length !== 2) { + throw new Error(`unable to find signed data in bundle: ${bundle}`); + } + + // We add the closing brace back: it was our marker for the end of the group in the regex above, hence not captured. + const signedDataBytes = new TextEncoder().encode(signedData[1] + "}"); + // Encode these bytes to hex since verifyEnclaveSignature expects hex-encoded bytes + const signedDataHexString = TKHQ.uint8arrayToHexString(signedDataBytes); + + verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, signedDataHexString); if (!verified) { throw new Error(`failed to verify enclave signature: ${bundle}`); } diff --git a/import/index.template.html b/import/index.template.html index 5d5f5c7..9de340f 100644 --- a/import/index.template.html +++ b/import/index.template.html @@ -285,8 +285,11 @@ /** * Function to verify enclave signature on import bundle received from the server. + * @param {string} enclaveQuorumPublic uncompressed public key for the quorum key which produced the signature + * @param {string} publicSignature signature bytes encoded as a hexadecimal string + * @param {string} signedData signed bytes encoded as a hexadecimal string. This could be public key bytes directly, or JSON-encoded bytes */ - async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { + async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, signedData) { /** Turnkey Signer enclave's public keys */ const TURNKEY_SIGNERS_ENCLAVES = { "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", @@ -312,8 +315,8 @@ // The ECDSA signature is ASN.1 DER encoded but WebCrypto uses raw format const publicSignatureBuf = fromDerSignature(publicSignature); - const publicKeyBuf = uint8arrayFromHexString(publicKey); - return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, publicKeyBuf); + const signedDataBuf = uint8arrayFromHexString(signedData); + return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, signedDataBuf); } /** @@ -546,7 +549,16 @@ if (!TKHQ.verifyEnclaveSignature) { throw new Error("method not loaded"); } - verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, bundleObj.data); + + // Temporary solution to get the bytes signed by the enclave + var signedData = /"data":({[^}]+)/.exec(bundle); + if (signedData === null || signedData.length !== 2) { + throw new Error(`unable to find signed data in bundle: ${bundle}`); + } + const signedDataBytes = new TextEncoder().encode(signedData[1] + "}"); + const signedDataHexString = TKHQ.uint8arrayToHexString(signedDataBytes); + + verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, signedDataHexString); if (!verified) { throw new Error(`failed to verify enclave signature: ${bundle}`); } diff --git a/import/standalone.template.html b/import/standalone.template.html index 203ef76..819ad48 100644 --- a/import/standalone.template.html +++ b/import/standalone.template.html @@ -337,8 +337,11 @@

Message log

/** * Function to verify enclave signature on import bundle received from the server. + * @param {string} enclaveQuorumPublic uncompressed public key for the quorum key which produced the signature + * @param {string} publicSignature signature bytes encoded as a hexadecimal string + * @param {string} signedData signed bytes encoded as a hexadecimal string. This could be public key bytes directly, or JSON-encoded bytes */ - async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, publicKey) { + async function verifyEnclaveSignature(enclaveQuorumPublic, publicSignature, signedData) { /** Turnkey Signer enclave's public keys */ const TURNKEY_SIGNERS_ENCLAVES = { "prod": "04cf288fe433cc4e1aa0ce1632feac4ea26bf2f5a09dcfe5a42c398e06898710330f0572882f4dbdf0f5304b8fc8703acd69adca9a4bbf7f5d00d20a5e364b2569", @@ -364,8 +367,8 @@

Message log

// The ECDSA signature is ASN.1 DER encoded but WebCrypto uses raw format const publicSignatureBuf = fromDerSignature(publicSignature); - const publicKeyBuf = uint8arrayFromHexString(publicKey); - return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, publicKeyBuf); + const signedDataBuf = uint8arrayFromHexString(signedData); + return await crypto.subtle.verify({ name: "ECDSA", namedCurve: "P-256", hash: {name: "SHA-256" }}, quorumKey, publicSignatureBuf, signedDataBuf); } /** @@ -543,7 +546,17 @@

Message log

if (!TKHQ.verifyEnclaveSignature) { throw new Error("method not loaded"); } - verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, bundleObj.data); + + // Temporary solution to get the bytes signed by the enclave + var signedData = /"data":({[^}]+)/.exec(bundle); + if (signedData === null || signedData.length !== 2) { + throw new Error(`unable to find signed data in bundle: ${bundle}`); + } + const signedDataBytes = new TextEncoder().encode(signedData[1] + "}"); + const signedDataHexString = TKHQ.uint8arrayToHexString(signedDataBytes); + + verified = await TKHQ.verifyEnclaveSignature(bundleObj.enclaveQuorumPublic, bundleObj.dataSignature, signedDataHexString); + if (!verified) { throw new Error(`failed to verify enclave signature: ${bundle}`); }