2013-11-08 00:24:47 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "bip39.h"
|
2013-11-25 21:46:54 +00:00
|
|
|
#include "hmac.h"
|
|
|
|
#include "rand.h"
|
2013-11-08 00:24:47 +00:00
|
|
|
#include "sha2.h"
|
2013-12-09 15:21:42 +00:00
|
|
|
#include "pbkdf2.h"
|
2013-11-08 00:24:47 +00:00
|
|
|
#include "bip39_english.h"
|
|
|
|
|
2014-01-10 19:22:33 +00:00
|
|
|
#define PBKDF2_ROUNDS 2048
|
2013-11-08 00:24:47 +00:00
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
const char *mnemonic_generate(int strength)
|
2013-11-08 00:24:47 +00:00
|
|
|
{
|
2013-11-25 21:46:54 +00:00
|
|
|
if (strength % 32 || strength < 128 || strength > 256) {
|
|
|
|
return 0;
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
2014-03-11 19:09:15 +00:00
|
|
|
int i;
|
|
|
|
static uint32_t data[16];
|
2013-11-25 21:46:54 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
data[i] = random32();
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
2013-11-25 21:46:54 +00:00
|
|
|
return mnemonic_from_data((const uint8_t *)data, strength / 8);
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
const char *mnemonic_from_data(const uint8_t *data, int len)
|
2013-11-08 00:24:47 +00:00
|
|
|
{
|
2013-11-26 00:29:06 +00:00
|
|
|
if (len % 4 || len < 16 || len > 32) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-03-11 19:09:15 +00:00
|
|
|
int i, j;
|
|
|
|
char bits[256 + 8];
|
2013-11-08 00:24:47 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
|
|
bits[8 * i + j] = (data[i] & (1 << (7 - j))) > 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-11 19:09:15 +00:00
|
|
|
uint8_t hash[32];
|
|
|
|
sha256_Raw((const uint8_t *)data, len, hash);
|
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
char hlen = len / 4;
|
|
|
|
for (i = 0; i < hlen; i++) {
|
|
|
|
char c = (hash[0] & (1 << (7 - i))) > 0;
|
|
|
|
bits[8 * len + i] = c;
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
int mlen = len * 3 / 4;
|
2014-03-11 19:09:15 +00:00
|
|
|
static char mnemo[24 * 10];
|
2013-11-25 21:46:54 +00:00
|
|
|
|
2013-11-08 00:24:47 +00:00
|
|
|
char *p = mnemo;
|
2013-11-25 21:46:54 +00:00
|
|
|
for (i = 0; i < mlen; i++) {
|
2013-11-08 00:24:47 +00:00
|
|
|
int idx = 0;
|
|
|
|
for (j = 0; j < 11; j++) {
|
|
|
|
idx += bits[i * 11 + j] << (10 - j);
|
|
|
|
}
|
|
|
|
strcpy(p, wordlist[idx]);
|
|
|
|
p += strlen(wordlist[idx]);
|
2013-11-25 21:46:54 +00:00
|
|
|
*p = (i < mlen - 1) ? ' ' : 0;
|
2013-11-08 00:24:47 +00:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mnemo;
|
|
|
|
}
|
|
|
|
|
2014-03-11 19:09:15 +00:00
|
|
|
int mnemonic_check(const char *mnemonic)
|
|
|
|
{
|
|
|
|
// TODO: add proper check
|
|
|
|
(void)mnemonic;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total))
|
2013-11-08 00:24:47 +00:00
|
|
|
{
|
2013-12-09 15:21:42 +00:00
|
|
|
static uint8_t salt[8 + 256 + 4];
|
|
|
|
int saltlen = strlen(passphrase);
|
|
|
|
memcpy(salt, "mnemonic", 8);
|
|
|
|
memcpy(salt + 8, passphrase, saltlen);
|
|
|
|
saltlen += 8;
|
2014-03-11 19:09:15 +00:00
|
|
|
pbkdf2((const uint8_t *)mnemonic, strlen(mnemonic), salt, saltlen, PBKDF2_ROUNDS, seed, 512 / 8, progress_callback);
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
2014-03-07 19:11:50 +00:00
|
|
|
|
|
|
|
const char **mnemonic_wordlist(void)
|
|
|
|
{
|
|
|
|
return wordlist;
|
|
|
|
}
|