From 8a8647874bd456ee11bb5f0909973694646a634e Mon Sep 17 00:00:00 2001 From: Ruslan Serebriakov Date: Mon, 19 Jun 2023 21:28:43 +0100 Subject: [PATCH 1/2] [Barz] Format signature API changes --- .../core/app/blockchains/ethereum/TestBarz.kt | 9 +++++---- include/TrustWalletCore/TWBarz.h | 7 ++++--- src/Ethereum/Barz.cpp | 14 ++++++++++--- src/Ethereum/Barz.h | 2 +- src/interface/TWBarz.cpp | 7 ++++--- swift/Tests/BarzTests.swift | 9 +++++---- tests/chains/Ethereum/BarzTests.cpp | 20 ++++++++++--------- 7 files changed, 41 insertions(+), 27 deletions(-) diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt index da900781363..ea2ce793ecb 100644 --- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/ethereum/TestBarz.kt @@ -89,11 +89,12 @@ class TestBarz { @Test fun testGetFormattedSignature() { - val signature = Numeric.hexStringToByteArray("3045022009fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33022100e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b") + val signature = Numeric.hexStringToByteArray("0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276") + val challenge = Numeric.hexStringToByteArray("0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9") val authenticatorData = Numeric.hexStringToByteArray("0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000") - val origin = "https://trustwallet.com" - val result = WCBarz.getFormattedSignature(signature, authenticatorData, origin) - assertEquals(Numeric.toHexString(result), "0x09fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000") + val clientDataJSON = "{\"type\":\"webauthn.get\",\"challenge\":\"zyZ6eMWtr5bzQaaW61doJChMVy8-Yb5hlpTVOdsZJfk\",\"origin\":\"https://trustwallet.com\"}"; + val result = WCBarz.getFormattedSignature(signature, challenge, authenticatorData, clientDataJSON) + assertEquals(Numeric.toHexString(result), "0x12d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca27600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000") } // https://testnet.bscscan.com/tx/0x43fc13dfdf06bbb09da8ce070953753764f1e43782d0c8b621946d8b45749419 diff --git a/include/TrustWalletCore/TWBarz.h b/include/TrustWalletCore/TWBarz.h index 3b15bb27463..37521d8eec8 100644 --- a/include/TrustWalletCore/TWBarz.h +++ b/include/TrustWalletCore/TWBarz.h @@ -43,9 +43,10 @@ TWData *_Nonnull TWBarzGetInitCodeFromAttestationObject(TWString* _Nonnull facto /// Converts the original ASN-encoded signature from webauthn to the format accepted by Barz /// /// \param signature Original signature -/// \param authenticatorData Hex encoded authenticator data -/// \param origin URL of the origin from clientDataJSON +/// \param challenge The original challenge that was signed +/// \param authenticatorData Returned from Webauthn API +/// \param clientDataJSON Returned from Webauthn API /// \return Bytes of the formatted signature TW_EXPORT_STATIC_METHOD -TWData *_Nonnull TWBarzGetFormattedSignature(TWData* _Nonnull signature, TWData* _Nonnull authenticatorData, TWString* _Nonnull origin); +TWData *_Nonnull TWBarzGetFormattedSignature(TWData* _Nonnull signature, TWData* _Nonnull challenge, TWData* _Nonnull authenticatorData, TWString* _Nonnull clientDataJSON); TW_EXTERN_C_END diff --git a/src/Ethereum/Barz.cpp b/src/Ethereum/Barz.cpp index aad3e11d85d..cbd498d5b25 100644 --- a/src/Ethereum/Barz.cpp +++ b/src/Ethereum/Barz.cpp @@ -12,6 +12,7 @@ #include #include "../proto/Barz.pb.h" #include "AsnParser.h" +#include "Base64.h" namespace TW::Barz { @@ -72,9 +73,16 @@ Data getInitCodeFromAttestationObject(const std::string& factoryAddress, const s return getInitCodeFromPublicKey(factoryAddress, hexEncoded(publicKey), verificationFacet); } -Data getFormattedSignature(const Data& signature, const Data& authenticatorData, const std::string& origin) { - const std::string clientDataJSONPre = "{\"type\":\"webauthn.get\",\"challenge\":\""; - const std::string clientDataJSONPost = "\",\"origin\":\"" + origin + "\"}"; +Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON) { + std::string challengeBase64 = TW::Base64::encodeBase64Url(challenge); + challengeBase64.pop_back(); + size_t challengePos = clientDataJSON.find(challengeBase64); + if (challengePos == std::string::npos) { + return Data(); + } + + const std::string clientDataJSONPre = clientDataJSON.substr(0, challengePos); + const std::string clientDataJSONPost = clientDataJSON.substr(challengePos + challengeBase64.size()); const auto parsedSignatureOptional = ASN::AsnParser::ecdsa_signature_from_der(signature); if (!parsedSignatureOptional.has_value()) { diff --git a/src/Ethereum/Barz.h b/src/Ethereum/Barz.h index 224a9e607a5..c9f47706afc 100644 --- a/src/Ethereum/Barz.h +++ b/src/Ethereum/Barz.h @@ -15,6 +15,6 @@ namespace TW::Barz { std::string getCounterfactualAddress(const Proto::ContractAddressInput input); Data getInitCodeFromPublicKey(const std::string& factoryAddress, const std::string& owner, const std::string& verificationFacet); Data getInitCodeFromAttestationObject(const std::string& factoryAddress, const std::string& attestationObject, const std::string& verificationFacet); -Data getFormattedSignature(const Data& signature, const Data& authenticatorData, const std::string& origin); +Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON); } diff --git a/src/interface/TWBarz.cpp b/src/interface/TWBarz.cpp index 230bfffc24d..3a579b67f75 100644 --- a/src/interface/TWBarz.cpp +++ b/src/interface/TWBarz.cpp @@ -38,11 +38,12 @@ TWData *_Nonnull TWBarzGetInitCodeFromAttestationObject(TWString* _Nonnull facto return TWDataCreateWithData(&initCode); } -TWData *_Nonnull TWBarzGetFormattedSignature(TWData* _Nonnull signature, TWData* _Nonnull authenticatorData, TWString* _Nonnull origin) { +TWData *_Nonnull TWBarzGetFormattedSignature(TWData* _Nonnull signature, TWData* _Nonnull challenge, TWData* _Nonnull authenticatorData, TWString* _Nonnull clientDataJSON) { const auto& signatureData = *reinterpret_cast(signature); + const auto& challengeData = *reinterpret_cast(challenge); const auto& authenticatorDataConverted = *reinterpret_cast(authenticatorData); - const auto& originStr = *reinterpret_cast(origin); + const auto& clientDataJSONStr = *reinterpret_cast(clientDataJSON); - const auto initCode = TW::Barz::getFormattedSignature(signatureData, authenticatorDataConverted, originStr); + const auto initCode = TW::Barz::getFormattedSignature(signatureData, challengeData, authenticatorDataConverted, clientDataJSONStr); return TWDataCreateWithData(&initCode); } \ No newline at end of file diff --git a/swift/Tests/BarzTests.swift b/swift/Tests/BarzTests.swift index 291e6e829a8..396984201a4 100644 --- a/swift/Tests/BarzTests.swift +++ b/swift/Tests/BarzTests.swift @@ -69,11 +69,12 @@ class BarzTests: XCTestCase { } func testFormatSignature() { - let signature = Data(hexString: "0x3045022009fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33022100e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b")! + let signature = Data(hexString: "0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276")! + let challenge = Data(hexString: "0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9")! let authenticatorData = Data(hexString: "0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000")! - let origin = "https://trustwallet.com" - let result = Barz.getFormattedSignature(signature: signature, authenticatorData: authenticatorData, origin: origin); - XCTAssertEqual(result.hexString, "09fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000") + let clientDataJSON = "{\"type\":\"webauthn.get\",\"challenge\":\"zyZ6eMWtr5bzQaaW61doJChMVy8-Yb5hlpTVOdsZJfk\",\"origin\":\"https://trustwallet.com\"}"; + let result = Barz.getFormattedSignature(signature: signature, challenge: challenge, authenticatorData: authenticatorData, clientDataJSON: clientDataJSON); + XCTAssertEqual(result.hexString, "12d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca27600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000") } // https://testnet.bscscan.com/tx/0x43fc13dfdf06bbb09da8ce070953753764f1e43782d0c8b621946d8b45749419 diff --git a/tests/chains/Ethereum/BarzTests.cpp b/tests/chains/Ethereum/BarzTests.cpp index 94b3aab9944..96661e3d31e 100644 --- a/tests/chains/Ethereum/BarzTests.cpp +++ b/tests/chains/Ethereum/BarzTests.cpp @@ -130,23 +130,25 @@ TEST(Barz, GetCounterfactualAddressFromAttestationObject) { TEST(Barz, GetFormattedSignature) { // C++ { - const std::string& signature = "0x3045022009fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33022100e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b"; - const std::string& authenticatorData = "0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000"; - const std::string& origin = "https://trustwallet.com"; + const Data& signature = parse_hex("0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276"); + const Data& challenge = parse_hex("0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9"); + const Data& authenticatorData = parse_hex("0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000"); + const std::string& clientDataJSON = "{\"type\":\"webauthn.get\",\"challenge\":\"zyZ6eMWtr5bzQaaW61doJChMVy8-Yb5hlpTVOdsZJfk\",\"origin\":\"https://trustwallet.com\"}"; - const auto& formattedSignature = Barz::getFormattedSignature(parse_hex(signature), parse_hex(authenticatorData), origin); - ASSERT_EQ(hexEncoded(formattedSignature), "0x09fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000"); + const auto& formattedSignature = Barz::getFormattedSignature(signature, challenge, authenticatorData, clientDataJSON); + ASSERT_EQ(hexEncoded(formattedSignature), "0x12d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca27600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000"); } // C { - const auto signature = DATA("0x3045022009fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33022100e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b"); + const auto signature = DATA("0x3044022012d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf0220256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca276"); + const auto challenge = DATA("0xcf267a78c5adaf96f341a696eb576824284c572f3e61be619694d539db1925f9"); const auto authenticatorData = DATA("0x1a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d00000000"); - const auto origin = STRING("https://trustwallet.com"); + const auto clientDataJSON = STRING("{\"type\":\"webauthn.get\",\"challenge\":\"zyZ6eMWtr5bzQaaW61doJChMVy8-Yb5hlpTVOdsZJfk\",\"origin\":\"https://trustwallet.com\"}"); - const auto& formattedSignatureData = TWBarzGetFormattedSignature(signature.get(), authenticatorData.get(), origin.get()); + const auto& formattedSignatureData = TWBarzGetFormattedSignature(signature.get(), challenge.get(), authenticatorData.get(), clientDataJSON.get()); const auto& formattedSignature = hexEncoded(*reinterpret_cast(WRAPD(formattedSignatureData).get())); - EXPECT_EQ(formattedSignature, "0x09fa8e18a42d76198e072dce79f5b621a24806e2fc4d99c59cc745ad2291fe33e3de1bd5b3264424ecb55a61daf54475d8f86bc24d16b799a3910f9c3ea3593b00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000"); + EXPECT_EQ(formattedSignature, "0x12d89e3b41e253dc9e90bd34dc1750d059b76d0b1d16af2059aa26e90b8960bf256d8a05572c654906ce422464693e280e243e6d9dbc5f96a681dba846bca27600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000251a70842af8c1feb7133b81e6a160a6a2be45ee057f0eb6d3f7f5126daa202e071d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025222c226f726967696e223a2268747470733a2f2f747275737477616c6c65742e636f6d227d000000000000000000000000000000000000000000000000000000"); } } From cab3debdc883185338a4f6c4b1e742a28241bc89 Mon Sep 17 00:00:00 2001 From: Ruslan Serebriakov Date: Tue, 20 Jun 2023 11:34:35 +0100 Subject: [PATCH 2/2] Update Barz.cpp --- src/Ethereum/Barz.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ethereum/Barz.cpp b/src/Ethereum/Barz.cpp index cbd498d5b25..4573f4bb3fa 100644 --- a/src/Ethereum/Barz.cpp +++ b/src/Ethereum/Barz.cpp @@ -75,7 +75,9 @@ Data getInitCodeFromAttestationObject(const std::string& factoryAddress, const s Data getFormattedSignature(const Data& signature, const Data challenge, const Data& authenticatorData, const std::string& clientDataJSON) { std::string challengeBase64 = TW::Base64::encodeBase64Url(challenge); - challengeBase64.pop_back(); + while (challengeBase64.back() == '=') { + challengeBase64.pop_back(); + } size_t challengePos = clientDataJSON.find(challengeBase64); if (challengePos == std::string::npos) { return Data();