PRCYCoin  2.0.0.7rc1
P2P Digital Currency
bip39.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2014 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "bip39.h"
6 #include "bip39_english.h"
7 #include "crypto/sha256.h"
8 #include "random.h"
9 
10 #include <openssl/evp.h>
11 
13 {
14  if (strength % 32 || strength < 128 || strength > 256) {
15  return SecureString();
16  }
17  SecureVector data(32);
18  GetRandBytes(&data[0], 32);
19  SecureString mnemonic = FromData(data, strength / 8);
20  return mnemonic;
21 }
22 
23 // SecureString CMnemonic::FromData(const uint8_t *data, int len)
25 {
26  if (len % 4 || len < 16 || len > 32) {
27  return SecureString();
28  }
29 
30  SecureVector checksum(32);
31  CSHA256().Write(&data[0], len).Finalize(&checksum[0]);
32 
33  // data
34  SecureVector bits(len);
35  memcpy(&bits[0], &data[0], len);
36  // checksum
37  bits.push_back(checksum[0]);
38 
39  int mlen = len * 3 / 4;
40  SecureString mnemonic;
41 
42  int i, j, idx;
43  for (i = 0; i < mlen; i++) {
44  idx = 0;
45  for (j = 0; j < 11; j++) {
46  idx <<= 1;
47  idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
48  }
49  mnemonic.append(wordlist[idx]);
50  if (i < mlen - 1) {
51  mnemonic += ' ';
52  }
53  }
54 
55  return mnemonic;
56 }
57 
59 {
60  if (mnemonic.empty()) {
61  return false;
62  }
63 
64  uint32_t nWordCount{};
65 
66  for (size_t i = 0; i < mnemonic.size(); ++i) {
67  if (mnemonic[i] == ' ') {
68  nWordCount++;
69  }
70  }
71  nWordCount++;
72  // check number of words
73  if (nWordCount != 12 && nWordCount != 18 && nWordCount != 24) {
74  return false;
75  }
76 
77  SecureString ssCurrentWord;
78  SecureVector bits(32 + 1);
79 
80  uint32_t nWordIndex, ki, nBitsCount{};
81 
82  for (size_t i = 0; i < mnemonic.size(); ++i)
83  {
84  ssCurrentWord = "";
85  while (i + ssCurrentWord.size() < mnemonic.size() && mnemonic[i + ssCurrentWord.size()] != ' ') {
86  if (ssCurrentWord.size() >= 9) {
87  return false;
88  }
89  ssCurrentWord += mnemonic[i + ssCurrentWord.size()];
90  }
91  i += ssCurrentWord.size();
92  nWordIndex = 0;
93  for (;;) {
94  if (!wordlist[nWordIndex]) { // word not found
95  return false;
96  }
97  if (ssCurrentWord == wordlist[nWordIndex]) { // word found on index nWordIndex
98  for (ki = 0; ki < 11; ki++) {
99  if (nWordIndex & (1 << (10 - ki))) {
100  bits[nBitsCount / 8] |= 1 << (7 - (nBitsCount % 8));
101  }
102  nBitsCount++;
103  }
104  break;
105  }
106  nWordIndex++;
107  }
108  }
109  if (nBitsCount != nWordCount * 11) {
110  return false;
111  }
112  bits[32] = bits[nWordCount * 4 / 3];
113  CSHA256().Write(&bits[0], nWordCount * 4 / 3).Finalize(&bits[0]);
114 
115  bool fResult = 0;
116  if (nWordCount == 12) {
117  fResult = (bits[0] & 0xF0) == (bits[32] & 0xF0); // compare first 4 bits
118  } else
119  if (nWordCount == 18) {
120  fResult = (bits[0] & 0xFC) == (bits[32] & 0xFC); // compare first 6 bits
121  } else
122  if (nWordCount == 24) {
123  fResult = bits[0] == bits[32]; // compare 8 bits
124  }
125 
126  return fResult;
127 }
128 
129 // passphrase must be at most 256 characters or code may crash
130 void CMnemonic::ToSeed(SecureString mnemonic, SecureString passphrase, SecureVector& seedRet)
131 {
132  SecureString ssSalt = SecureString("mnemonic") + passphrase;
133  SecureVector vchSalt(ssSalt.begin(), ssSalt.end());
134  seedRet.resize(64);
135  // int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
136  // const unsigned char *salt, int saltlen, int iter,
137  // const EVP_MD *digest,
138  // int keylen, unsigned char *out);
139  PKCS5_PBKDF2_HMAC(mnemonic.c_str(), mnemonic.size(), &vchSalt[0], vchSalt.size(), 2048, EVP_sha512(), 64, &seedRet[0]);
140 }
CSHA256::Write
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:141
CMnemonic::ToSeed
static void ToSeed(SecureString mnemonic, SecureString passphrase, SecureVector &seedRet)
Definition: bip39.cpp:130
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:15
wordlist
const char *const wordlist[]
Copyright (c) 2013-2014 Tomas Dzetkulic Copyright (c) 2013-2014 Pavol Rusnak.
Definition: bip39_english.h:24
random.h
GetRandBytes
void GetRandBytes(unsigned char *buf, int num)
Functions to gather random data via the OpenSSL PRNG.
Definition: random.cpp:273
CMnemonic::FromData
static SecureString FromData(const SecureVector &data, int len)
Definition: bip39.cpp:24
SecureString
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: allocators.h:262
bip39_english.h
CMnemonic::Generate
static SecureString Generate(int strength)
Definition: bip39.cpp:12
CMnemonic::Check
static bool Check(SecureString mnemonic)
Definition: bip39.cpp:58
CSHA256::Finalize
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:167
sha256.h
SecureVector
std::vector< unsigned char, secure_allocator< unsigned char > > SecureVector
Definition: allocators.h:267
CSHA256
A hasher class for SHA-256.
Definition: sha256.h:12
bip39.h