rippled
Loading...
Searching...
No Matches
WalletPropose.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2014 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/rpc/Context.h>
21#include <xrpld/rpc/detail/RPCHelpers.h>
22#include <xrpld/rpc/handlers/WalletPropose.h>
23
24#include <xrpl/basics/strHex.h>
25#include <xrpl/protocol/ErrorCodes.h>
26#include <xrpl/protocol/KeyType.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/RPCErr.h>
29#include <xrpl/protocol/SecretKey.h>
30#include <xrpl/protocol/Seed.h>
31#include <xrpl/protocol/jss.h>
32
33#include <cmath>
34#include <map>
35
36namespace ripple {
37
38double
40{
41 // First, we calculate the Shannon entropy. This gives
42 // the average number of bits per symbol that we would
43 // need to encode the input.
45
46 for (auto const& c : input)
47 freq[c]++;
48
49 double se = 0.0;
50
51 for (auto const& [_, f] : freq)
52 {
53 (void)_;
54 auto x = f / input.length();
55 se += (x)*log2(x);
56 }
57
58 // We multiply it by the length, to get an estimate of
59 // the number of bits in the input. We floor because it
60 // is better to be conservative.
61 return std::floor(-se * input.length());
62}
63
64// {
65// passphrase: <string>
66// }
69{
70 return walletPropose(context.params);
71}
72
75{
78 bool rippleLibSeed = false;
79
80 if (params.isMember(jss::key_type))
81 {
82 if (!params[jss::key_type].isString())
83 {
84 return RPC::expected_field_error(jss::key_type, "string");
85 }
86
87 keyType = keyTypeFromString(params[jss::key_type].asString());
88
89 if (!keyType)
91 }
92
93 // ripple-lib encodes seed used to generate an Ed25519 wallet in a
94 // non-standard way. While we never encode seeds that way, we try
95 // to detect such keys to avoid user confusion.
96 {
97 if (params.isMember(jss::passphrase))
98 seed = RPC::parseRippleLibSeed(params[jss::passphrase]);
99 else if (params.isMember(jss::seed))
100 seed = RPC::parseRippleLibSeed(params[jss::seed]);
101
102 if (seed)
103 {
104 rippleLibSeed = true;
105
106 // If the user *explicitly* requests a key type other than
107 // Ed25519 we return an error.
109 return rpcError(rpcBAD_SEED);
110
111 keyType = KeyType::ed25519;
112 }
113 }
114
115 if (!seed)
116 {
117 if (params.isMember(jss::passphrase) || params.isMember(jss::seed) ||
118 params.isMember(jss::seed_hex))
119 {
120 Json::Value err;
121
122 seed = RPC::getSeedFromRPC(params, err);
123
124 if (!seed)
125 return err;
126 }
127 else
128 {
129 seed = randomSeed();
130 }
131 }
132
133 if (!keyType)
134 keyType = KeyType::secp256k1;
135
136 auto const publicKey = generateKeyPair(*keyType, *seed).first;
137
139
140 auto const seed1751 = seedAs1751(*seed);
141 auto const seedHex = strHex(*seed);
142 auto const seedBase58 = toBase58(*seed);
143
144 obj[jss::master_seed] = seedBase58;
145 obj[jss::master_seed_hex] = seedHex;
146 obj[jss::master_key] = seed1751;
147 obj[jss::account_id] = toBase58(calcAccountID(publicKey));
148 obj[jss::public_key] = toBase58(TokenType::AccountPublic, publicKey);
149 obj[jss::key_type] = to_string(*keyType);
150 obj[jss::public_key_hex] = strHex(publicKey);
151
152 // If a passphrase was specified, and it was hashed and used as a seed
153 // run a quick entropy check and add an appropriate warning, because
154 // "brain wallets" can be easily attacked.
155 if (!rippleLibSeed && params.isMember(jss::passphrase))
156 {
157 auto const passphrase = params[jss::passphrase].asString();
158
159 if (passphrase != seed1751 && passphrase != seedBase58 &&
160 passphrase != seedHex)
161 {
162 // 80 bits of entropy isn't bad, but it's better to
163 // err on the side of caution and be conservative.
164 if (estimate_entropy(passphrase) < 80.0)
165 obj[jss::warning] =
166 "This wallet was generated using a user-supplied "
167 "passphrase that has low entropy and is vulnerable "
168 "to brute-force attacks.";
169 else
170 obj[jss::warning] =
171 "This wallet was generated using a user-supplied "
172 "passphrase. It may be vulnerable to brute-force "
173 "attacks.";
174 }
175 }
176
177 return obj;
178}
179
180} // namespace ripple
Represents a JSON value.
Definition json_value.h:149
std::string asString() const
Returns the unquoted string value.
bool isMember(char const *key) const
Return true if the object has a member named key.
T floor(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
std::optional< Seed > getSeedFromRPC(Json::Value const &params, Json::Value &error)
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition ErrorCodes.h:349
std::optional< Seed > parseRippleLibSeed(Json::Value const &value)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition KeyType.h:34
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:84
@ rpcBAD_SEED
Definition ErrorCodes.h:99
std::pair< PublicKey, SecretKey > generateKeyPair(KeyType type, Seed const &seed)
Generate a key pair deterministically.
Seed randomSeed()
Create a seed using secure random numbers.
Definition Seed.cpp:66
AccountID calcAccountID(PublicKey const &pk)
Json::Value rpcError(int iError)
Definition RPCErr.cpp:31
std::string seedAs1751(Seed const &seed)
Encode a Seed in RFC1751 format.
Definition Seed.cpp:135
std::string strHex(FwdIt begin, FwdIt end)
Definition strHex.h:30
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
Json::Value walletPropose(Json::Value const &params)
double estimate_entropy(std::string const &input)
Json::Value doWalletPropose(RPC::JsonContext &)
T length(T... args)
T value_or(T... args)