xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
xrpld
rpc
handlers
admin
keygen
WalletPropose.cpp
1
#include <xrpld/rpc/handlers/admin/keygen/WalletPropose.h>
2
3
#include <xrpld/rpc/Context.h>
4
#include <xrpld/rpc/detail/RPCHelpers.h>
5
6
#include <xrpl/basics/strHex.h>
7
#include <xrpl/json/json_value.h>
8
#include <xrpl/protocol/AccountID.h>
9
#include <xrpl/protocol/ErrorCodes.h>
10
#include <xrpl/protocol/KeyType.h>
11
#include <xrpl/protocol/PublicKey.h>
12
#include <xrpl/protocol/RPCErr.h>
13
#include <xrpl/protocol/SecretKey.h>
14
#include <xrpl/protocol/Seed.h>
15
#include <xrpl/protocol/jss.h>
16
#include <xrpl/protocol/tokens.h>
17
18
#include <
cmath
>
19
#include <
map
>
20
#include <
optional
>
21
#include <
string
>
22
23
namespace
xrpl
{
24
25
double
26
estimateEntropy
(
std::string
const
& input)
27
{
28
// First, we calculate the Shannon entropy. This gives
29
// the average number of bits per symbol that we would
30
// need to encode the input.
31
std::map<int, double>
freq;
32
33
for
(
auto
const
& c : input)
34
freq[c]++;
35
36
double
se = 0.0;
37
38
for
(
auto
const
& [_, f] : freq)
39
{
40
(void)_;
41
auto
x = f / input.
length
();
42
se += x * log2(x);
43
}
44
45
// We multiply it by the length, to get an estimate of
46
// the number of bits in the input. We floor because it
47
// is better to be conservative.
48
return
std::floor
(-se * input.
length
());
49
}
50
51
// {
52
// passphrase: <string>
53
// }
54
json::Value
55
doWalletPropose
(
rpc::JsonContext
& context)
56
{
57
return
walletPropose
(context.
params
);
58
}
59
60
json::Value
61
walletPropose
(
json::Value
const
& params)
62
{
63
std::optional<KeyType>
keyType;
64
std::optional<Seed>
seed;
65
bool
libSeed =
false
;
66
67
if
(params.
isMember
(jss::key_type))
68
{
69
if
(!params[jss::key_type].isString())
70
{
71
return
rpc::expectedFieldError
(jss::key_type,
"string"
);
72
}
73
74
keyType =
keyTypeFromString
(params[jss::key_type].asString());
75
76
if
(!keyType)
77
return
rpcError
(
RpcInvalidParams
);
78
}
79
80
// XrplLib encodes seed used to generate an Ed25519 wallet in a
81
// non-standard way. While we never encode seeds that way, we try
82
// to detect such keys to avoid user confusion.
83
{
84
if
(params.
isMember
(jss::passphrase))
85
{
86
seed =
rpc::parseXrplLibSeed
(params[jss::passphrase]);
87
}
88
else
if
(params.
isMember
(jss::seed))
89
{
90
seed =
rpc::parseXrplLibSeed
(params[jss::seed]);
91
}
92
93
if
(seed)
94
{
95
libSeed =
true
;
96
97
// If the user *explicitly* requests a key type other than
98
// Ed25519 we return an error.
99
if
(keyType.
value_or
(
KeyType::Ed25519
) !=
KeyType::Ed25519
)
100
return
rpcError
(
RpcBadSeed
);
101
102
keyType =
KeyType::Ed25519
;
103
}
104
}
105
106
if
(!seed)
107
{
108
if
(params.
isMember
(jss::passphrase) || params.
isMember
(jss::seed) ||
109
params.
isMember
(jss::seed_hex))
110
{
111
json::Value
err;
112
113
seed =
rpc::getSeedFromRPC
(params, err);
114
115
if
(!seed)
116
return
err;
117
}
118
else
119
{
120
seed =
randomSeed
();
121
}
122
}
123
124
if
(!keyType)
125
keyType =
KeyType::Secp256k1
;
126
127
auto
const
publicKey =
generateKeyPair
(*keyType, *seed).first;
128
129
json::Value
obj(
json::ValueType::Object
);
130
131
auto
const
seed1751 =
seedAs1751
(*seed);
132
auto
const
seedHex =
strHex
(*seed);
133
auto
const
seedBase58 =
toBase58
(*seed);
134
135
obj[jss::master_seed] = seedBase58;
136
obj[jss::master_seed_hex] = seedHex;
137
obj[jss::master_key] = seed1751;
138
obj[jss::account_id] =
toBase58
(
calcAccountID
(publicKey));
139
obj[jss::public_key] =
toBase58
(
TokenType::AccountPublic
, publicKey);
140
obj[jss::key_type] =
to_string
(*keyType);
141
obj[jss::public_key_hex] =
strHex
(publicKey);
142
143
// If a passphrase was specified, and it was hashed and used as a seed
144
// run a quick entropy check and add an appropriate warning, because
145
// "brain wallets" can be easily attacked.
146
if
(!libSeed && params.
isMember
(jss::passphrase))
147
{
148
auto
const
passphrase = params[jss::passphrase].
asString
();
149
150
if
(passphrase != seed1751 && passphrase != seedBase58 && passphrase != seedHex)
151
{
152
// 80 bits of entropy isn't bad, but it's better to
153
// err on the side of caution and be conservative.
154
if
(
estimateEntropy
(passphrase) < 80.0)
155
{
156
obj[jss::warning] =
157
"This wallet was generated using a user-supplied "
158
"passphrase that has low entropy and is vulnerable "
159
"to brute-force attacks."
;
160
}
161
else
162
{
163
obj[jss::warning] =
164
"This wallet was generated using a user-supplied "
165
"passphrase. It may be vulnerable to brute-force "
166
"attacks."
;
167
}
168
}
169
}
170
171
return
obj;
172
}
173
174
}
// namespace xrpl
std::string
json::Value
Represents a JSON value.
Definition
json_value.h:117
json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition
json_value.cpp:494
json::Value::isMember
bool isMember(char const *key) const
Return true if the object has a member named key.
Definition
json_value.cpp:1049
cmath
std::floor
T floor(T... args)
map
json::ValueType::Object
@ Object
object value (collection of name/value pairs).
Definition
json_value.h:29
xrpl::rpc::expectedFieldError
json::Value expectedFieldError(std::string const &name, std::string const &type)
Definition
ErrorCodes.h:309
xrpl::rpc::getSeedFromRPC
std::optional< Seed > getSeedFromRPC(json::Value const ¶ms, json::Value &error)
Extracts a Seed from RPC parameters.
Definition
RPCHelpers.cpp:187
xrpl::rpc::parseXrplLibSeed
std::optional< Seed > parseXrplLibSeed(json::Value const &value)
Parses a XrplLib seed from RPC parameters.
Definition
RPCHelpers.cpp:169
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::KeyType::Secp256k1
@ Secp256k1
Definition
KeyType.h:9
xrpl::KeyType::Ed25519
@ Ed25519
Definition
KeyType.h:10
xrpl::RpcInvalidParams
@ RpcInvalidParams
Definition
ErrorCodes.h:67
xrpl::RpcBadSeed
@ RpcBadSeed
Definition
ErrorCodes.h:82
xrpl::keyTypeFromString
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition
KeyType.h:14
xrpl::randomSeed
Seed randomSeed()
Create a seed using secure random numbers.
Definition
Seed.cpp:48
xrpl::strHex
std::string strHex(FwdIt begin, FwdIt end)
Definition
strHex.h:13
xrpl::doWalletPropose
json::Value doWalletPropose(rpc::JsonContext &context)
Definition
WalletPropose.cpp:55
xrpl::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition
AccountID.cpp:95
xrpl::seedAs1751
std::string seedAs1751(Seed const &seed)
Encode a Seed in RFC1751 format.
Definition
Seed.cpp:116
xrpl::generateKeyPair
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Definition
SecretKey.cpp:338
xrpl::to_string
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition
base_uint.h:657
xrpl::rpcError
json::Value rpcError(ErrorCodeI iError)
Definition
RPCErr.cpp:13
xrpl::walletPropose
json::Value walletPropose(json::Value const ¶ms)
Definition
WalletPropose.cpp:61
xrpl::calcAccountID
AccountID calcAccountID(PublicKey const &pk)
Definition
AccountID.cpp:149
xrpl::TokenType::AccountPublic
@ AccountPublic
Definition
tokens.h:24
xrpl::estimateEntropy
double estimateEntropy(std::string const &input)
Definition
WalletPropose.cpp:26
optional
std::string::length
T length(T... args)
string
xrpl::rpc::JsonContext
Definition
Context.h:41
xrpl::rpc::JsonContext::params
json::Value params
Definition
Context.h:51
std::optional::value_or
T value_or(T... args)
Generated by
1.17.0