-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathScryptParameters.cpp
More file actions
127 lines (104 loc) · 3.85 KB
/
ScryptParameters.cpp
File metadata and controls
127 lines (104 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// SPDX-License-Identifier: Apache-2.0
//
// Copyright © 2017 Trust Wallet.
#include "ScryptParameters.h"
#include <TrezorCrypto/rand.h>
#include <limits>
#include <sstream>
using namespace TW;
namespace TW::Keystore {
namespace internal {
Data randomSalt() {
Data salt(32);
random_buffer(salt.data(), salt.size());
return salt;
}
} // namespace internal
std::string toString(const ScryptValidationError error) {
switch (error) {
case ScryptValidationError::desiredKeyLengthTooLarge:
return "Desired key length is too large";
case ScryptValidationError::invalidSaltLength:
return "Salt length is invalid";
case ScryptValidationError::blockSizeTooLarge:
return "Block size (r * p) is too large";
case ScryptValidationError::invalidCostFactor:
return "Cost factor n must be a power of 2 greater than 1";
case ScryptValidationError::overflow:
return "Parameters are too large and may cause overflow";
default:
return "Unknown error";
}
}
ScryptParameters ScryptParameters::minimal() {
return { internal::randomSalt(), minimalN, defaultR, minimalP, defaultDesiredKeyLength };
}
ScryptParameters ScryptParameters::weak() {
return { internal::randomSalt(), weakN, defaultR, weakP, defaultDesiredKeyLength };
}
ScryptParameters ScryptParameters::standard() {
return { internal::randomSalt(), standardN, defaultR, standardP, defaultDesiredKeyLength };
}
ScryptParameters::ScryptParameters()
: salt(internal::randomSalt()) {
}
#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
std::optional<ScryptValidationError> ScryptParameters::validate() const {
if (desiredKeyLength > ((1ULL << 32) - 1) * 32) { // depending on size_t size on platform, may be always false
return ScryptValidationError::desiredKeyLengthTooLarge;
}
if (salt.size() < minSaltLength || salt.size() > maxSaltLength) {
return ScryptValidationError::invalidSaltLength;
}
if (static_cast<uint64_t>(r) * static_cast<uint64_t>(p) >= (1 << 30)) {
return ScryptValidationError::blockSizeTooLarge;
}
if ((n & (n - 1)) != 0 || n < 2) {
return ScryptValidationError::invalidCostFactor;
}
if ((r > std::numeric_limits<uint32_t>::max() / 128 / p) ||
(n > std::numeric_limits<uint32_t>::max() / 128 / r)) {
return ScryptValidationError::overflow;
}
return {};
}
// -----------------
// Encoding/Decoding
// -----------------
namespace CodingKeys::SP {
static const auto salt = "salt";
static const auto desiredKeyLength = "dklen";
static const auto n = "n";
static const auto p = "p";
static const auto r = "r";
} // namespace CodingKeys::SP
ScryptParameters::ScryptParameters(const nlohmann::json& json) {
if (json.count(CodingKeys::SP::n) == 0
|| json.count(CodingKeys::SP::p) == 0
|| json.count(CodingKeys::SP::r) == 0
|| json.count(CodingKeys::SP::salt) == 0
|| json.count(CodingKeys::SP::desiredKeyLength) == 0) {
throw std::invalid_argument("Missing required scrypt parameters n, p, r, salt, or dklen");
}
salt = parse_hex(json[CodingKeys::SP::salt].get<std::string>());
desiredKeyLength = json[CodingKeys::SP::desiredKeyLength];
n = json[CodingKeys::SP::n];
p = json[CodingKeys::SP::p];
r = json[CodingKeys::SP::r];
if (const auto error = validate()) {
std::stringstream ss;
ss << "Invalid scrypt parameters: " << toString(*error);
throw std::invalid_argument(ss.str());
}
}
/// Saves `this` as a JSON object.
nlohmann::json ScryptParameters::json() const {
nlohmann::json j;
j[CodingKeys::SP::salt] = hex(salt);
j[CodingKeys::SP::desiredKeyLength] = desiredKeyLength;
j[CodingKeys::SP::n] = n;
j[CodingKeys::SP::p] = p;
j[CodingKeys::SP::r] = r;
return j;
}
} // namespace TW::Keystore