From 3b66bcfdeed6c6150f83a0069df5dca9d1b52a14 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Mon, 8 Nov 2021 12:26:31 +0100 Subject: [PATCH 01/12] Expose StoredKey encryption parameters --- include/TrustWalletCore/TWStoredKey.h | 4 ++++ src/interface/TWStoredKey.cpp | 8 +++++++ tests/interface/TWStoredKeyTests.cpp | 34 +++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/include/TrustWalletCore/TWStoredKey.h b/include/TrustWalletCore/TWStoredKey.h index c5b6484d3cb..71bfead007c 100644 --- a/include/TrustWalletCore/TWStoredKey.h +++ b/include/TrustWalletCore/TWStoredKey.h @@ -105,4 +105,8 @@ TWData* _Nullable TWStoredKeyExportJSON(struct TWStoredKey* _Nonnull key); TW_EXPORT_METHOD bool TWStoredKeyFixAddresses(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password); +/// Retrieve stored key encoding parameters, as JSON string. +TW_EXPORT_PROPERTY +TWString* _Nullable TWStoredKeyEncryptionParameters(struct TWStoredKey* _Nonnull key); + TW_EXTERN_C_END diff --git a/src/interface/TWStoredKey.cpp b/src/interface/TWStoredKey.cpp index cb4625a40c7..f774cd07f82 100644 --- a/src/interface/TWStoredKey.cpp +++ b/src/interface/TWStoredKey.cpp @@ -178,3 +178,11 @@ bool TWStoredKeyFixAddresses(struct TWStoredKey* _Nonnull key, TWData* _Nonnull return false; } } + +TWString* _Nullable TWStoredKeyEncryptionParameters(struct TWStoredKey* _Nonnull key) { + if (!key->impl.id) { + return nullptr; + } + const std::string params = key->impl.payload.json().dump(); + return TWStringCreateWithUTF8Bytes(params.c_str()); +} diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index ff498e4f6cb..872878b8d6b 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -14,6 +14,7 @@ #include "../src/HexCoding.h" #include +#include #include @@ -225,3 +226,36 @@ TEST(TWStoredKey, getWalletPasswordInvalid) { ASSERT_NE(WRAP(TWHDWallet, TWStoredKeyWallet(key.get(), password.get())).get(), nullptr); ASSERT_EQ(WRAP(TWHDWallet, TWStoredKeyWallet(key.get(), passwordInvalid.get())).get(), nullptr); } + +TEST(TWStoredKey, encryptionParameters) { + const auto key = createDefaultStoredKey(); + const auto params = WRAPS(TWStoredKeyEncryptionParameters(key.get())); + + nlohmann::json jsonParams = nlohmann::json::parse(string(TWStringUTF8Bytes(params.get()))); + + // compare one parameter + EXPECT_EQ(jsonParams["kdfparams"]["n"], 4096); + + // compare all keys, except dynamic ones (like cipherparams/iv) + jsonParams["cipherparams"] = {}; + jsonParams["ciphertext"] = ""; + jsonParams["kdfparams"]["salt"] = ""; + jsonParams["mac"] = ""; + const auto params2 = jsonParams.dump(); + assertJSONEqual(params2, R"( + { + "cipher": "aes-128-ctr", + "cipherparams": null, + "ciphertext": "", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "" + }, + "mac": "" + } + )"); +} From 25f64d1dec4be049ca51e4a562fcaa7584115d8b Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Mon, 8 Nov 2021 17:45:42 +0100 Subject: [PATCH 02/12] Add Swift test --- swift/Tests/Keystore/KeystoreKeyTests.swift | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/swift/Tests/Keystore/KeystoreKeyTests.swift b/swift/Tests/Keystore/KeystoreKeyTests.swift index dafa208495b..df4453b1d3e 100755 --- a/swift/Tests/Keystore/KeystoreKeyTests.swift +++ b/swift/Tests/Keystore/KeystoreKeyTests.swift @@ -119,4 +119,25 @@ class KeystoreKeyTests: XCTestCase { let data = keystore.decryptPrivateKey(password: password) XCTAssertEqual(data?.hexString, "4357b2f9a6150ba969bc52f01c98cce5313595fe49f2d08303759c73e5c7a46c") } + + struct KdfParamsStruct: Decodable { + let dklen: Int + let n: Int + } + + struct EncryptionParametersStruct: Decodable { + let kdf: String + let kdfparams: KdfParamsStruct + } + + func testEncryptionParameters() { + let url = Bundle(for: type(of: self)).url(forResource: "key", withExtension: "json")! + let key = StoredKey.load(path: url.path)! + + let params = key.encryptionParameters + let paramsData = params!.data(using: .utf8)! + let paramsSruct: EncryptionParametersStruct = try! JSONDecoder().decode(EncryptionParametersStruct.self, from: paramsData) + XCTAssertEqual(paramsSruct.kdf, "scrypt"); + XCTAssertEqual(paramsSruct.kdfparams.n, 262144); + } } From a62a75c0705af17f6769f1ca4d4a5612b704f049 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Tue, 9 Nov 2021 09:55:21 +0100 Subject: [PATCH 03/12] Test adjustments, review comments --- swift/Tests/Keystore/KeystoreKeyTests.swift | 16 ++++++++-------- tests/interface/TWStoredKeyTests.cpp | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/swift/Tests/Keystore/KeystoreKeyTests.swift b/swift/Tests/Keystore/KeystoreKeyTests.swift index df4453b1d3e..b33659ceaef 100755 --- a/swift/Tests/Keystore/KeystoreKeyTests.swift +++ b/swift/Tests/Keystore/KeystoreKeyTests.swift @@ -120,24 +120,24 @@ class KeystoreKeyTests: XCTestCase { XCTAssertEqual(data?.hexString, "4357b2f9a6150ba969bc52f01c98cce5313595fe49f2d08303759c73e5c7a46c") } - struct KdfParamsStruct: Decodable { + struct KdfParams: Decodable { let dklen: Int let n: Int } - struct EncryptionParametersStruct: Decodable { + struct EncryptionParameters: Decodable { let kdf: String - let kdfparams: KdfParamsStruct + let kdfparams: KdfParams } func testEncryptionParameters() { let url = Bundle(for: type(of: self)).url(forResource: "key", withExtension: "json")! let key = StoredKey.load(path: url.path)! - let params = key.encryptionParameters - let paramsData = params!.data(using: .utf8)! - let paramsSruct: EncryptionParametersStruct = try! JSONDecoder().decode(EncryptionParametersStruct.self, from: paramsData) - XCTAssertEqual(paramsSruct.kdf, "scrypt"); - XCTAssertEqual(paramsSruct.kdfparams.n, 262144); + let paramsData = key.encryptionParameters!.data(using: .utf8)! + let params = try! JSONDecoder().decode(EncryptionParameters.self, from: paramsData) + + XCTAssertEqual(params.kdf, "scrypt"); + XCTAssertEqual(params.kdfparams.n, 262144); } } diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index 872878b8d6b..f5c816fd9bf 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -233,8 +233,9 @@ TEST(TWStoredKey, encryptionParameters) { nlohmann::json jsonParams = nlohmann::json::parse(string(TWStringUTF8Bytes(params.get()))); - // compare one parameter + // compare some specific parameters EXPECT_EQ(jsonParams["kdfparams"]["n"], 4096); + EXPECT_EQ(std::string(jsonParams["cipherparams"]["iv"]).length(), 32); // compare all keys, except dynamic ones (like cipherparams/iv) jsonParams["cipherparams"] = {}; From 8470cb3f3719fa3a46e3e2532271d31514eb58d2 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 11 Nov 2021 15:21:32 +0100 Subject: [PATCH 04/12] Add test with default encryption parameters --- tests/Keystore/StoredKeyTests.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index 84266df0ccd..eb74ad9d9df 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -383,4 +383,22 @@ TEST(StoredKey, EtherWalletAddressNo0x) { EXPECT_EQ(key.account(TWCoinTypeEthereum, nullptr)->address, "0xAc1ec44E4f0ca7D172B7803f6836De87Fb72b309"); } +TEST(StoredKey, CreateWithMnemonicDefaultEncryptionParameters) { + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); + const Data& mnemo2Data = key.payload.decrypt(password); + EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); + EXPECT_EQ(key.accounts.size(), 0); + EXPECT_EQ(key.wallet(password).getMnemonic(), string(mnemonic)); + + const auto json = key.json(); + + EXPECT_EQ(json["crypto"]["kdf"], "scrypt"); + EXPECT_EQ(json["crypto"]["kdfparams"]["n"], 4096); + + // load it back + const auto key2 = StoredKey::createWithJson(json); + EXPECT_EQ(key2.wallet(password).getMnemonic(), string(mnemonic)); +} + } // namespace TW::Keystore From 3a359322a86ca029fbfc7bf3da0cda83d0cf46fe Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 14:24:59 +0100 Subject: [PATCH 05/12] Break up EncryptionParameters to EncryptedPayload and EncryptionParameters --- src/Keystore/EncryptionParameters.cpp | 50 ++++++++--------- src/Keystore/EncryptionParameters.h | 80 ++++++++++++++++++--------- src/Keystore/StoredKey.cpp | 4 +- src/Keystore/StoredKey.h | 2 +- tests/Keystore/StoredKeyTests.cpp | 26 ++++----- 5 files changed, 96 insertions(+), 66 deletions(-) diff --git a/src/Keystore/EncryptionParameters.cpp b/src/Keystore/EncryptionParameters.cpp index ddb461d982e..97e43f7418a 100644 --- a/src/Keystore/EncryptionParameters.cpp +++ b/src/Keystore/EncryptionParameters.cpp @@ -28,8 +28,8 @@ static Data computeMAC(Iter begin, Iter end, const Data& key) { return Hash::keccak256(data); } -EncryptionParameters::EncryptionParameters(const Data& password, const Data& data) : mac() { - auto scryptParams = boost::get(kdfParams); +EncryptedPayload::EncryptedPayload(const Data& password, const Data& data) : mac() { + auto scryptParams = boost::get(params.kdfParams); auto derivedKey = Data(scryptParams.desiredKeyLength); scrypt(reinterpret_cast(password.data()), password.size(), scryptParams.salt.data(), scryptParams.salt.size(), scryptParams.n, scryptParams.r, scryptParams.p, derivedKey.data(), @@ -39,7 +39,7 @@ EncryptionParameters::EncryptionParameters(const Data& password, const Data& dat auto result = aes_encrypt_key128(derivedKey.data(), &ctx); assert(result == EXIT_SUCCESS); if (result == EXIT_SUCCESS) { - Data iv = cipherParams.iv; + Data iv = params.cipherParams.iv; encrypted = Data(data.size()); aes_ctr_encrypt(data.data(), encrypted.data(), static_cast(data.size()), iv.data(), aes_ctr_cbuf_inc, &ctx); @@ -47,23 +47,24 @@ EncryptionParameters::EncryptionParameters(const Data& password, const Data& dat } } -EncryptionParameters::~EncryptionParameters() { +EncryptedPayload::~EncryptedPayload() { std::fill(encrypted.begin(), encrypted.end(), 0); + std::fill(mac.begin(), mac.end(), 0); } -Data EncryptionParameters::decrypt(const Data& password) const { +Data EncryptedPayload::decrypt(const Data& password) const { auto derivedKey = Data(); auto mac = Data(); - if (kdfParams.which() == 0) { - auto scryptParams = boost::get(kdfParams); + if (params.kdfParams.which() == 0) { + auto scryptParams = boost::get(params.kdfParams); derivedKey.resize(scryptParams.defaultDesiredKeyLength); scrypt(password.data(), password.size(), scryptParams.salt.data(), scryptParams.salt.size(), scryptParams.n, scryptParams.r, scryptParams.p, derivedKey.data(), scryptParams.defaultDesiredKeyLength); mac = computeMAC(derivedKey.end() - 16, derivedKey.end(), encrypted); - } else if (kdfParams.which() == 1) { - auto pbkdf2Params = boost::get(kdfParams); + } else if (params.kdfParams.which() == 1) { + auto pbkdf2Params = boost::get(params.kdfParams); derivedKey.resize(pbkdf2Params.defaultDesiredKeyLength); pbkdf2_hmac_sha256(password.data(), static_cast(password.size()), pbkdf2Params.salt.data(), static_cast(pbkdf2Params.salt.size()), pbkdf2Params.iterations, derivedKey.data(), @@ -78,15 +79,15 @@ Data EncryptionParameters::decrypt(const Data& password) const { } Data decrypted(encrypted.size()); - Data iv = cipherParams.iv; - if (cipher == "aes-128-ctr") { + Data iv = params.cipherParams.iv; + if (params.cipher == "aes-128-ctr") { aes_encrypt_ctx ctx; auto __attribute__((unused)) result = aes_encrypt_key(derivedKey.data(), 16, &ctx); assert(result != EXIT_FAILURE); aes_ctr_decrypt(encrypted.data(), decrypted.data(), static_cast(encrypted.size()), iv.data(), aes_ctr_cbuf_inc, &ctx); - } else if (cipher == "aes-128-cbc") { + } else if (params.cipher == "aes-128-cbc") { aes_decrypt_ctx ctx; auto __attribute__((unused)) result = aes_decrypt_key(derivedKey.data(), 16, &ctx); assert(result != EXIT_FAILURE); @@ -114,36 +115,35 @@ static const auto kdfParams = "kdfparams"; static const auto mac = "mac"; } // namespace CodingKeys -EncryptionParameters::EncryptionParameters(const nlohmann::json& json) { +EncryptedPayload::EncryptedPayload(const nlohmann::json& json) { encrypted = parse_hex(json[CodingKeys::encrypted].get()); - cipher = json[CodingKeys::cipher].get(); - cipherParams = AESParameters(json[CodingKeys::cipherParams]); + params.cipher = json[CodingKeys::cipher].get(); + params.cipherParams = AESParameters(json[CodingKeys::cipherParams]); mac = parse_hex(json[CodingKeys::mac].get()); auto kdf = json[CodingKeys::kdf].get(); if (kdf == "scrypt") { - kdfParams = ScryptParameters(json[CodingKeys::kdfParams]); + params.kdfParams = ScryptParameters(json[CodingKeys::kdfParams]); } else if (kdf == "pbkdf2") { - kdfParams = PBKDF2Parameters(json[CodingKeys::kdfParams]); + params.kdfParams = PBKDF2Parameters(json[CodingKeys::kdfParams]); } } -nlohmann::json EncryptionParameters::json() const { +nlohmann::json EncryptedPayload::json() const { nlohmann::json j; j[CodingKeys::encrypted] = hex(encrypted); - j[CodingKeys::cipher] = cipher; - j[CodingKeys::cipherParams] = cipherParams.json(); + j[CodingKeys::cipher] = params.cipher; + j[CodingKeys::cipherParams] = params.cipherParams.json(); j[CodingKeys::mac] = hex(mac); - if (kdfParams.which() == 0) { - auto scryptParams = boost::get(kdfParams); + if (params.kdfParams.which() == 0) { + auto scryptParams = boost::get(params.kdfParams); j[CodingKeys::kdf] = "scrypt"; j[CodingKeys::kdfParams] = scryptParams.json(); - } else if (kdfParams.which() == 1) { - auto pbkdf2Params = boost::get(kdfParams); + } else if (params.kdfParams.which() == 1) { + auto pbkdf2Params = boost::get(params.kdfParams); j[CodingKeys::kdf] = "pbkdf2"; j[CodingKeys::kdfParams] = pbkdf2Params.json(); - } return j; diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index e1e68933977..8dcdaa7d06e 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -17,6 +17,42 @@ namespace TW::Keystore { +/// Preset encryption parameters with different security strength +enum EncryptionLevel { + Default = 0, + Weak, + Standard, +}; + +/// Set of parameters used when encoding +struct EncryptionParameters { + /// Cipher algorithm. + std::string cipher = "aes-128-ctr"; + + /// Cipher parameters. + AESParameters cipherParams = AESParameters(); + + /// Key derivation function parameters. + boost::variant kdfParams = ScryptParameters(); + + EncryptionParameters() = default; + + /// Initializes with standard values. + EncryptionParameters(AESParameters cipherParams, boost::variant kdfParams) + : cipherParams(std::move(cipherParams)) + , kdfParams(std::move(kdfParams)) {} + + /// Saves `this` as a JSON object. + nlohmann::json json() const; + + EncryptionParameters(const EncryptionParameters& other) = default; + EncryptionParameters(EncryptionParameters&& other) = default; + EncryptionParameters& operator=(const EncryptionParameters& other) = default; + EncryptionParameters& operator=(EncryptionParameters&& other) = default; + + virtual ~EncryptionParameters() = default; +}; + /// Errors thrown when decrypting a key. enum class DecryptionError { unsupportedKDF, @@ -27,37 +63,31 @@ enum class DecryptionError { invalidPassword, }; -struct EncryptionParameters { +/// An encrypted payload data +struct EncryptedPayload { +public: + EncryptionParameters params; + /// Encrypted data. Data encrypted; - /// Cipher algorithm. - std::string cipher = "aes-128-ctr"; - - /// Cipher parameters. - AESParameters cipherParams = AESParameters(); - - /// Key derivation function parameters. - boost::variant kdfParams = ScryptParameters(); - /// Message authentication code. Data mac; - EncryptionParameters() = default; + EncryptedPayload() = default; - /// Initializes `EncryptionParameters` with standard values. - EncryptionParameters(const Data& encrypted, AESParameters cipherParams, boost::variant kdfParams, const Data& mac) - : encrypted(std::move(encrypted)) - , cipherParams(std::move(cipherParams)) - , kdfParams(std::move(kdfParams)) + /// Initializes with standard values. + EncryptedPayload(const EncryptionParameters& params, const Data& encrypted, const Data& mac) + : params(std::move(params)) + , encrypted(std::move(encrypted)) , mac(std::move(mac)) {} - /// Initializes `EncryptionParameters` by encrypting data with a password + /// Initializes by encrypting data with a password /// using standard values. - EncryptionParameters(const Data& password, const Data& data); + EncryptedPayload(const Data& password, const Data& data); - /// Initializes `EncryptionParameters` with a JSON object. - EncryptionParameters(const nlohmann::json& json); + /// Initializes with a JSON object. + EncryptedPayload(const nlohmann::json& json); /// Decrypts the payload with the given password. Data decrypt(const Data& password) const; @@ -65,12 +95,12 @@ struct EncryptionParameters { /// Saves `this` as a JSON object. nlohmann::json json() const; - EncryptionParameters(const EncryptionParameters& other) = default; - EncryptionParameters(EncryptionParameters&& other) = default; - EncryptionParameters& operator=(const EncryptionParameters& other) = default; - EncryptionParameters& operator=(EncryptionParameters&& other) = default; + EncryptedPayload(const EncryptedPayload& other) = default; + EncryptedPayload(EncryptedPayload&& other) = default; + EncryptedPayload& operator=(const EncryptedPayload& other) = default; + EncryptedPayload& operator=(EncryptedPayload&& other) = default; - virtual ~EncryptionParameters(); + virtual ~EncryptedPayload(); }; } // namespace TW::Keystore diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index ee7b5d9dcc5..16903d2c58f 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -225,10 +225,10 @@ void StoredKey::loadJson(const nlohmann::json& json) { } if (json.count(CodingKeys::crypto) != 0) { - payload = EncryptionParameters(json[CodingKeys::crypto]); + payload = EncryptedPayload(json[CodingKeys::crypto]); } else if (json.count(UppercaseCodingKeys::crypto) != 0) { // Workaround for myEtherWallet files - payload = EncryptionParameters(json[UppercaseCodingKeys::crypto]); + payload = EncryptedPayload(json[UppercaseCodingKeys::crypto]); } else { throw DecryptionError::invalidKeyFile; } diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index 4a019c5b5b3..e4a6db0416d 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -36,7 +36,7 @@ class StoredKey { std::string name; /// Encrypted payload. - EncryptionParameters payload; + EncryptedPayload payload; /// Active accounts. std::vector accounts; diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index eb74ad9d9df..68e720622b6 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -243,10 +243,10 @@ TEST(StoredKey, LoadPBKDF2Key) { EXPECT_EQ(key.id, "3198bc9c-6672-5ab3-d995-4942343ae5b6"); const auto& payload = key.payload; - ASSERT_TRUE(payload.kdfParams.which() == 1); - EXPECT_EQ(boost::get(payload.kdfParams).desiredKeyLength, 32); - EXPECT_EQ(boost::get(payload.kdfParams).iterations, 262144); - EXPECT_EQ(hex(boost::get(payload.kdfParams).salt), "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"); + ASSERT_TRUE(payload.params.kdfParams.which() == 1); + EXPECT_EQ(boost::get(payload.params.kdfParams).desiredKeyLength, 32); + EXPECT_EQ(boost::get(payload.params.kdfParams).iterations, 262144); + EXPECT_EQ(hex(boost::get(payload.params.kdfParams).salt), "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"); EXPECT_EQ(hex(payload.decrypt(TW::data("testpassword"))), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); } @@ -287,17 +287,17 @@ TEST(StoredKey, ReadWallet) { const auto header = key.payload; - EXPECT_EQ(header.cipher, "aes-128-ctr"); + EXPECT_EQ(header.params.cipher, "aes-128-ctr"); EXPECT_EQ(hex(header.encrypted), "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c"); EXPECT_EQ(hex(header.mac), "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"); - EXPECT_EQ(hex(header.cipherParams.iv), "83dbcc02d8ccb40e466191a123791e0e"); - - ASSERT_TRUE(header.kdfParams.which() == 0); - EXPECT_EQ(boost::get(header.kdfParams).desiredKeyLength, 32); - EXPECT_EQ(boost::get(header.kdfParams).n, 262144); - EXPECT_EQ(boost::get(header.kdfParams).p, 8); - EXPECT_EQ(boost::get(header.kdfParams).r, 1); - EXPECT_EQ(hex(boost::get(header.kdfParams).salt), "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"); + EXPECT_EQ(hex(header.params.cipherParams.iv), "83dbcc02d8ccb40e466191a123791e0e"); + + ASSERT_TRUE(header.params.kdfParams.which() == 0); + EXPECT_EQ(boost::get(header.params.kdfParams).desiredKeyLength, 32); + EXPECT_EQ(boost::get(header.params.kdfParams).n, 262144); + EXPECT_EQ(boost::get(header.params.kdfParams).p, 8); + EXPECT_EQ(boost::get(header.params.kdfParams).r, 1); + EXPECT_EQ(hex(boost::get(header.params.kdfParams).salt), "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"); } TEST(StoredKey, ReadMyEtherWallet) { From 32c5c284a72bb76ff8e8f338475236a833efc926 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 14:30:37 +0100 Subject: [PATCH 06/12] Weak and Standard levels, provide level in constructor, tests with 2 levels --- src/Keystore/EncryptionParameters.cpp | 3 ++- src/Keystore/EncryptionParameters.h | 11 ++++++++++- src/Keystore/ScryptParameters.cpp | 4 ++++ src/Keystore/ScryptParameters.h | 4 ++++ src/Keystore/StoredKey.cpp | 10 ++++++---- src/Keystore/StoredKey.h | 4 ++-- tests/Keystore/StoredKeyTests.cpp | 22 ++++++++++++++++++++-- 7 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/Keystore/EncryptionParameters.cpp b/src/Keystore/EncryptionParameters.cpp index 97e43f7418a..4662b48e0e4 100644 --- a/src/Keystore/EncryptionParameters.cpp +++ b/src/Keystore/EncryptionParameters.cpp @@ -28,7 +28,8 @@ static Data computeMAC(Iter begin, Iter end, const Data& key) { return Hash::keccak256(data); } -EncryptedPayload::EncryptedPayload(const Data& password, const Data& data) : mac() { +EncryptedPayload::EncryptedPayload(const Data& password, const Data& data, const EncryptionParameters& params) : + params(std::move(params)), mac() { auto scryptParams = boost::get(params.kdfParams); auto derivedKey = Data(scryptParams.desiredKeyLength); scrypt(reinterpret_cast(password.data()), password.size(), scryptParams.salt.data(), diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index 8dcdaa7d06e..15dc5e2f3dd 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -26,6 +26,15 @@ enum EncryptionLevel { /// Set of parameters used when encoding struct EncryptionParameters { + static EncryptionParameters getPreset(enum EncryptionLevel preset) { + switch (preset) { + case Weak: + case Default: + default: return EncryptionParameters(AESParameters(), ScryptParameters::Light); + case Standard: return EncryptionParameters(AESParameters(), ScryptParameters::Standard); + } + } + /// Cipher algorithm. std::string cipher = "aes-128-ctr"; @@ -84,7 +93,7 @@ struct EncryptedPayload { /// Initializes by encrypting data with a password /// using standard values. - EncryptedPayload(const Data& password, const Data& data); + EncryptedPayload(const Data& password, const Data& data, const EncryptionParameters& params); /// Initializes with a JSON object. EncryptedPayload(const nlohmann::json& json); diff --git a/src/Keystore/ScryptParameters.cpp b/src/Keystore/ScryptParameters.cpp index 16ccd489c4c..8c89afc8f47 100644 --- a/src/Keystore/ScryptParameters.cpp +++ b/src/Keystore/ScryptParameters.cpp @@ -12,6 +12,10 @@ using namespace TW; using namespace TW::Keystore; +ScryptParameters ScryptParameters::Light = ScryptParameters(Data(), lightN, defaultR, lightP, defaultDesiredKeyLength); + +ScryptParameters ScryptParameters::Standard = ScryptParameters(Data(), standardN, defaultR, standardP, defaultDesiredKeyLength); + ScryptParameters::ScryptParameters() : salt(32) { random_buffer(salt.data(), salt.size()); } diff --git a/src/Keystore/ScryptParameters.h b/src/Keystore/ScryptParameters.h index 10e7c019bd6..f98807693a3 100644 --- a/src/Keystore/ScryptParameters.h +++ b/src/Keystore/ScryptParameters.h @@ -23,6 +23,10 @@ enum class ScryptValidationError { /// Scrypt function parameters. struct ScryptParameters { + static ScryptParameters Light; + + static ScryptParameters Standard; + /// The N parameter of Scrypt encryption algorithm, using 256MB memory and /// taking approximately 1s CPU time on a modern processor. static const uint32_t standardN = 1 << 18; diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index 16903d2c58f..cfd58fa068d 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -27,13 +27,13 @@ using namespace TW; using namespace TW::Keystore; -StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic) { +StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, EncryptionLevel encryptionLevel) { if (!Mnemonic::isValid(mnemonic)) { throw std::invalid_argument("Invalid mnemonic"); } Data mnemonicData = TW::Data(mnemonic.begin(), mnemonic.end()); - StoredKey key = StoredKey(StoredKeyType::mnemonicPhrase, name, password, mnemonicData); + StoredKey key = StoredKey(StoredKeyType::mnemonicPhrase, name, password, mnemonicData, encryptionLevel); return key; } @@ -78,8 +78,10 @@ StoredKey StoredKey::createWithPrivateKeyAddDefaultAddress(const std::string& na return key; } -StoredKey::StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data) - : type(type), id(), name(std::move(name)), payload(password, data), accounts() { +StoredKey::StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, EncryptionLevel encryptionLevel) + : type(type), id(), name(std::move(name)), accounts() { + const auto encryptionParams = EncryptionParameters::getPreset(encryptionLevel); + payload = EncryptedPayload(password, data, encryptionParams); boost::uuids::random_generator gen; id = boost::lexical_cast(gen()); } diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index e4a6db0416d..3b01211da4f 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -43,7 +43,7 @@ class StoredKey { /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic); + static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, EncryptionLevel encryptionLevel = Default); /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid @@ -119,7 +119,7 @@ class StoredKey { /// Initializes a `StoredKey` with a type, an encryption password, and unencrypted data. /// This contstructor will encrypt the provided data with default encryption /// parameters. - StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data); + StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, EncryptionLevel encryptionLevel = Default); }; } // namespace TW::Keystore diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index 68e720622b6..ad5d9ad2a13 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -383,8 +383,8 @@ TEST(StoredKey, EtherWalletAddressNo0x) { EXPECT_EQ(key.account(TWCoinTypeEthereum, nullptr)->address, "0xAc1ec44E4f0ca7D172B7803f6836De87Fb72b309"); } -TEST(StoredKey, CreateWithMnemonicDefaultEncryptionParameters) { - const auto key = StoredKey::createWithMnemonic("name", password, mnemonic); +TEST(StoredKey, CreateWeakEncryptionParameters) { + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, Weak); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); @@ -401,4 +401,22 @@ TEST(StoredKey, CreateWithMnemonicDefaultEncryptionParameters) { EXPECT_EQ(key2.wallet(password).getMnemonic(), string(mnemonic)); } +TEST(StoredKey, CreateStandardEncryptionParameters) { + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, Standard); + EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); + const Data& mnemo2Data = key.payload.decrypt(password); + EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); + EXPECT_EQ(key.accounts.size(), 0); + EXPECT_EQ(key.wallet(password).getMnemonic(), string(mnemonic)); + + const auto json = key.json(); + + EXPECT_EQ(json["crypto"]["kdf"], "scrypt"); + EXPECT_EQ(json["crypto"]["kdfparams"]["n"], 262144); + + // load it back + const auto key2 = StoredKey::createWithJson(json); + EXPECT_EQ(key2.wallet(password).getMnemonic(), string(mnemonic)); +} + } // namespace TW::Keystore From 6cc37f73b3bc15f3b484a2ccd3d367dc9884785c Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:05:37 +0100 Subject: [PATCH 07/12] Enum to TW include --- .../TrustWalletCore/TWEncryptionParameters.h | 23 +++++++++++++++++++ include/TrustWalletCore/TWStoredKey.h | 1 + src/Keystore/EncryptionParameters.h | 10 ++------ src/Keystore/StoredKey.cpp | 4 ++-- src/Keystore/StoredKey.h | 4 ++-- 5 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 include/TrustWalletCore/TWEncryptionParameters.h diff --git a/include/TrustWalletCore/TWEncryptionParameters.h b/include/TrustWalletCore/TWEncryptionParameters.h new file mode 100644 index 00000000000..13947b0cfb0 --- /dev/null +++ b/include/TrustWalletCore/TWEncryptionParameters.h @@ -0,0 +1,23 @@ +// Copyright © 2017-2021 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +#include "TWBase.h" + +TW_EXTERN_C_BEGIN + +TW_EXPORT_ENUM(uint32_t) +/// Preset encryption parameter with different security strength, for key store +enum TWStoredKeyEncryptionLevel { + /// Default, which is one of the below values, determined by the implementation. + Default = 0, + /// Minimal sufficient level of encryption strength + Weak, + Standard, +}; + +TW_EXTERN_C_END diff --git a/include/TrustWalletCore/TWStoredKey.h b/include/TrustWalletCore/TWStoredKey.h index 71bfead007c..f5114ebf6e9 100644 --- a/include/TrustWalletCore/TWStoredKey.h +++ b/include/TrustWalletCore/TWStoredKey.h @@ -12,6 +12,7 @@ #include "TWHDWallet.h" #include "TWPrivateKey.h" #include "TWString.h" +#include "TWEncryptionParameters.h" TW_EXTERN_C_BEGIN diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index 15dc5e2f3dd..c29fcd9f22a 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -10,6 +10,7 @@ #include "PBKDF2Parameters.h" #include "ScryptParameters.h" #include "../Data.h" +#include #include #include @@ -17,16 +18,9 @@ namespace TW::Keystore { -/// Preset encryption parameters with different security strength -enum EncryptionLevel { - Default = 0, - Weak, - Standard, -}; - /// Set of parameters used when encoding struct EncryptionParameters { - static EncryptionParameters getPreset(enum EncryptionLevel preset) { + static EncryptionParameters getPreset(enum TWStoredKeyEncryptionLevel preset) { switch (preset) { case Weak: case Default: diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index cfd58fa068d..dd2251dff77 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -27,7 +27,7 @@ using namespace TW; using namespace TW::Keystore; -StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, EncryptionLevel encryptionLevel) { +StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel) { if (!Mnemonic::isValid(mnemonic)) { throw std::invalid_argument("Invalid mnemonic"); } @@ -78,7 +78,7 @@ StoredKey StoredKey::createWithPrivateKeyAddDefaultAddress(const std::string& na return key; } -StoredKey::StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, EncryptionLevel encryptionLevel) +StoredKey::StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel) : type(type), id(), name(std::move(name)), accounts() { const auto encryptionParams = EncryptionParameters::getPreset(encryptionLevel); payload = EncryptedPayload(password, data, encryptionParams); diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index 3b01211da4f..552d27f6a7d 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -43,7 +43,7 @@ class StoredKey { /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, EncryptionLevel encryptionLevel = Default); + static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel = Default); /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid @@ -119,7 +119,7 @@ class StoredKey { /// Initializes a `StoredKey` with a type, an encryption password, and unencrypted data. /// This contstructor will encrypt the provided data with default encryption /// parameters. - StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, EncryptionLevel encryptionLevel = Default); + StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel = Default); }; } // namespace TW::Keystore From 02d142d36873bc9bf757feae37d8afc8ff8fa7d0 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:15:48 +0100 Subject: [PATCH 08/12] Enum rename/fix --- include/TrustWalletCore/TWEncryptionParameters.h | 8 ++++---- src/Keystore/EncryptionParameters.h | 8 ++++---- src/Keystore/StoredKey.h | 4 ++-- tests/Keystore/StoredKeyTests.cpp | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/TrustWalletCore/TWEncryptionParameters.h b/include/TrustWalletCore/TWEncryptionParameters.h index 13947b0cfb0..fd0e30b726f 100644 --- a/include/TrustWalletCore/TWEncryptionParameters.h +++ b/include/TrustWalletCore/TWEncryptionParameters.h @@ -10,14 +10,14 @@ TW_EXTERN_C_BEGIN -TW_EXPORT_ENUM(uint32_t) /// Preset encryption parameter with different security strength, for key store +TW_EXPORT_ENUM(uint32_t) enum TWStoredKeyEncryptionLevel { /// Default, which is one of the below values, determined by the implementation. - Default = 0, + TWEncryptionLevelDefault = 0, /// Minimal sufficient level of encryption strength - Weak, - Standard, + TWEncryptionLevelWeak, + TWEncryptionLevelStandard, }; TW_EXTERN_C_END diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index c29fcd9f22a..7c14f1deaa6 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -22,10 +22,10 @@ namespace TW::Keystore { struct EncryptionParameters { static EncryptionParameters getPreset(enum TWStoredKeyEncryptionLevel preset) { switch (preset) { - case Weak: - case Default: - default: return EncryptionParameters(AESParameters(), ScryptParameters::Light); - case Standard: return EncryptionParameters(AESParameters(), ScryptParameters::Standard); + case TWEncryptionLevelWeak: + case TWEncryptionLevelDefault: + default: return EncryptionParameters(AESParameters(), ScryptParameters::Light); + case TWEncryptionLevelStandard: return EncryptionParameters(AESParameters(), ScryptParameters::Standard); } } diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index 552d27f6a7d..5fc8320ccb8 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -43,7 +43,7 @@ class StoredKey { /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel = Default); + static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel = TWEncryptionLevelDefault); /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid @@ -119,7 +119,7 @@ class StoredKey { /// Initializes a `StoredKey` with a type, an encryption password, and unencrypted data. /// This contstructor will encrypt the provided data with default encryption /// parameters. - StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel = Default); + StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel = TWEncryptionLevelDefault); }; } // namespace TW::Keystore diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index ad5d9ad2a13..fe6799e867f 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -384,7 +384,7 @@ TEST(StoredKey, EtherWalletAddressNo0x) { } TEST(StoredKey, CreateWeakEncryptionParameters) { - const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, Weak); + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelWeak); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); @@ -402,7 +402,7 @@ TEST(StoredKey, CreateWeakEncryptionParameters) { } TEST(StoredKey, CreateStandardEncryptionParameters) { - const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, Standard); + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelStandard); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); From 48c23c468a1d28929609b89fd076d8c7ad060952 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:30:17 +0100 Subject: [PATCH 09/12] Expose encryption level in TWStoredKeyCreate --- include/TrustWalletCore/TWStoredKey.h | 6 +++++- src/Keystore/StoredKey.cpp | 6 +++--- src/Keystore/StoredKey.h | 4 ++-- src/interface/TWStoredKey.cpp | 8 ++++++-- tests/Keystore/StoredKeyTests.cpp | 16 ++++++++-------- tests/interface/TWStoredKeyTests.cpp | 4 ++-- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/include/TrustWalletCore/TWStoredKey.h b/include/TrustWalletCore/TWStoredKey.h index f5114ebf6e9..ffbf48f3474 100644 --- a/include/TrustWalletCore/TWStoredKey.h +++ b/include/TrustWalletCore/TWStoredKey.h @@ -36,7 +36,11 @@ struct TWStoredKey* _Nullable TWStoredKeyImportHDWallet(TWString* _Nonnull mnemo TW_EXPORT_STATIC_METHOD struct TWStoredKey* _Nullable TWStoredKeyImportJSON(TWData* _Nonnull json); -/// Creates a new key. Returned object needs to be deleted. +/// Creates a new key, with given encrpytion strength level. Returned object needs to be deleted. +TW_EXPORT_STATIC_METHOD +struct TWStoredKey* _Nonnull TWStoredKeyCreateLevel(TWString* _Nonnull name, TWData* _Nonnull password, enum TWStoredKeyEncryptionLevel encryptionLevel); + +/// DEPRECATED, use TWStoredKeyCreateLevel. Creates a new key. Returned object needs to be deleted. TW_EXPORT_STATIC_METHOD struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password); diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index dd2251dff77..37cde5b0c27 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -37,17 +37,17 @@ StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& pas return key; } -StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const Data& password) { +StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const Data& password, TWStoredKeyEncryptionLevel encryptionLevel) { const auto wallet = TW::HDWallet(128, ""); const auto& mnemonic = wallet.getMnemonic(); assert(Mnemonic::isValid(mnemonic)); Data mnemonicData = TW::Data(mnemonic.begin(), mnemonic.end()); - StoredKey key = StoredKey(StoredKeyType::mnemonicPhrase, name, password, mnemonicData); + StoredKey key = StoredKey(StoredKeyType::mnemonicPhrase, name, password, mnemonicData, encryptionLevel); return key; } StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name, const Data& password, const std::string& mnemonic, TWCoinType coin) { - StoredKey key = createWithMnemonic(name, password, mnemonic); + StoredKey key = createWithMnemonic(name, password, mnemonic, TWEncryptionLevelDefault); const auto wallet = HDWallet(mnemonic, ""); const auto derivationPath = TW::derivationPath(coin); diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index 5fc8320ccb8..2c7c715a204 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -43,11 +43,11 @@ class StoredKey { /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel = TWEncryptionLevelDefault); + static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic, TWStoredKeyEncryptionLevel encryptionLevel); /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonicRandom(const std::string& name, const Data& password); + static StoredKey createWithMnemonicRandom(const std::string& name, const Data& password, TWStoredKeyEncryptionLevel encryptionLevel); /// Create a new StoredKey, with the given name, mnemonic and password, and also add the default address for the given coin.. /// @throws std::invalid_argument if mnemonic is invalid diff --git a/src/interface/TWStoredKey.cpp b/src/interface/TWStoredKey.cpp index f774cd07f82..618a85ed29e 100644 --- a/src/interface/TWStoredKey.cpp +++ b/src/interface/TWStoredKey.cpp @@ -25,10 +25,14 @@ struct TWStoredKey* _Nullable TWStoredKeyLoad(TWString* _Nonnull path) { } } -struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password) { +struct TWStoredKey* _Nonnull TWStoredKeyCreateLevel(TWString* _Nonnull name, TWData* _Nonnull password, enum TWStoredKeyEncryptionLevel encryptionLevel) { const auto& nameString = *reinterpret_cast(name); const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); - return new TWStoredKey{ StoredKey::createWithMnemonicRandom(nameString, passwordData) }; + return new TWStoredKey{ StoredKey::createWithMnemonicRandom(nameString, passwordData, encryptionLevel) }; +} + +struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password) { + return TWStoredKeyCreateLevel(name, password, TWEncryptionLevelDefault); } struct TWStoredKey* _Nullable TWStoredKeyImportPrivateKey(TWData* _Nonnull privateKey, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin) { diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index fe6799e867f..747665125a7 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -31,7 +31,7 @@ const TWCoinType coinTypeEth = TWCoinTypeEthereum; const TWCoinType coinTypeBscLegacy = TWCoinTypeSmartChainLegacy; TEST(StoredKey, CreateWithMnemonic) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); @@ -46,7 +46,7 @@ TEST(StoredKey, CreateWithMnemonic) { TEST(StoredKey, CreateWithMnemonicInvalid) { try { - auto key = StoredKey::createWithMnemonic("name", password, "_THIS_IS_NOT_A_VALID_MNEMONIC_"); + auto key = StoredKey::createWithMnemonic("name", password, "_THIS_IS_NOT_A_VALID_MNEMONIC_", TWEncryptionLevelDefault); } catch (std::invalid_argument&) { // expedcted exception OK return; @@ -55,7 +55,7 @@ TEST(StoredKey, CreateWithMnemonicInvalid) { } TEST(StoredKey, CreateWithMnemonicRandom) { - const auto key = StoredKey::createWithMnemonicRandom("name", password); + const auto key = StoredKey::createWithMnemonicRandom("name", password, TWEncryptionLevelDefault); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); // random mnemonic: check only length and validity const Data& mnemo2Data = key.payload.decrypt(password); @@ -102,7 +102,7 @@ TEST(StoredKey, CreateWithPrivateKeyAddDefaultAddressInvalid) { } TEST(StoredKey, AccountGetCreate) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); EXPECT_EQ(key.accounts.size(), 0); // not exists @@ -140,7 +140,7 @@ TEST(StoredKey, AccountGetCreate) { } TEST(StoredKey, AccountGetDoesntChange) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); auto wallet = key.wallet(password); EXPECT_EQ(key.accounts.size(), 0); @@ -164,7 +164,7 @@ TEST(StoredKey, AccountGetDoesntChange) { } TEST(StoredKey, AddRemoveAccount) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); EXPECT_EQ(key.accounts.size(), 0); { @@ -195,7 +195,7 @@ TEST(StoredKey, AddRemoveAccount) { TEST(StoredKey, FixAddress) { { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); key.fixAddresses(password); } { @@ -333,7 +333,7 @@ TEST(StoredKey, CreateWallet) { TEST(StoredKey, CreateAccounts) { string mnemonicPhrase = "team engine square letter hero song dizzy scrub tornado fabric divert saddle"; - auto key = StoredKey::createWithMnemonic("name", password, mnemonicPhrase); + auto key = StoredKey::createWithMnemonic("name", password, mnemonicPhrase, TWEncryptionLevelDefault); const auto wallet = key.wallet(password); EXPECT_EQ(key.account(TWCoinTypeEthereum, &wallet)->address, "0x494f60cb6Ac2c8F5E1393aD9FdBdF4Ad589507F7"); diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index f5c816fd9bf..86deed31d28 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -57,7 +57,7 @@ TEST(TWStoredKey, createWallet) { const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); - const auto key = WRAP(TWStoredKey, TWStoredKeyCreate(name.get(), password.get())); + const auto key = WRAP(TWStoredKey, TWStoredKeyCreateLevel(name.get(), password.get(), TWEncryptionLevelDefault)); const auto name2 = WRAPS(TWStoredKeyName(key.get())); EXPECT_EQ(string(TWStringUTF8Bytes(name2.get())), "name"); const auto mnemonic = WRAPS(TWStoredKeyDecryptMnemonic(key.get(), password.get())); @@ -222,7 +222,7 @@ TEST(TWStoredKey, getWalletPasswordInvalid) { const auto invalidString = WRAPS(TWStringCreateWithUTF8Bytes("_THIS_IS_INVALID_PASSWORD_")); const auto passwordInvalid = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(invalidString.get())), TWStringSize(invalidString.get()))); - auto key = WRAP(TWStoredKey, TWStoredKeyCreate (name.get(), password.get())); + auto key = WRAP(TWStoredKey, TWStoredKeyCreate(name.get(), password.get())); ASSERT_NE(WRAP(TWHDWallet, TWStoredKeyWallet(key.get(), password.get())).get(), nullptr); ASSERT_EQ(WRAP(TWHDWallet, TWStoredKeyWallet(key.get(), passwordInvalid.get())).get(), nullptr); } From 6295d80a85816d83a3c118928940ca3f8dc981f1 Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:35:05 +0100 Subject: [PATCH 10/12] Remove StoreKey ctor parameter default value --- include/TrustWalletCore/TWEncryptionParameters.h | 3 ++- src/Keystore/StoredKey.cpp | 2 +- src/Keystore/StoredKey.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/TrustWalletCore/TWEncryptionParameters.h b/include/TrustWalletCore/TWEncryptionParameters.h index fd0e30b726f..2d0edef2c89 100644 --- a/include/TrustWalletCore/TWEncryptionParameters.h +++ b/include/TrustWalletCore/TWEncryptionParameters.h @@ -15,8 +15,9 @@ TW_EXPORT_ENUM(uint32_t) enum TWStoredKeyEncryptionLevel { /// Default, which is one of the below values, determined by the implementation. TWEncryptionLevelDefault = 0, - /// Minimal sufficient level of encryption strength + /// Minimal sufficient level of encryption strength (scrypt 4096) TWEncryptionLevelWeak, + /// Standard level of encryption strength (scrypt 262k) TWEncryptionLevelStandard, }; diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index 37cde5b0c27..1c16d49611c 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -59,7 +59,7 @@ StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name } StoredKey StoredKey::createWithPrivateKey(const std::string& name, const Data& password, const Data& privateKeyData) { - StoredKey key = StoredKey(StoredKeyType::privateKey, name, password, privateKeyData); + StoredKey key = StoredKey(StoredKeyType::privateKey, name, password, privateKeyData, TWEncryptionLevelDefault); return key; } diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index 2c7c715a204..bc156658653 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -119,7 +119,7 @@ class StoredKey { /// Initializes a `StoredKey` with a type, an encryption password, and unencrypted data. /// This contstructor will encrypt the provided data with default encryption /// parameters. - StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel = TWEncryptionLevelDefault); + StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data, TWStoredKeyEncryptionLevel encryptionLevel); }; } // namespace TW::Keystore From 7ad5503908902176e6f9c34372ba712205977b4d Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:43:19 +0100 Subject: [PATCH 11/12] Update TW enum, to fix swift/kotlin compilation --- include/TrustWalletCore/TWStoredKey.h | 2 +- ...ameters.h => TWStoredKeyEncryptionLevel.h} | 6 +++--- src/Keystore/EncryptionParameters.h | 12 ++++++----- src/Keystore/StoredKey.cpp | 4 ++-- src/interface/TWStoredKey.cpp | 2 +- tests/Keystore/StoredKeyTests.cpp | 20 +++++++++---------- tests/interface/TWStoredKeyTests.cpp | 2 +- 7 files changed, 25 insertions(+), 23 deletions(-) rename include/TrustWalletCore/{TWEncryptionParameters.h => TWStoredKeyEncryptionLevel.h} (84%) diff --git a/include/TrustWalletCore/TWStoredKey.h b/include/TrustWalletCore/TWStoredKey.h index ffbf48f3474..cbf427a9c56 100644 --- a/include/TrustWalletCore/TWStoredKey.h +++ b/include/TrustWalletCore/TWStoredKey.h @@ -12,7 +12,7 @@ #include "TWHDWallet.h" #include "TWPrivateKey.h" #include "TWString.h" -#include "TWEncryptionParameters.h" +#include "TWStoredKeyEncryptionLevel.h" TW_EXTERN_C_BEGIN diff --git a/include/TrustWalletCore/TWEncryptionParameters.h b/include/TrustWalletCore/TWStoredKeyEncryptionLevel.h similarity index 84% rename from include/TrustWalletCore/TWEncryptionParameters.h rename to include/TrustWalletCore/TWStoredKeyEncryptionLevel.h index 2d0edef2c89..587d88b60c7 100644 --- a/include/TrustWalletCore/TWEncryptionParameters.h +++ b/include/TrustWalletCore/TWStoredKeyEncryptionLevel.h @@ -14,11 +14,11 @@ TW_EXTERN_C_BEGIN TW_EXPORT_ENUM(uint32_t) enum TWStoredKeyEncryptionLevel { /// Default, which is one of the below values, determined by the implementation. - TWEncryptionLevelDefault = 0, + TWStoredKeyEncryptionLevelDefault = 0, /// Minimal sufficient level of encryption strength (scrypt 4096) - TWEncryptionLevelWeak, + TWStoredKeyEncryptionLevelWeak = 1, /// Standard level of encryption strength (scrypt 262k) - TWEncryptionLevelStandard, + TWStoredKeyEncryptionLevelStandard = 2, }; TW_EXTERN_C_END diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index 7c14f1deaa6..05fdfdde273 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -10,7 +10,7 @@ #include "PBKDF2Parameters.h" #include "ScryptParameters.h" #include "../Data.h" -#include +#include #include #include @@ -22,10 +22,12 @@ namespace TW::Keystore { struct EncryptionParameters { static EncryptionParameters getPreset(enum TWStoredKeyEncryptionLevel preset) { switch (preset) { - case TWEncryptionLevelWeak: - case TWEncryptionLevelDefault: - default: return EncryptionParameters(AESParameters(), ScryptParameters::Light); - case TWEncryptionLevelStandard: return EncryptionParameters(AESParameters(), ScryptParameters::Standard); + case TWStoredKeyEncryptionLevelWeak: + case TWStoredKeyEncryptionLevelDefault: + default: + return EncryptionParameters(AESParameters(), ScryptParameters::Light); + case TWStoredKeyEncryptionLevelStandard: + return EncryptionParameters(AESParameters(), ScryptParameters::Standard); } } diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index 1c16d49611c..3272305b4a6 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -47,7 +47,7 @@ StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const Dat } StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name, const Data& password, const std::string& mnemonic, TWCoinType coin) { - StoredKey key = createWithMnemonic(name, password, mnemonic, TWEncryptionLevelDefault); + StoredKey key = createWithMnemonic(name, password, mnemonic, TWStoredKeyEncryptionLevelDefault); const auto wallet = HDWallet(mnemonic, ""); const auto derivationPath = TW::derivationPath(coin); @@ -59,7 +59,7 @@ StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name } StoredKey StoredKey::createWithPrivateKey(const std::string& name, const Data& password, const Data& privateKeyData) { - StoredKey key = StoredKey(StoredKeyType::privateKey, name, password, privateKeyData, TWEncryptionLevelDefault); + StoredKey key = StoredKey(StoredKeyType::privateKey, name, password, privateKeyData, TWStoredKeyEncryptionLevelDefault); return key; } diff --git a/src/interface/TWStoredKey.cpp b/src/interface/TWStoredKey.cpp index 618a85ed29e..b5b86031f4f 100644 --- a/src/interface/TWStoredKey.cpp +++ b/src/interface/TWStoredKey.cpp @@ -32,7 +32,7 @@ struct TWStoredKey* _Nonnull TWStoredKeyCreateLevel(TWString* _Nonnull name, TWD } struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password) { - return TWStoredKeyCreateLevel(name, password, TWEncryptionLevelDefault); + return TWStoredKeyCreateLevel(name, password, TWStoredKeyEncryptionLevelDefault); } struct TWStoredKey* _Nullable TWStoredKeyImportPrivateKey(TWData* _Nonnull privateKey, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin) { diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index 747665125a7..41b72e82e7a 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -31,7 +31,7 @@ const TWCoinType coinTypeEth = TWCoinTypeEthereum; const TWCoinType coinTypeBscLegacy = TWCoinTypeSmartChainLegacy; TEST(StoredKey, CreateWithMnemonic) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelDefault); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); @@ -46,7 +46,7 @@ TEST(StoredKey, CreateWithMnemonic) { TEST(StoredKey, CreateWithMnemonicInvalid) { try { - auto key = StoredKey::createWithMnemonic("name", password, "_THIS_IS_NOT_A_VALID_MNEMONIC_", TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, "_THIS_IS_NOT_A_VALID_MNEMONIC_", TWStoredKeyEncryptionLevelDefault); } catch (std::invalid_argument&) { // expedcted exception OK return; @@ -55,7 +55,7 @@ TEST(StoredKey, CreateWithMnemonicInvalid) { } TEST(StoredKey, CreateWithMnemonicRandom) { - const auto key = StoredKey::createWithMnemonicRandom("name", password, TWEncryptionLevelDefault); + const auto key = StoredKey::createWithMnemonicRandom("name", password, TWStoredKeyEncryptionLevelDefault); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); // random mnemonic: check only length and validity const Data& mnemo2Data = key.payload.decrypt(password); @@ -102,7 +102,7 @@ TEST(StoredKey, CreateWithPrivateKeyAddDefaultAddressInvalid) { } TEST(StoredKey, AccountGetCreate) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelDefault); EXPECT_EQ(key.accounts.size(), 0); // not exists @@ -140,7 +140,7 @@ TEST(StoredKey, AccountGetCreate) { } TEST(StoredKey, AccountGetDoesntChange) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelDefault); auto wallet = key.wallet(password); EXPECT_EQ(key.accounts.size(), 0); @@ -164,7 +164,7 @@ TEST(StoredKey, AccountGetDoesntChange) { } TEST(StoredKey, AddRemoveAccount) { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelDefault); EXPECT_EQ(key.accounts.size(), 0); { @@ -195,7 +195,7 @@ TEST(StoredKey, AddRemoveAccount) { TEST(StoredKey, FixAddress) { { - auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelDefault); key.fixAddresses(password); } { @@ -333,7 +333,7 @@ TEST(StoredKey, CreateWallet) { TEST(StoredKey, CreateAccounts) { string mnemonicPhrase = "team engine square letter hero song dizzy scrub tornado fabric divert saddle"; - auto key = StoredKey::createWithMnemonic("name", password, mnemonicPhrase, TWEncryptionLevelDefault); + auto key = StoredKey::createWithMnemonic("name", password, mnemonicPhrase, TWStoredKeyEncryptionLevelDefault); const auto wallet = key.wallet(password); EXPECT_EQ(key.account(TWCoinTypeEthereum, &wallet)->address, "0x494f60cb6Ac2c8F5E1393aD9FdBdF4Ad589507F7"); @@ -384,7 +384,7 @@ TEST(StoredKey, EtherWalletAddressNo0x) { } TEST(StoredKey, CreateWeakEncryptionParameters) { - const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelWeak); + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelWeak); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); @@ -402,7 +402,7 @@ TEST(StoredKey, CreateWeakEncryptionParameters) { } TEST(StoredKey, CreateStandardEncryptionParameters) { - const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWEncryptionLevelStandard); + const auto key = StoredKey::createWithMnemonic("name", password, mnemonic, TWStoredKeyEncryptionLevelStandard); EXPECT_EQ(key.type, StoredKeyType::mnemonicPhrase); const Data& mnemo2Data = key.payload.decrypt(password); EXPECT_EQ(string(mnemo2Data.begin(), mnemo2Data.end()), string(mnemonic)); diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index 86deed31d28..f2f47e09a6c 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -57,7 +57,7 @@ TEST(TWStoredKey, createWallet) { const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); - const auto key = WRAP(TWStoredKey, TWStoredKeyCreateLevel(name.get(), password.get(), TWEncryptionLevelDefault)); + const auto key = WRAP(TWStoredKey, TWStoredKeyCreateLevel(name.get(), password.get(), TWStoredKeyEncryptionLevelDefault)); const auto name2 = WRAPS(TWStoredKeyName(key.get())); EXPECT_EQ(string(TWStringUTF8Bytes(name2.get())), "name"); const auto mnemonic = WRAPS(TWStoredKeyDecryptMnemonic(key.get(), password.get())); From 36ce2b138e62c344a248707fb7dc4b94343991da Mon Sep 17 00:00:00 2001 From: catenocrypt <13562139+catenocrypt@users.noreply.github.com> Date: Fri, 19 Nov 2021 16:47:57 +0100 Subject: [PATCH 12/12] Proper breakup of json parse/create --- src/Keystore/EncryptionParameters.cpp | 81 +++++++++++++++------------ src/Keystore/EncryptionParameters.h | 3 + 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/Keystore/EncryptionParameters.cpp b/src/Keystore/EncryptionParameters.cpp index 4662b48e0e4..406474e638a 100644 --- a/src/Keystore/EncryptionParameters.cpp +++ b/src/Keystore/EncryptionParameters.cpp @@ -28,6 +28,49 @@ static Data computeMAC(Iter begin, Iter end, const Data& key) { return Hash::keccak256(data); } +// ----------------- +// Encoding/Decoding +// ----------------- + +namespace CodingKeys { +static const auto encrypted = "ciphertext"; +static const auto cipher = "cipher"; +static const auto cipherParams = "cipherparams"; +static const auto kdf = "kdf"; +static const auto kdfParams = "kdfparams"; +static const auto mac = "mac"; +} // namespace CodingKeys + +EncryptionParameters::EncryptionParameters(const nlohmann::json& json) { + cipher = json[CodingKeys::cipher].get(); + cipherParams = AESParameters(json[CodingKeys::cipherParams]); + + auto kdf = json[CodingKeys::kdf].get(); + if (kdf == "scrypt") { + kdfParams = ScryptParameters(json[CodingKeys::kdfParams]); + } else if (kdf == "pbkdf2") { + kdfParams = PBKDF2Parameters(json[CodingKeys::kdfParams]); + } +} + +nlohmann::json EncryptionParameters::json() const { + nlohmann::json j; + j[CodingKeys::cipher] = cipher; + j[CodingKeys::cipherParams] = cipherParams.json(); + + if (kdfParams.which() == 0) { + auto scryptParams = boost::get(kdfParams); + j[CodingKeys::kdf] = "scrypt"; + j[CodingKeys::kdfParams] = scryptParams.json(); + } else if (kdfParams.which() == 1) { + auto pbkdf2Params = boost::get(kdfParams); + j[CodingKeys::kdf] = "pbkdf2"; + j[CodingKeys::kdfParams] = pbkdf2Params.json(); + } + + return j; +} + EncryptedPayload::EncryptedPayload(const Data& password, const Data& data, const EncryptionParameters& params) : params(std::move(params)), mac() { auto scryptParams = boost::get(params.kdfParams); @@ -103,49 +146,15 @@ Data EncryptedPayload::decrypt(const Data& password) const { return decrypted; } -// ----------------- -// Encoding/Decoding -// ----------------- - -namespace CodingKeys { -static const auto encrypted = "ciphertext"; -static const auto cipher = "cipher"; -static const auto cipherParams = "cipherparams"; -static const auto kdf = "kdf"; -static const auto kdfParams = "kdfparams"; -static const auto mac = "mac"; -} // namespace CodingKeys - EncryptedPayload::EncryptedPayload(const nlohmann::json& json) { + params = EncryptionParameters(json); encrypted = parse_hex(json[CodingKeys::encrypted].get()); - params.cipher = json[CodingKeys::cipher].get(); - params.cipherParams = AESParameters(json[CodingKeys::cipherParams]); mac = parse_hex(json[CodingKeys::mac].get()); - - auto kdf = json[CodingKeys::kdf].get(); - if (kdf == "scrypt") { - params.kdfParams = ScryptParameters(json[CodingKeys::kdfParams]); - } else if (kdf == "pbkdf2") { - params.kdfParams = PBKDF2Parameters(json[CodingKeys::kdfParams]); - } } nlohmann::json EncryptedPayload::json() const { - nlohmann::json j; + nlohmann::json j = params.json(); j[CodingKeys::encrypted] = hex(encrypted); - j[CodingKeys::cipher] = params.cipher; - j[CodingKeys::cipherParams] = params.cipherParams.json(); j[CodingKeys::mac] = hex(mac); - - if (params.kdfParams.which() == 0) { - auto scryptParams = boost::get(params.kdfParams); - j[CodingKeys::kdf] = "scrypt"; - j[CodingKeys::kdfParams] = scryptParams.json(); - } else if (params.kdfParams.which() == 1) { - auto pbkdf2Params = boost::get(params.kdfParams); - j[CodingKeys::kdf] = "pbkdf2"; - j[CodingKeys::kdfParams] = pbkdf2Params.json(); - } - return j; } diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index 05fdfdde273..1d5a70f819c 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -47,6 +47,9 @@ struct EncryptionParameters { : cipherParams(std::move(cipherParams)) , kdfParams(std::move(kdfParams)) {} + /// Initializes with a JSON object. + EncryptionParameters(const nlohmann::json& json); + /// Saves `this` as a JSON object. nlohmann::json json() const;