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"
|
|
|
|
#include "bip39_english.h"
|
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
#define HMAC_ROUNDS 10000
|
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
|
|
|
{
|
|
|
|
int i;
|
2013-11-25 21:46:54 +00:00
|
|
|
static uint32_t data[16];
|
|
|
|
if (strength % 32 || strength < 128 || strength > 256) {
|
|
|
|
return 0;
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
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-25 21:46:54 +00:00
|
|
|
int i, j;
|
|
|
|
static uint8_t hash[32];
|
|
|
|
static char bits[256 + 8];
|
|
|
|
static char mnemo[24 * 10];
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-25 21:46:54 +00:00
|
|
|
SHA256_Raw((const uint8_t *)data, len, hash);
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-27 23:53:09 +00:00
|
|
|
void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8])
|
2013-11-08 00:24:47 +00:00
|
|
|
{
|
2013-11-25 21:46:54 +00:00
|
|
|
static uint8_t k[8 + 256];
|
|
|
|
int i, kl;
|
|
|
|
|
|
|
|
kl = strlen(passphrase);
|
|
|
|
memcpy(k, "mnemonic", 8);
|
|
|
|
memcpy(k + 8, passphrase, kl);
|
|
|
|
kl += 8;
|
|
|
|
|
2013-11-27 23:53:09 +00:00
|
|
|
hmac_sha512(k, kl, (const uint8_t *)mnemonic, strlen(mnemonic), seed);
|
2013-11-25 21:46:54 +00:00
|
|
|
for (i = 1; i < HMAC_ROUNDS; i++) {
|
2013-11-27 23:53:09 +00:00
|
|
|
hmac_sha512(k, kl, seed, 512 / 8, seed);
|
2013-11-08 00:24:47 +00:00
|
|
|
}
|
|
|
|
}
|