1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2013-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4
5
6 #include <libdevcore/Guards.h> // <boost/thread> conflicts with <thread>
7 #include "Common.h"
8 #include <secp256k1.h>
9 #include <secp256k1_ecdh.h>
10 #include <secp256k1_recovery.h>
11 #include <secp256k1_sha256.h>
12 #include <cryptopp/aes.h>
13 #include <cryptopp/pwdbased.h>
14 #include <cryptopp/sha.h>
15 #include <cryptopp/modes.h>
16 #include <libscrypt.h>
17 #include <libdevcore/SHA3.h>
18 #include <libdevcore/RLP.h>
19 #include "AES.h"
20 #include "CryptoPP.h"
21 #include "Exceptions.h"
22 using namespace std;
23 using namespace dev;
24 using namespace dev::crypto;
25
26 namespace
27 {
28
getCtx()29 secp256k1_context const* getCtx()
30 {
31 static std::unique_ptr<secp256k1_context, decltype(&secp256k1_context_destroy)> s_ctx{
32 secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY),
33 &secp256k1_context_destroy
34 };
35 return s_ctx.get();
36 }
37
38 template <std::size_t KeySize>
toPublicKey(Secret const & _secret,unsigned _flags,array<byte,KeySize> & o_serializedPubkey)39 bool toPublicKey(Secret const& _secret, unsigned _flags, array<byte, KeySize>& o_serializedPubkey)
40 {
41 auto* ctx = getCtx();
42 secp256k1_pubkey rawPubkey;
43 // Creation will fail if the secret key is invalid.
44 if (!secp256k1_ec_pubkey_create(ctx, &rawPubkey, _secret.data()))
45 return false;
46 size_t serializedPubkeySize = o_serializedPubkey.size();
47 secp256k1_ec_pubkey_serialize(
48 ctx, o_serializedPubkey.data(), &serializedPubkeySize, &rawPubkey, _flags);
49 assert(serializedPubkeySize == o_serializedPubkey.size());
50 return true;
51 }
52 }
53
isValid() const54 bool dev::SignatureStruct::isValid() const noexcept
55 {
56 static const h256 s_max{"0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"};
57 static const h256 s_zero;
58
59 return (v <= 1 && r > s_zero && s > s_zero && r < s_max && s < s_max);
60 }
61
toPublic(Secret const & _secret)62 Public dev::toPublic(Secret const& _secret)
63 {
64 std::array<byte, 65> serializedPubkey;
65 if (!toPublicKey(_secret, SECP256K1_EC_UNCOMPRESSED, serializedPubkey))
66 return {};
67
68 // Expect single byte header of value 0x04 -- uncompressed public key.
69 assert(serializedPubkey[0] == 0x04);
70
71 // Create the Public skipping the header.
72 return Public{&serializedPubkey[1], Public::ConstructFromPointer};
73 }
74
toPublic(PublicCompressed const & _publicCompressed)75 Public dev::toPublic(PublicCompressed const& _publicCompressed)
76 {
77 auto* ctx = getCtx();
78
79 secp256k1_pubkey rawPubkey;
80 if (!secp256k1_ec_pubkey_parse(
81 ctx, &rawPubkey, _publicCompressed.data(), PublicCompressed::size))
82 return {};
83
84 std::array<byte, 65> serializedPubkey;
85 auto serializedPubkeySize = serializedPubkey.size();
86 secp256k1_ec_pubkey_serialize(
87 ctx, serializedPubkey.data(), &serializedPubkeySize, &rawPubkey, SECP256K1_EC_UNCOMPRESSED);
88 assert(serializedPubkeySize == serializedPubkey.size());
89 // Expect single byte header of value 0x04 -- uncompressed public key.
90 assert(serializedPubkey[0] == 0x04);
91 // Create the Public skipping the header.
92 return Public{&serializedPubkey[1], Public::ConstructFromPointer};
93 }
94
toPublicCompressed(Secret const & _secret)95 PublicCompressed dev::toPublicCompressed(Secret const& _secret)
96 {
97 PublicCompressed serializedPubkey;
98 if (!toPublicKey(_secret, SECP256K1_EC_COMPRESSED, serializedPubkey.asArray()))
99 return {};
100
101 // Expect single byte header of value 0x02 or 0x03 -- compressed public key.
102 assert(serializedPubkey[0] == 0x02 || serializedPubkey[0] == 0x03);
103
104 return serializedPubkey;
105 }
106
toAddress(Public const & _public)107 Address dev::toAddress(Public const& _public)
108 {
109 return right160(sha3(_public.ref()));
110 }
111
toAddress(Secret const & _secret)112 Address dev::toAddress(Secret const& _secret)
113 {
114 return toAddress(toPublic(_secret));
115 }
116
toAddress(Address const & _from,u256 const & _nonce)117 Address dev::toAddress(Address const& _from, u256 const& _nonce)
118 {
119 return right160(sha3(rlpList(_from, _nonce)));
120 }
121
encrypt(Public const & _k,bytesConstRef _plain,bytes & o_cipher)122 void dev::encrypt(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
123 {
124 bytes io = _plain.toBytes();
125 Secp256k1PP::get()->encrypt(_k, io);
126 o_cipher = std::move(io);
127 }
128
decrypt(Secret const & _k,bytesConstRef _cipher,bytes & o_plaintext)129 bool dev::decrypt(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
130 {
131 bytes io = _cipher.toBytes();
132 Secp256k1PP::get()->decrypt(_k, io);
133 if (io.empty())
134 return false;
135 o_plaintext = std::move(io);
136 return true;
137 }
138
encryptECIES(Public const & _k,bytesConstRef _plain,bytes & o_cipher)139 void dev::encryptECIES(Public const& _k, bytesConstRef _plain, bytes& o_cipher)
140 {
141 encryptECIES(_k, bytesConstRef(), _plain, o_cipher);
142 }
143
encryptECIES(Public const & _k,bytesConstRef _sharedMacData,bytesConstRef _plain,bytes & o_cipher)144 void dev::encryptECIES(Public const& _k, bytesConstRef _sharedMacData, bytesConstRef _plain, bytes& o_cipher)
145 {
146 bytes io = _plain.toBytes();
147 Secp256k1PP::get()->encryptECIES(_k, _sharedMacData, io);
148 o_cipher = std::move(io);
149 }
150
decryptECIES(Secret const & _k,bytesConstRef _cipher,bytes & o_plaintext)151 bool dev::decryptECIES(Secret const& _k, bytesConstRef _cipher, bytes& o_plaintext)
152 {
153 return decryptECIES(_k, bytesConstRef(), _cipher, o_plaintext);
154 }
155
decryptECIES(Secret const & _k,bytesConstRef _sharedMacData,bytesConstRef _cipher,bytes & o_plaintext)156 bool dev::decryptECIES(Secret const& _k, bytesConstRef _sharedMacData, bytesConstRef _cipher, bytes& o_plaintext)
157 {
158 bytes io = _cipher.toBytes();
159 if (!Secp256k1PP::get()->decryptECIES(_k, _sharedMacData, io))
160 return false;
161 o_plaintext = std::move(io);
162 return true;
163 }
164
encryptSym(Secret const & _k,bytesConstRef _plain,bytes & o_cipher)165 void dev::encryptSym(Secret const& _k, bytesConstRef _plain, bytes& o_cipher)
166 {
167 // TODO: @alex @subtly do this properly.
168 encrypt(KeyPair(_k).pub(), _plain, o_cipher);
169 }
170
decryptSym(Secret const & _k,bytesConstRef _cipher,bytes & o_plain)171 bool dev::decryptSym(Secret const& _k, bytesConstRef _cipher, bytes& o_plain)
172 {
173 // TODO: @alex @subtly do this properly.
174 return decrypt(_k, _cipher, o_plain);
175 }
176
encryptSymNoAuth(SecureFixedHash<16> const & _k,bytesConstRef _plain)177 std::pair<bytes, h128> dev::encryptSymNoAuth(SecureFixedHash<16> const& _k, bytesConstRef _plain)
178 {
179 h128 iv(Nonce::get().makeInsecure());
180 return make_pair(encryptSymNoAuth(_k, iv, _plain), iv);
181 }
182
encryptAES128CTR(bytesConstRef _k,h128 const & _iv,bytesConstRef _plain)183 bytes dev::encryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _plain)
184 {
185 if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32)
186 return bytes();
187 CryptoPP::SecByteBlock key(_k.data(), _k.size());
188 try
189 {
190 CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption e;
191 e.SetKeyWithIV(key, key.size(), _iv.data());
192 bytes ret(_plain.size());
193 e.ProcessData(ret.data(), _plain.data(), _plain.size());
194 return ret;
195 }
196 catch (CryptoPP::Exception& _e)
197 {
198 cerr << _e.what() << endl;
199 return bytes();
200 }
201 }
202
decryptAES128CTR(bytesConstRef _k,h128 const & _iv,bytesConstRef _cipher)203 bytesSec dev::decryptAES128CTR(bytesConstRef _k, h128 const& _iv, bytesConstRef _cipher)
204 {
205 if (_k.size() != 16 && _k.size() != 24 && _k.size() != 32)
206 return bytesSec();
207 CryptoPP::SecByteBlock key(_k.data(), _k.size());
208 try
209 {
210 CryptoPP::CTR_Mode<CryptoPP::AES>::Decryption d;
211 d.SetKeyWithIV(key, key.size(), _iv.data());
212 bytesSec ret(_cipher.size());
213 d.ProcessData(ret.writable().data(), _cipher.data(), _cipher.size());
214 return ret;
215 }
216 catch (CryptoPP::Exception& _e)
217 {
218 cerr << _e.what() << endl;
219 return bytesSec();
220 }
221 }
222
recover(Signature const & _sig,h256 const & _message)223 Public dev::recover(Signature const& _sig, h256 const& _message)
224 {
225 int v = _sig[64];
226 if (v > 3)
227 return {};
228
229 auto* ctx = getCtx();
230 secp256k1_ecdsa_recoverable_signature rawSig;
231 if (!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rawSig, _sig.data(), v))
232 return {};
233
234 secp256k1_pubkey rawPubkey;
235 if (!secp256k1_ecdsa_recover(ctx, &rawPubkey, &rawSig, _message.data()))
236 return {};
237
238 std::array<byte, 65> serializedPubkey;
239 size_t serializedPubkeySize = serializedPubkey.size();
240 secp256k1_ec_pubkey_serialize(
241 ctx, serializedPubkey.data(), &serializedPubkeySize,
242 &rawPubkey, SECP256K1_EC_UNCOMPRESSED
243 );
244 assert(serializedPubkeySize == serializedPubkey.size());
245 // Expect single byte header of value 0x04 -- uncompressed public key.
246 assert(serializedPubkey[0] == 0x04);
247 // Create the Public skipping the header.
248 return Public{&serializedPubkey[1], Public::ConstructFromPointer};
249 }
250
251 static const u256 c_secp256k1n("115792089237316195423570985008687907852837564279074904382605163141518161494337");
252
sign(Secret const & _k,h256 const & _hash)253 Signature dev::sign(Secret const& _k, h256 const& _hash)
254 {
255 auto* ctx = getCtx();
256 secp256k1_ecdsa_recoverable_signature rawSig;
257 if (!secp256k1_ecdsa_sign_recoverable(ctx, &rawSig, _hash.data(), _k.data(), nullptr, nullptr))
258 return {};
259
260 Signature s;
261 int v = 0;
262 secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, s.data(), &v, &rawSig);
263
264 SignatureStruct& ss = *reinterpret_cast<SignatureStruct*>(&s);
265 ss.v = static_cast<byte>(v);
266 if (ss.s > c_secp256k1n / 2)
267 {
268 ss.v = static_cast<byte>(ss.v ^ 1);
269 ss.s = h256(c_secp256k1n - u256(ss.s));
270 }
271 assert(ss.s <= c_secp256k1n / 2);
272 return s;
273 }
274
verify(Public const & _p,Signature const & _s,h256 const & _hash)275 bool dev::verify(Public const& _p, Signature const& _s, h256 const& _hash)
276 {
277 // TODO: Verify w/o recovery (if faster).
278 if (!_p)
279 return false;
280 return _p == recover(_s, _hash);
281 }
282
verify(PublicCompressed const & _key,h512 const & _signature,h256 const & _hash)283 bool dev::verify(PublicCompressed const& _key, h512 const& _signature, h256 const& _hash)
284 {
285 auto* ctx = getCtx();
286
287 secp256k1_ecdsa_signature rawSig;
288 if (!secp256k1_ecdsa_signature_parse_compact(ctx, &rawSig, _signature.data()))
289 return false;
290
291 secp256k1_pubkey rawPubkey;
292 if (!secp256k1_ec_pubkey_parse(ctx, &rawPubkey, _key.data(), PublicCompressed::size))
293 return false; // Invalid public key.
294
295 return secp256k1_ecdsa_verify(ctx, &rawSig, _hash.data(), &rawPubkey);
296 }
297
pbkdf2(string const & _pass,bytes const & _salt,unsigned _iterations,unsigned _dkLen)298 bytesSec dev::pbkdf2(string const& _pass, bytes const& _salt, unsigned _iterations, unsigned _dkLen)
299 {
300 bytesSec ret(_dkLen);
301 if (CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA256>().DeriveKey(
302 ret.writable().data(),
303 _dkLen,
304 0,
305 reinterpret_cast<byte const*>(_pass.data()),
306 _pass.size(),
307 _salt.data(),
308 _salt.size(),
309 _iterations
310 ) != _iterations)
311 BOOST_THROW_EXCEPTION(CryptoException() << errinfo_comment("Key derivation failed."));
312 return ret;
313 }
314
scrypt(std::string const & _pass,bytes const & _salt,uint64_t _n,uint32_t _r,uint32_t _p,unsigned _dkLen)315 bytesSec dev::scrypt(std::string const& _pass, bytes const& _salt, uint64_t _n, uint32_t _r, uint32_t _p, unsigned _dkLen)
316 {
317 bytesSec ret(_dkLen);
318 if (libscrypt_scrypt(
319 reinterpret_cast<uint8_t const*>(_pass.data()),
320 _pass.size(),
321 _salt.data(),
322 _salt.size(),
323 _n,
324 _r,
325 _p,
326 ret.writable().data(),
327 _dkLen
328 ) != 0)
329 BOOST_THROW_EXCEPTION(CryptoException() << errinfo_comment("Key derivation failed."));
330 return ret;
331 }
332
KeyPair(Secret const & _sec)333 KeyPair::KeyPair(Secret const& _sec):
334 m_secret(_sec),
335 m_public(toPublic(_sec))
336 {
337 // Assign address only if the secret key is valid.
338 if (m_public)
339 m_address = toAddress(m_public);
340 }
341
create()342 KeyPair KeyPair::create()
343 {
344 while (true)
345 {
346 KeyPair keyPair(Secret::random());
347 if (keyPair.address())
348 return keyPair;
349 }
350 }
351
fromEncryptedSeed(bytesConstRef _seed,std::string const & _password)352 KeyPair KeyPair::fromEncryptedSeed(bytesConstRef _seed, std::string const& _password)
353 {
354 return KeyPair(Secret(sha3(aesDecrypt(_seed, _password))));
355 }
356
kdf(Secret const & _priv,h256 const & _hash)357 h256 crypto::kdf(Secret const& _priv, h256 const& _hash)
358 {
359 // H(H(r||k)^h)
360 h256 s;
361 sha3mac(Secret::random().ref(), _priv.ref(), s.ref());
362 s ^= _hash;
363 sha3(s.ref(), s.ref());
364
365 if (!s || !_hash || !_priv)
366 BOOST_THROW_EXCEPTION(InvalidState());
367 return s;
368 }
369
next()370 Secret Nonce::next()
371 {
372 Guard l(x_value);
373 if (!m_value)
374 {
375 m_value = Secret::random();
376 if (!m_value)
377 BOOST_THROW_EXCEPTION(InvalidState());
378 }
379 m_value = sha3Secure(m_value.ref());
380 return sha3(~m_value);
381 }
382
agree(Secret const & _s,Public const & _r,Secret & o_s)383 bool ecdh::agree(Secret const& _s, Public const& _r, Secret& o_s) noexcept
384 {
385 auto* ctx = getCtx();
386 static_assert(sizeof(Secret) == 32, "Invalid Secret type size");
387 secp256k1_pubkey rawPubkey;
388 std::array<byte, 65> serializedPubKey{{0x04}};
389 std::copy(_r.asArray().begin(), _r.asArray().end(), serializedPubKey.begin() + 1);
390 if (!secp256k1_ec_pubkey_parse(ctx, &rawPubkey, serializedPubKey.data(), serializedPubKey.size()))
391 return false; // Invalid public key.
392 // FIXME: We should verify the public key when constructed, maybe even keep
393 // secp256k1_pubkey as the internal data of Public.
394 std::array<byte, 33> compressedPoint;
395 #ifdef QTUM_BUILD
396 if (!secp256k1_ecdh(ctx, compressedPoint.data(), &rawPubkey, _s.data(), nullptr, nullptr))
397 #else
398 if (!secp256k1_ecdh_raw(ctx, compressedPoint.data(), &rawPubkey, _s.data()))
399 #endif
400 return false; // Invalid secret key.
401 std::copy(compressedPoint.begin() + 1, compressedPoint.end(), o_s.writable().data());
402 return true;
403 }
404
kdf(Secret const & _z,bytes const & _s1,unsigned kdByteLen)405 bytes ecies::kdf(Secret const& _z, bytes const& _s1, unsigned kdByteLen)
406 {
407 auto reps = ((kdByteLen + 7) * 8) / 512;
408 // SEC/ISO/Shoup specify counter size SHOULD be equivalent
409 // to size of hash output, however, it also notes that
410 // the 4 bytes is okay. NIST specifies 4 bytes.
411 std::array<byte, 4> ctr{{0, 0, 0, 1}};
412 bytes k;
413 secp256k1_sha256_t ctx;
414 for (unsigned i = 0; i <= reps; i++)
415 {
416 secp256k1_sha256_initialize(&ctx);
417 secp256k1_sha256_write(&ctx, ctr.data(), ctr.size());
418 secp256k1_sha256_write(&ctx, _z.data(), Secret::size);
419 secp256k1_sha256_write(&ctx, _s1.data(), _s1.size());
420 // append hash to k
421 std::array<byte, 32> digest;
422 secp256k1_sha256_finalize(&ctx, digest.data());
423
424 k.reserve(k.size() + h256::size);
425 move(digest.begin(), digest.end(), back_inserter(k));
426
427 if (++ctr[3] || ++ctr[2] || ++ctr[1] || ++ctr[0])
428 continue;
429 }
430
431 k.resize(kdByteLen);
432 return k;
433 }
434