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#include <xrpl/basics/strHex.h>
24#include <xrpl/protocol/ErrorCodes.h>
25#include <xrpl/protocol/KeyType.h>
26#include <xrpl/protocol/PublicKey.h>
27#include <xrpl/protocol/RPCErr.h>
28#include <xrpl/protocol/SecretKey.h>
29#include <xrpl/protocol/Seed.h>
30#include <xrpl/protocol/jss.h>
31#include <cmath>
32#include <ed25519.h>
33#include <map>
34
35namespace ripple {
36
37double
39{
40 // First, we calculate the Shannon entropy. This gives
41 // the average number of bits per symbol that we would
42 // need to encode the input.
44
45 for (auto const& c : input)
46 freq[c]++;
47
48 double se = 0.0;
49
50 for (auto const& [_, f] : freq)
51 {
52 (void)_;
53 auto x = f / input.length();
54 se += (x)*log2(x);
55 }
56
57 // We multiply it by the length, to get an estimate of
58 // the number of bits in the input. We floor because it
59 // is better to be conservative.
60 return std::floor(-se * input.length());
61}
62
63// {
64// passphrase: <string>
65// }
68{
69 return walletPropose(context.params);
70}
71
74{
77 bool rippleLibSeed = false;
78
79 if (params.isMember(jss::key_type))
80 {
81 if (!params[jss::key_type].isString())
82 {
83 return RPC::expected_field_error(jss::key_type, "string");
84 }
85
86 keyType = keyTypeFromString(params[jss::key_type].asString());
87
88 if (!keyType)
90 }
91
92 // ripple-lib encodes seed used to generate an Ed25519 wallet in a
93 // non-standard way. While we never encode seeds that way, we try
94 // to detect such keys to avoid user confusion.
95 {
96 if (params.isMember(jss::passphrase))
97 seed = RPC::parseRippleLibSeed(params[jss::passphrase]);
98 else if (params.isMember(jss::seed))
99 seed = RPC::parseRippleLibSeed(params[jss::seed]);
100
101 if (seed)
102 {
103 rippleLibSeed = true;
104
105 // If the user *explicitly* requests a key type other than
106 // Ed25519 we return an error.
108 return rpcError(rpcBAD_SEED);
109
110 keyType = KeyType::ed25519;
111 }
112 }
113
114 if (!seed)
115 {
116 if (params.isMember(jss::passphrase) || params.isMember(jss::seed) ||
117 params.isMember(jss::seed_hex))
118 {
119 Json::Value err;
120
121 seed = RPC::getSeedFromRPC(params, err);
122
123 if (!seed)
124 return err;
125 }
126 else
127 {
128 seed = randomSeed();
129 }
130 }
131
132 if (!keyType)
133 keyType = KeyType::secp256k1;
134
135 auto const publicKey = generateKeyPair(*keyType, *seed).first;
136
138
139 auto const seed1751 = seedAs1751(*seed);
140 auto const seedHex = strHex(*seed);
141 auto const seedBase58 = toBase58(*seed);
142
143 obj[jss::master_seed] = seedBase58;
144 obj[jss::master_seed_hex] = seedHex;
145 obj[jss::master_key] = seed1751;
146 obj[jss::account_id] = toBase58(calcAccountID(publicKey));
147 obj[jss::public_key] = toBase58(TokenType::AccountPublic, publicKey);
148 obj[jss::key_type] = to_string(*keyType);
149 obj[jss::public_key_hex] = strHex(publicKey);
150
151 // If a passphrase was specified, and it was hashed and used as a seed
152 // run a quick entropy check and add an appropriate warning, because
153 // "brain wallets" can be easily attacked.
154 if (!rippleLibSeed && params.isMember(jss::passphrase))
155 {
156 auto const passphrase = params[jss::passphrase].asString();
157
158 if (passphrase != seed1751 && passphrase != seedBase58 &&
159 passphrase != seedHex)
160 {
161 // 80 bits of entropy isn't bad, but it's better to
162 // err on the side of caution and be conservative.
163 if (estimate_entropy(passphrase) < 80.0)
164 obj[jss::warning] =
165 "This wallet was generated using a user-supplied "
166 "passphrase that has low entropy and is vulnerable "
167 "to brute-force attacks.";
168 else
169 obj[jss::warning] =
170 "This wallet was generated using a user-supplied "
171 "passphrase. It may be vulnerable to brute-force "
172 "attacks.";
173 }
174 }
175
176 return obj;
177}
178
179} // namespace ripple
Represents a JSON value.
Definition: json_value.h:147
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:943
T floor(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
std::optional< Seed > getSeedFromRPC(Json::Value const &params, Json::Value &error)
Definition: RPCHelpers.cpp:737
Json::Value expected_field_error(std::string const &name, std::string const &type)
Definition: ErrorCodes.h:339
std::optional< Seed > parseRippleLibSeed(Json::Value const &value)
Definition: RPCHelpers.cpp:718
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::optional< KeyType > keyTypeFromString(std::string const &s)
Definition: KeyType.h:34
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:106
@ 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.
Definition: SecretKey.cpp:351
Seed randomSeed()
Create a seed using secure random numbers.
Definition: Seed.cpp:59
AccountID calcAccountID(PublicKey const &pk)
Definition: AccountID.cpp:160
Json::Value rpcError(int iError)
Definition: RPCErr.cpp:29
std::string seedAs1751(Seed const &seed)
Encode a Seed in RFC1751 format.
Definition: Seed.cpp:128
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:629
Json::Value walletPropose(Json::Value const &params)
double estimate_entropy(std::string const &input)
Json::Value doWalletPropose(RPC::JsonContext &)
T length(T... args)
Json::Value params
Definition: Context.h:64
T value_or(T... args)