mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-21 23:18:13 +00:00
format: start using clang-format with style=Google
This commit is contained in:
parent
8434b2468c
commit
0c622d62e1
2
.clang-format
Normal file
2
.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
102
address.c
102
address.c
@ -24,66 +24,68 @@
|
||||
#include "address.h"
|
||||
#include "bignum.h"
|
||||
|
||||
size_t address_prefix_bytes_len(uint32_t address_type)
|
||||
{
|
||||
if (address_type <= 0xFF) return 1;
|
||||
if (address_type <= 0xFFFF) return 2;
|
||||
if (address_type <= 0xFFFFFF) return 3;
|
||||
return 4;
|
||||
size_t address_prefix_bytes_len(uint32_t address_type) {
|
||||
if (address_type <= 0xFF) return 1;
|
||||
if (address_type <= 0xFFFF) return 2;
|
||||
if (address_type <= 0xFFFFFF) return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
void address_write_prefix_bytes(uint32_t address_type, uint8_t *out)
|
||||
{
|
||||
if (address_type > 0xFFFFFF) *(out++) = address_type >> 24;
|
||||
if (address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF;
|
||||
if (address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF;
|
||||
*(out++) = address_type & 0xFF;
|
||||
void address_write_prefix_bytes(uint32_t address_type, uint8_t *out) {
|
||||
if (address_type > 0xFFFFFF) *(out++) = address_type >> 24;
|
||||
if (address_type > 0xFFFF) *(out++) = (address_type >> 16) & 0xFF;
|
||||
if (address_type > 0xFF) *(out++) = (address_type >> 8) & 0xFF;
|
||||
*(out++) = address_type & 0xFF;
|
||||
}
|
||||
|
||||
bool address_check_prefix(const uint8_t *addr, uint32_t address_type)
|
||||
{
|
||||
if (address_type <= 0xFF) {
|
||||
return address_type == (uint32_t)(addr[0]);
|
||||
}
|
||||
if (address_type <= 0xFFFF) {
|
||||
return address_type == (((uint32_t) addr[0] << 8) | ((uint32_t) addr[1]));
|
||||
}
|
||||
if (address_type <= 0xFFFFFF) {
|
||||
return address_type == (((uint32_t) addr[0] << 16) | ((uint32_t) addr[1] << 8) | ((uint32_t) addr[2]));
|
||||
}
|
||||
return address_type == (((uint32_t) addr[0] << 24) | ((uint32_t) addr[1] << 16) | ((uint32_t) addr[2] << 8) | ((uint32_t) addr[3]));
|
||||
bool address_check_prefix(const uint8_t *addr, uint32_t address_type) {
|
||||
if (address_type <= 0xFF) {
|
||||
return address_type == (uint32_t)(addr[0]);
|
||||
}
|
||||
if (address_type <= 0xFFFF) {
|
||||
return address_type == (((uint32_t)addr[0] << 8) | ((uint32_t)addr[1]));
|
||||
}
|
||||
if (address_type <= 0xFFFFFF) {
|
||||
return address_type == (((uint32_t)addr[0] << 16) |
|
||||
((uint32_t)addr[1] << 8) | ((uint32_t)addr[2]));
|
||||
}
|
||||
return address_type ==
|
||||
(((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) |
|
||||
((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]));
|
||||
}
|
||||
|
||||
#if USE_ETHEREUM
|
||||
#include "sha3.h"
|
||||
|
||||
void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id)
|
||||
{
|
||||
const char *hex = "0123456789abcdef";
|
||||
for (int i = 0; i < 20; i++) {
|
||||
address[i * 2] = hex[(addr[i] >> 4) & 0xF];
|
||||
address[i * 2 + 1] = hex[addr[i] & 0xF];
|
||||
}
|
||||
address[40] = 0;
|
||||
void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60,
|
||||
uint32_t chain_id) {
|
||||
const char *hex = "0123456789abcdef";
|
||||
for (int i = 0; i < 20; i++) {
|
||||
address[i * 2] = hex[(addr[i] >> 4) & 0xF];
|
||||
address[i * 2 + 1] = hex[addr[i] & 0xF];
|
||||
}
|
||||
address[40] = 0;
|
||||
|
||||
SHA3_CTX ctx;
|
||||
uint8_t hash[32];
|
||||
keccak_256_Init(&ctx);
|
||||
if (rskip60) {
|
||||
char prefix[16];
|
||||
int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, prefix, sizeof(prefix));
|
||||
keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size);
|
||||
}
|
||||
keccak_Update(&ctx, (const uint8_t *)address, 40);
|
||||
keccak_Final(&ctx, hash);
|
||||
SHA3_CTX ctx;
|
||||
uint8_t hash[32];
|
||||
keccak_256_Init(&ctx);
|
||||
if (rskip60) {
|
||||
char prefix[16];
|
||||
int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false,
|
||||
prefix, sizeof(prefix));
|
||||
keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size);
|
||||
}
|
||||
keccak_Update(&ctx, (const uint8_t *)address, 40);
|
||||
keccak_Final(&ctx, hash);
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (hash[i] & 0x80 && address[i * 2 ] >= 'a' && address[i * 2 ] <= 'f') {
|
||||
address[i * 2] -= 0x20;
|
||||
}
|
||||
if (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' && address[i * 2 + 1] <= 'f') {
|
||||
address[i * 2 + 1] -= 0x20;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (hash[i] & 0x80 && address[i * 2] >= 'a' && address[i * 2] <= 'f') {
|
||||
address[i * 2] -= 0x20;
|
||||
}
|
||||
if (hash[i] & 0x08 && address[i * 2 + 1] >= 'a' &&
|
||||
address[i * 2 + 1] <= 'f') {
|
||||
address[i * 2 + 1] -= 0x20;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -24,16 +24,17 @@
|
||||
#ifndef __ADDRESS_H__
|
||||
#define __ADDRESS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
|
||||
size_t address_prefix_bytes_len(uint32_t address_type);
|
||||
void address_write_prefix_bytes(uint32_t address_type, uint8_t *out);
|
||||
bool address_check_prefix(const uint8_t *addr, uint32_t address_type);
|
||||
#if USE_ETHEREUM
|
||||
void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint32_t chain_id);
|
||||
void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60,
|
||||
uint32_t chain_id);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
293
base32.c
293
base32.c
@ -27,207 +27,214 @@
|
||||
const char *BASE32_ALPHABET_RFC4648 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789";
|
||||
|
||||
static inline void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out);
|
||||
static inline bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet);
|
||||
static inline void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out);
|
||||
static inline bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out,
|
||||
const char *alphabet);
|
||||
static inline void base32_8to5_raw(const uint8_t *in, uint8_t length,
|
||||
uint8_t *out);
|
||||
|
||||
static inline int base32_encode_character(uint8_t decoded, const char *alphabet);
|
||||
static inline int base32_encode_character(uint8_t decoded,
|
||||
const char *alphabet);
|
||||
static inline int base32_decode_character(char encoded, const char *alphabet);
|
||||
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet) {
|
||||
size_t length = base32_encoded_length(inlen);
|
||||
if (outlen <= length) {
|
||||
return NULL;
|
||||
}
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen,
|
||||
const char *alphabet) {
|
||||
size_t length = base32_encoded_length(inlen);
|
||||
if (outlen <= length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
base32_encode_unsafe(in, inlen, (uint8_t *) out);
|
||||
base32_encode_unsafe(in, inlen, (uint8_t *)out);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_encode_character(out[i], alphabet);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_encode_character(out[i], alphabet);
|
||||
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
out[i] = ret;
|
||||
}
|
||||
}
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
out[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
out[length] = '\0';
|
||||
return &out[length];
|
||||
out[length] = '\0';
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet) {
|
||||
size_t length = base32_decoded_length(inlen);
|
||||
if (outlen < length) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out,
|
||||
size_t outlen, const char *alphabet) {
|
||||
size_t length = base32_decoded_length(inlen);
|
||||
if (outlen < length) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!base32_decode_unsafe((uint8_t *) in, inlen, (uint8_t *) out, alphabet)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!base32_decode_unsafe((uint8_t *)in, inlen, (uint8_t *)out, alphabet)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &out[length];
|
||||
return &out[length];
|
||||
}
|
||||
|
||||
void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
size_t limit = inlen - remainder;
|
||||
uint8_t remainder = inlen % 5;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 5, j += 8) {
|
||||
base32_5to8(&in[i], 5, &out[j]);
|
||||
}
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 5, j += 8) {
|
||||
base32_5to8(&in[i], 5, &out[j]);
|
||||
}
|
||||
|
||||
if (remainder) base32_5to8(&in[i], remainder, &out[j]);
|
||||
if (remainder) base32_5to8(&in[i], remainder, &out[j]);
|
||||
}
|
||||
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
size_t limit = inlen - remainder;
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out,
|
||||
const char *alphabet) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
size_t limit = inlen - remainder;
|
||||
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 8, j += 5) {
|
||||
if (!base32_8to5(&in[i], 8, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
size_t i, j;
|
||||
for (i = 0, j = 0; i < limit; i += 8, j += 5) {
|
||||
if (!base32_8to5(&in[i], 8, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
if (remainder && !base32_8to5(&in[i], remainder, &out[j], alphabet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t base32_encoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 5;
|
||||
uint8_t remainder = inlen % 5;
|
||||
|
||||
return (inlen / 5) * 8 + (remainder * 8 + 4) / 5;
|
||||
return (inlen / 5) * 8 + (remainder * 8 + 4) / 5;
|
||||
}
|
||||
|
||||
size_t base32_decoded_length(size_t inlen) {
|
||||
uint8_t remainder = inlen % 8;
|
||||
uint8_t remainder = inlen % 8;
|
||||
|
||||
return (inlen / 8) * 5 + (remainder * 5) / 8;
|
||||
return (inlen / 8) * 5 + (remainder * 5) / 8;
|
||||
}
|
||||
|
||||
void base32_5to8(const uint8_t *in, uint8_t length, uint8_t *out) {
|
||||
if (length >= 1) {
|
||||
out[0] = (in[0] >> 3);
|
||||
out[1] = (in[0] & 7) << 2;
|
||||
}
|
||||
if (length >= 1) {
|
||||
out[0] = (in[0] >> 3);
|
||||
out[1] = (in[0] & 7) << 2;
|
||||
}
|
||||
|
||||
if (length >= 2) {
|
||||
out[1] |= (in[1] >> 6);
|
||||
out[2] = (in[1] >> 1) & 31;
|
||||
out[3] = (in[1] & 1) << 4;
|
||||
}
|
||||
if (length >= 2) {
|
||||
out[1] |= (in[1] >> 6);
|
||||
out[2] = (in[1] >> 1) & 31;
|
||||
out[3] = (in[1] & 1) << 4;
|
||||
}
|
||||
|
||||
if (length >= 3) {
|
||||
out[3] |= (in[2] >> 4);
|
||||
out[4] = (in[2] & 15) << 1;
|
||||
}
|
||||
if (length >= 3) {
|
||||
out[3] |= (in[2] >> 4);
|
||||
out[4] = (in[2] & 15) << 1;
|
||||
}
|
||||
|
||||
if (length >= 4) {
|
||||
out[4] |= (in[3] >> 7);
|
||||
out[5] = (in[3] >> 2) & 31;
|
||||
out[6] = (in[3] & 3) << 3;
|
||||
}
|
||||
if (length >= 4) {
|
||||
out[4] |= (in[3] >> 7);
|
||||
out[5] = (in[3] >> 2) & 31;
|
||||
out[6] = (in[3] & 3) << 3;
|
||||
}
|
||||
|
||||
if (length >= 5) {
|
||||
out[6] |= (in[4] >> 5);
|
||||
out[7] = (in[4] & 31);
|
||||
}
|
||||
if (length >= 5) {
|
||||
out[6] |= (in[4] >> 5);
|
||||
out[7] = (in[4] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out, const char *alphabet) {
|
||||
if (length == 1 || length == 3 || length == 6 || length > 8) {
|
||||
return false;
|
||||
}
|
||||
bool base32_8to5(const uint8_t *in, uint8_t length, uint8_t *out,
|
||||
const char *alphabet) {
|
||||
if (length == 1 || length == 3 || length == 6 || length > 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alphabet) {
|
||||
uint8_t decoded[length];
|
||||
if (alphabet) {
|
||||
uint8_t decoded[length];
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_decode_character(in[i], alphabet);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
int ret = base32_decode_character(in[i], alphabet);
|
||||
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
decoded[i] = ret;
|
||||
}
|
||||
}
|
||||
if (ret == -1) {
|
||||
return false;
|
||||
} else {
|
||||
decoded[i] = ret;
|
||||
}
|
||||
}
|
||||
|
||||
base32_8to5_raw(decoded, length, out);
|
||||
} else {
|
||||
base32_8to5_raw(in, length, out);
|
||||
}
|
||||
base32_8to5_raw(decoded, length, out);
|
||||
} else {
|
||||
base32_8to5_raw(in, length, out);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void base32_8to5_raw(const uint8_t *in, uint8_t length, uint8_t *out) {
|
||||
if (length >= 2) {
|
||||
out[0] = (in[0] << 3);
|
||||
out[0] |= (in[1] >> 2);
|
||||
}
|
||||
if (length >= 2) {
|
||||
out[0] = (in[0] << 3);
|
||||
out[0] |= (in[1] >> 2);
|
||||
}
|
||||
|
||||
if (length >= 4) {
|
||||
out[1] = (in[1] & 3) << 6;
|
||||
out[1] |= (in[2] << 1);
|
||||
out[1] |= (in[3] >> 4);
|
||||
}
|
||||
if (length >= 4) {
|
||||
out[1] = (in[1] & 3) << 6;
|
||||
out[1] |= (in[2] << 1);
|
||||
out[1] |= (in[3] >> 4);
|
||||
}
|
||||
|
||||
if (length >= 5) {
|
||||
out[2] = (in[3] & 15) << 4;
|
||||
out[2] |= (in[4] >> 1);
|
||||
}
|
||||
if (length >= 5) {
|
||||
out[2] = (in[3] & 15) << 4;
|
||||
out[2] |= (in[4] >> 1);
|
||||
}
|
||||
|
||||
if (length >= 7) {
|
||||
out[3] = (in[4] & 1) << 7;
|
||||
out[3] |= (in[5] << 2);
|
||||
out[3] |= (in[6] >> 3);
|
||||
}
|
||||
if (length >= 7) {
|
||||
out[3] = (in[4] & 1) << 7;
|
||||
out[3] |= (in[5] << 2);
|
||||
out[3] |= (in[6] >> 3);
|
||||
}
|
||||
|
||||
if (length >= 8) {
|
||||
out[4] = (in[6] & 7) << 5;
|
||||
out[4] |= (in[7] & 31);
|
||||
}
|
||||
if (length >= 8) {
|
||||
out[4] = (in[6] & 7) << 5;
|
||||
out[4] |= (in[7] & 31);
|
||||
}
|
||||
}
|
||||
|
||||
int base32_encode_character(uint8_t decoded, const char *alphabet) {
|
||||
if (decoded >> 5) {
|
||||
return -1;
|
||||
}
|
||||
if (decoded >> 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (decoded < 26) {
|
||||
return 'A' + decoded;
|
||||
} else {
|
||||
return '2' - 26 + decoded;
|
||||
}
|
||||
}
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (decoded < 26) {
|
||||
return 'A' + decoded;
|
||||
} else {
|
||||
return '2' - 26 + decoded;
|
||||
}
|
||||
}
|
||||
|
||||
return alphabet[decoded];
|
||||
return alphabet[decoded];
|
||||
}
|
||||
|
||||
int base32_decode_character(char encoded, const char *alphabet) {
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (encoded >= 'A' && encoded <= 'Z') {
|
||||
return encoded - 'A';
|
||||
} else if (encoded >= 'a' && encoded <= 'z') {
|
||||
return encoded - 'a';
|
||||
} else if (encoded >= '2' && encoded <= '7') {
|
||||
return encoded - '2' + 26;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (alphabet == BASE32_ALPHABET_RFC4648) {
|
||||
if (encoded >= 'A' && encoded <= 'Z') {
|
||||
return encoded - 'A';
|
||||
} else if (encoded >= 'a' && encoded <= 'z') {
|
||||
return encoded - 'a';
|
||||
} else if (encoded >= '2' && encoded <= '7') {
|
||||
return encoded - '2' + 26;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char *occurrence = strchr(alphabet, encoded);
|
||||
const char *occurrence = strchr(alphabet, encoded);
|
||||
|
||||
if (occurrence) {
|
||||
return occurrence - alphabet;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (occurrence) {
|
||||
return occurrence - alphabet;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
9
base32.h
9
base32.h
@ -29,11 +29,14 @@
|
||||
|
||||
extern const char *BASE32_ALPHABET_RFC4648;
|
||||
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen, const char *alphabet);
|
||||
char *base32_encode(const uint8_t *in, size_t inlen, char *out, size_t outlen,
|
||||
const char *alphabet);
|
||||
void base32_encode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out);
|
||||
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out, size_t outlen, const char *alphabet);
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out, const char *alphabet);
|
||||
uint8_t *base32_decode(const char *in, size_t inlen, uint8_t *out,
|
||||
size_t outlen, const char *alphabet);
|
||||
bool base32_decode_unsafe(const uint8_t *in, size_t inlen, uint8_t *out,
|
||||
const char *alphabet);
|
||||
|
||||
size_t base32_encoded_length(size_t inlen);
|
||||
size_t base32_decoded_length(size_t inlen);
|
||||
|
419
base58.c
419
base58.c
@ -21,265 +21,248 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include "base58.h"
|
||||
#include "sha2.h"
|
||||
#include "ripemd160.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include "memzero.h"
|
||||
#include "ripemd160.h"
|
||||
#include "sha2.h"
|
||||
|
||||
const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
const char b58digits_ordered[] =
|
||||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
const int8_t b58digits_map[] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
|
||||
-1, 9,10,11,12,13,14,15,16,-1,17,18,19,20,21,-1,
|
||||
22,23,24,25,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,
|
||||
-1,33,34,35,36,37,38,39,40,41,42,43,-1,44,45,46,
|
||||
47,48,49,50,51,52,53,54,55,56,57,-1,-1,-1,-1,-1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, -1, -1, -1, -1, -1, -1, -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18,
|
||||
19, 20, 21, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1,
|
||||
-1, -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, 48,
|
||||
49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1,
|
||||
};
|
||||
|
||||
bool b58tobin(void *bin, size_t *binszp, const char *b58)
|
||||
{
|
||||
size_t binsz = *binszp;
|
||||
bool b58tobin(void *bin, size_t *binszp, const char *b58) {
|
||||
size_t binsz = *binszp;
|
||||
|
||||
if (binsz == 0) {
|
||||
return false;
|
||||
}
|
||||
if (binsz == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unsigned char *b58u = (const unsigned char*)b58;
|
||||
unsigned char *binu = bin;
|
||||
size_t outisz = (binsz + 3) / 4;
|
||||
uint32_t outi[outisz];
|
||||
uint64_t t;
|
||||
uint32_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
size_t b58sz;
|
||||
const unsigned char *b58u = (const unsigned char *)b58;
|
||||
unsigned char *binu = bin;
|
||||
size_t outisz = (binsz + 3) / 4;
|
||||
uint32_t outi[outisz];
|
||||
uint64_t t;
|
||||
uint32_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
size_t b58sz;
|
||||
|
||||
b58sz = strlen(b58);
|
||||
b58sz = strlen(b58);
|
||||
|
||||
memzero(outi, sizeof(outi));
|
||||
memzero(outi, sizeof(outi));
|
||||
|
||||
// Leading zeros, just count
|
||||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
|
||||
++zerocount;
|
||||
// Leading zeros, just count
|
||||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i) ++zerocount;
|
||||
|
||||
for ( ; i < b58sz; ++i)
|
||||
{
|
||||
if (b58u[i] & 0x80)
|
||||
// High-bit set on invalid digit
|
||||
return false;
|
||||
if (b58digits_map[b58u[i]] == -1)
|
||||
// Invalid base58 digit
|
||||
return false;
|
||||
c = (unsigned)b58digits_map[b58u[i]];
|
||||
for (j = outisz; j--; )
|
||||
{
|
||||
t = ((uint64_t)outi[j]) * 58 + c;
|
||||
c = (t & 0x3f00000000) >> 32;
|
||||
outi[j] = t & 0xffffffff;
|
||||
}
|
||||
if (c)
|
||||
// Output number too big (carry to the next int32)
|
||||
return false;
|
||||
if (outi[0] & zeromask)
|
||||
// Output number too big (last int32 filled too far)
|
||||
return false;
|
||||
}
|
||||
for (; i < b58sz; ++i) {
|
||||
if (b58u[i] & 0x80)
|
||||
// High-bit set on invalid digit
|
||||
return false;
|
||||
if (b58digits_map[b58u[i]] == -1)
|
||||
// Invalid base58 digit
|
||||
return false;
|
||||
c = (unsigned)b58digits_map[b58u[i]];
|
||||
for (j = outisz; j--;) {
|
||||
t = ((uint64_t)outi[j]) * 58 + c;
|
||||
c = (t & 0x3f00000000) >> 32;
|
||||
outi[j] = t & 0xffffffff;
|
||||
}
|
||||
if (c)
|
||||
// Output number too big (carry to the next int32)
|
||||
return false;
|
||||
if (outi[0] & zeromask)
|
||||
// Output number too big (last int32 filled too far)
|
||||
return false;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
switch (bytesleft) {
|
||||
case 3:
|
||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
||||
//-fallthrough
|
||||
case 2:
|
||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
||||
//-fallthrough
|
||||
case 1:
|
||||
*(binu++) = (outi[0] & 0xff);
|
||||
++j;
|
||||
//-fallthrough
|
||||
default:
|
||||
break;
|
||||
}
|
||||
j = 0;
|
||||
switch (bytesleft) {
|
||||
case 3:
|
||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
||||
//-fallthrough
|
||||
case 2:
|
||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
||||
//-fallthrough
|
||||
case 1:
|
||||
*(binu++) = (outi[0] & 0xff);
|
||||
++j;
|
||||
//-fallthrough
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (; j < outisz; ++j)
|
||||
{
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
}
|
||||
for (; j < outisz; ++j) {
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
}
|
||||
|
||||
// Count canonical base58 byte count
|
||||
binu = bin;
|
||||
for (i = 0; i < binsz; ++i)
|
||||
{
|
||||
if (binu[i]) {
|
||||
if (zerocount > i) {
|
||||
/* result too large */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
--*binszp;
|
||||
}
|
||||
*binszp += zerocount;
|
||||
// Count canonical base58 byte count
|
||||
binu = bin;
|
||||
for (i = 0; i < binsz; ++i) {
|
||||
if (binu[i]) {
|
||||
if (zerocount > i) {
|
||||
/* result too large */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
--*binszp;
|
||||
}
|
||||
*binszp += zerocount;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4)
|
||||
return -4;
|
||||
hasher_Raw(hasher_type, bin, binsz - 4, buf);
|
||||
if (memcmp(&binc[binsz - 4], buf, 4))
|
||||
return -1;
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type,
|
||||
const char *base58str) {
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4) return -4;
|
||||
hasher_Raw(hasher_type, bin, binsz - 4, buf);
|
||||
if (memcmp(&binc[binsz - 4], buf, 4)) return -1;
|
||||
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
|
||||
{} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1')
|
||||
return -3;
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid
|
||||
// possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) {
|
||||
} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1') return -3;
|
||||
|
||||
return binc[0];
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
|
||||
{
|
||||
const uint8_t *bin = data;
|
||||
int carry;
|
||||
ssize_t i, j, high, zcount = 0;
|
||||
size_t size;
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) {
|
||||
const uint8_t *bin = data;
|
||||
int carry;
|
||||
ssize_t i, j, high, zcount = 0;
|
||||
size_t size;
|
||||
|
||||
while (zcount < (ssize_t)binsz && !bin[zcount])
|
||||
++zcount;
|
||||
while (zcount < (ssize_t)binsz && !bin[zcount]) ++zcount;
|
||||
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t buf[size];
|
||||
memzero(buf, size);
|
||||
size = (binsz - zcount) * 138 / 100 + 1;
|
||||
uint8_t buf[size];
|
||||
memzero(buf, size);
|
||||
|
||||
for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j)
|
||||
{
|
||||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
|
||||
{
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
}
|
||||
for (i = zcount, high = size - 1; i < (ssize_t)binsz; ++i, high = j) {
|
||||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j) {
|
||||
carry += 256 * buf[j];
|
||||
buf[j] = carry % 58;
|
||||
carry /= 58;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < (ssize_t)size && !buf[j]; ++j);
|
||||
for (j = 0; j < (ssize_t)size && !buf[j]; ++j)
|
||||
;
|
||||
|
||||
if (*b58sz <= zcount + size - j)
|
||||
{
|
||||
*b58sz = zcount + size - j + 1;
|
||||
return false;
|
||||
}
|
||||
if (*b58sz <= zcount + size - j) {
|
||||
*b58sz = zcount + size - j + 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zcount)
|
||||
memset(b58, '1', zcount);
|
||||
for (i = zcount; j < (ssize_t)size; ++i, ++j)
|
||||
b58[i] = b58digits_ordered[buf[j]];
|
||||
b58[i] = '\0';
|
||||
*b58sz = i + 1;
|
||||
if (zcount) memset(b58, '1', zcount);
|
||||
for (i = zcount; j < (ssize_t)size; ++i, ++j)
|
||||
b58[i] = b58digits_ordered[buf[j]];
|
||||
b58[i] = '\0';
|
||||
*b58sz = i + 1;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int base58_encode_check(const uint8_t *data, int datalen, HasherType hasher_type, char *str, int strsize)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
hasher_Raw(hasher_type, data, datalen, hash);
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
int base58_encode_check(const uint8_t *data, int datalen,
|
||||
HasherType hasher_type, char *str, int strsize) {
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
hasher_Raw(hasher_type, data, datalen, hash);
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
}
|
||||
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58check(nd, res, hasher_type, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data,
|
||||
int datalen) {
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58check(nd, res, hasher_type, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
}
|
||||
|
||||
#if USE_GRAPHENE
|
||||
int b58gphcheck(const void *bin, size_t binsz, const char *base58str)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4)
|
||||
return -4;
|
||||
ripemd160(bin, binsz - 4, buf); // No double SHA256, but a single RIPEMD160
|
||||
if (memcmp(&binc[binsz - 4], buf, 4))
|
||||
return -1;
|
||||
int b58gphcheck(const void *bin, size_t binsz, const char *base58str) {
|
||||
unsigned char buf[32];
|
||||
const uint8_t *binc = bin;
|
||||
unsigned i;
|
||||
if (binsz < 4) return -4;
|
||||
ripemd160(bin, binsz - 4, buf); // No double SHA256, but a single RIPEMD160
|
||||
if (memcmp(&binc[binsz - 4], buf, 4)) return -1;
|
||||
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i)
|
||||
{} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1')
|
||||
return -3;
|
||||
// Check number of zeros is correct AFTER verifying checksum (to avoid
|
||||
// possibility of accessing base58str beyond the end)
|
||||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) {
|
||||
} // Just finding the end of zeros, nothing to do in loop
|
||||
if (binc[i] == '\0' || base58str[i] == '1') return -3;
|
||||
|
||||
return binc[0];
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
ripemd160(data, datalen, hash); // No double SHA256, but a single RIPEMD160
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str,
|
||||
int strsize) {
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t buf[datalen + 32];
|
||||
uint8_t *hash = buf + datalen;
|
||||
memcpy(buf, data, datalen);
|
||||
ripemd160(data, datalen, hash); // No double SHA256, but a single RIPEMD160
|
||||
size_t res = strsize;
|
||||
bool success = b58enc(str, &res, buf, datalen + 4);
|
||||
memzero(buf, sizeof(buf));
|
||||
return success ? res : 0;
|
||||
}
|
||||
|
||||
int base58gph_decode_check(const char *str, uint8_t *data, int datalen)
|
||||
{
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58gphcheck(nd, res, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
int base58gph_decode_check(const char *str, uint8_t *data, int datalen) {
|
||||
if (datalen > 128) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t d[datalen + 4];
|
||||
size_t res = datalen + 4;
|
||||
if (b58tobin(d, &res, str) != true) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t *nd = d + datalen + 4 - res;
|
||||
if (b58gphcheck(nd, res, str) < 0) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(data, nd, res - 4);
|
||||
return res - 4;
|
||||
}
|
||||
#endif
|
||||
|
14
base58.h
14
base58.h
@ -24,24 +24,28 @@
|
||||
#ifndef __BASE58_H__
|
||||
#define __BASE58_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
extern const char b58digits_ordered[];
|
||||
extern const int8_t b58digits_map[];
|
||||
|
||||
int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize);
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen);
|
||||
int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type,
|
||||
char *str, int strsize);
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data,
|
||||
int datalen);
|
||||
|
||||
// Private
|
||||
bool b58tobin(void *bin, size_t *binszp, const char *b58);
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *base58str);
|
||||
int b58check(const void *bin, size_t binsz, HasherType hasher_type,
|
||||
const char *base58str);
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz);
|
||||
|
||||
#if USE_GRAPHENE
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str, int strsize);
|
||||
int base58gph_encode_check(const uint8_t *data, int datalen, char *str,
|
||||
int strsize);
|
||||
int base58gph_decode_check(const char *str, uint8_t *data, int datalen);
|
||||
int b58gphcheck(const void *bin, size_t binsz, const char *base58str);
|
||||
#endif
|
||||
|
57
bignum.h
57
bignum.h
@ -33,7 +33,7 @@
|
||||
// bignum256 are 256 bits stored as 8*30 bit + 1*16 bit
|
||||
// val[0] are lowest 30 bits, val[8] highest 16 bits
|
||||
typedef struct {
|
||||
uint32_t val[9];
|
||||
uint32_t val[9];
|
||||
} bignum256;
|
||||
|
||||
// read 4 big endian bytes into uint32
|
||||
@ -60,26 +60,22 @@ void bn_read_uint32(uint32_t in_number, bignum256 *out_number);
|
||||
|
||||
void bn_read_uint64(uint64_t in_number, bignum256 *out_number);
|
||||
|
||||
static inline uint32_t bn_write_uint32(const bignum256 *in_number)
|
||||
{
|
||||
return in_number->val[0] | (in_number->val[1] << 30);
|
||||
static inline uint32_t bn_write_uint32(const bignum256 *in_number) {
|
||||
return in_number->val[0] | (in_number->val[1] << 30);
|
||||
}
|
||||
|
||||
static inline uint64_t bn_write_uint64(const bignum256 *in_number)
|
||||
{
|
||||
uint64_t tmp;
|
||||
tmp = in_number->val[2];
|
||||
tmp <<= 30;
|
||||
tmp |= in_number->val[1];
|
||||
tmp <<= 30;
|
||||
tmp |= in_number->val[0];
|
||||
return tmp;
|
||||
static inline uint64_t bn_write_uint64(const bignum256 *in_number) {
|
||||
uint64_t tmp;
|
||||
tmp = in_number->val[2];
|
||||
tmp <<= 30;
|
||||
tmp |= in_number->val[1];
|
||||
tmp <<= 30;
|
||||
tmp |= in_number->val[0];
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// copies number a to b
|
||||
static inline void bn_copy(const bignum256 *a, bignum256 *b) {
|
||||
*b = *a;
|
||||
}
|
||||
static inline void bn_copy(const bignum256 *a, bignum256 *b) { *b = *a; }
|
||||
|
||||
int bn_bitcount(const bignum256 *a);
|
||||
|
||||
@ -92,18 +88,17 @@ int bn_is_zero(const bignum256 *a);
|
||||
void bn_one(bignum256 *a);
|
||||
|
||||
static inline int bn_is_even(const bignum256 *a) {
|
||||
return (a->val[0] & 1) == 0;
|
||||
return (a->val[0] & 1) == 0;
|
||||
}
|
||||
|
||||
static inline int bn_is_odd(const bignum256 *a) {
|
||||
return (a->val[0] & 1) == 1;
|
||||
}
|
||||
static inline int bn_is_odd(const bignum256 *a) { return (a->val[0] & 1) == 1; }
|
||||
|
||||
int bn_is_less(const bignum256 *a, const bignum256 *b);
|
||||
|
||||
int bn_is_equal(const bignum256 *a, const bignum256 *b);
|
||||
|
||||
void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase, const bignum256 *falsecase);
|
||||
void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase,
|
||||
const bignum256 *falsecase);
|
||||
|
||||
void bn_lshift(bignum256 *a);
|
||||
|
||||
@ -141,7 +136,8 @@ void bn_addi(bignum256 *a, uint32_t b);
|
||||
|
||||
void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime);
|
||||
|
||||
void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res, const bignum256 *prime);
|
||||
void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res,
|
||||
const bignum256 *prime);
|
||||
|
||||
void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res);
|
||||
|
||||
@ -149,14 +145,19 @@ void bn_divmod58(bignum256 *a, uint32_t *r);
|
||||
|
||||
void bn_divmod1000(bignum256 *a, uint32_t *r);
|
||||
|
||||
size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen);
|
||||
size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix,
|
||||
unsigned int decimals, int exponent, bool trailing, char *out,
|
||||
size_t outlen);
|
||||
|
||||
static inline size_t bn_format_uint64(uint64_t amount, const char *prefix, const char *suffix, unsigned int decimals, int exponent, bool trailing, char *out, size_t outlen)
|
||||
{
|
||||
bignum256 amnt;
|
||||
bn_read_uint64(amount, &amnt);
|
||||
static inline size_t bn_format_uint64(uint64_t amount, const char *prefix,
|
||||
const char *suffix, unsigned int decimals,
|
||||
int exponent, bool trailing, char *out,
|
||||
size_t outlen) {
|
||||
bignum256 amnt;
|
||||
bn_read_uint64(amount, &amnt);
|
||||
|
||||
return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out, outlen);
|
||||
return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out,
|
||||
outlen);
|
||||
}
|
||||
|
||||
#if USE_BN_PRINT
|
||||
|
96
bip32.h
96
bip32.h
@ -24,58 +24,73 @@
|
||||
#ifndef __BIP32_H__
|
||||
#define __BIP32_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "ecdsa.h"
|
||||
#include "ed25519-donna/ed25519.h"
|
||||
#include "options.h"
|
||||
|
||||
typedef struct {
|
||||
const char *bip32_name; // string for generating BIP32 xprv from seed
|
||||
const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519
|
||||
const char *bip32_name; // string for generating BIP32 xprv from seed
|
||||
const ecdsa_curve *params; // ecdsa curve parameters, null for ed25519
|
||||
|
||||
HasherType hasher_base58;
|
||||
HasherType hasher_sign;
|
||||
HasherType hasher_pubkey;
|
||||
HasherType hasher_script;
|
||||
HasherType hasher_base58;
|
||||
HasherType hasher_sign;
|
||||
HasherType hasher_pubkey;
|
||||
HasherType hasher_script;
|
||||
} curve_info;
|
||||
|
||||
typedef struct {
|
||||
uint32_t depth;
|
||||
uint32_t child_num;
|
||||
uint8_t chain_code[32];
|
||||
uint32_t depth;
|
||||
uint32_t child_num;
|
||||
uint8_t chain_code[32];
|
||||
|
||||
uint8_t private_key[32];
|
||||
uint8_t private_key_extension[32];
|
||||
uint8_t private_key[32];
|
||||
uint8_t private_key_extension[32];
|
||||
|
||||
uint8_t public_key[33];
|
||||
const curve_info *curve;
|
||||
uint8_t public_key[33];
|
||||
const curve_info *curve;
|
||||
} HDNode;
|
||||
|
||||
int hdnode_from_xpub(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *public_key, const char *curve, HDNode *out);
|
||||
int hdnode_from_xpub(uint32_t depth, uint32_t child_num,
|
||||
const uint8_t *chain_code, const uint8_t *public_key,
|
||||
const char *curve, HDNode *out);
|
||||
|
||||
int hdnode_from_xprv(uint32_t depth, uint32_t child_num, const uint8_t *chain_code, const uint8_t *private_key, const char *curve, HDNode *out);
|
||||
int hdnode_from_xprv(uint32_t depth, uint32_t child_num,
|
||||
const uint8_t *chain_code, const uint8_t *private_key,
|
||||
const char *curve, HDNode *out);
|
||||
|
||||
int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNode *out);
|
||||
int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve,
|
||||
HDNode *out);
|
||||
|
||||
#define hdnode_private_ckd_prime(X, I) hdnode_private_ckd((X), ((I) | 0x80000000))
|
||||
#define hdnode_private_ckd_prime(X, I) \
|
||||
hdnode_private_ckd((X), ((I) | 0x80000000))
|
||||
|
||||
int hdnode_private_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
#if USE_CARDANO
|
||||
int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i);
|
||||
int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len, const uint8_t *seed, int seed_len, HDNode *out);
|
||||
int hdnode_from_seed_cardano(const uint8_t *pass, int pass_len,
|
||||
const uint8_t *seed, int seed_len, HDNode *out);
|
||||
#endif
|
||||
|
||||
int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent, const uint8_t *parent_chain_code, uint32_t i, curve_point *child, uint8_t *child_chain_code);
|
||||
int hdnode_public_ckd_cp(const ecdsa_curve *curve, const curve_point *parent,
|
||||
const uint8_t *parent_chain_code, uint32_t i,
|
||||
curve_point *child, uint8_t *child_chain_code);
|
||||
|
||||
int hdnode_public_ckd(HDNode *inout, uint32_t i);
|
||||
|
||||
void hdnode_public_ckd_address_optimized(const curve_point *pub, const uint8_t *chain_code, uint32_t i, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize, int addrformat);
|
||||
void hdnode_public_ckd_address_optimized(const curve_point *pub,
|
||||
const uint8_t *chain_code, uint32_t i,
|
||||
uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58, char *addr,
|
||||
int addrsize, int addrformat);
|
||||
|
||||
#if USE_BIP32_CACHE
|
||||
int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count, uint32_t *fingerprint);
|
||||
int hdnode_private_ckd_cached(HDNode *inout, const uint32_t *i, size_t i_count,
|
||||
uint32_t *fingerprint);
|
||||
#endif
|
||||
|
||||
uint32_t hdnode_fingerprint(HDNode *node);
|
||||
@ -88,24 +103,41 @@ int hdnode_get_ethereum_pubkeyhash(const HDNode *node, uint8_t *pubkeyhash);
|
||||
|
||||
#if USE_NEM
|
||||
int hdnode_get_nem_address(HDNode *node, uint8_t version, char *address);
|
||||
int hdnode_get_nem_shared_key(const HDNode *node, const ed25519_public_key peer_public_key, const uint8_t *salt, ed25519_public_key mul, uint8_t *shared_key);
|
||||
int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key, const uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);
|
||||
int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key, uint8_t *iv, const uint8_t *salt, const uint8_t *payload, size_t size, uint8_t *buffer);
|
||||
int hdnode_get_nem_shared_key(const HDNode *node,
|
||||
const ed25519_public_key peer_public_key,
|
||||
const uint8_t *salt, ed25519_public_key mul,
|
||||
uint8_t *shared_key);
|
||||
int hdnode_nem_encrypt(const HDNode *node, const ed25519_public_key public_key,
|
||||
const uint8_t *iv, const uint8_t *salt,
|
||||
const uint8_t *payload, size_t size, uint8_t *buffer);
|
||||
int hdnode_nem_decrypt(const HDNode *node, const ed25519_public_key public_key,
|
||||
uint8_t *iv, const uint8_t *salt, const uint8_t *payload,
|
||||
size_t size, uint8_t *buffer);
|
||||
#endif
|
||||
|
||||
int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType hasher_sign, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len,
|
||||
HasherType hasher_sign, uint8_t *sig, uint8_t *pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int hdnode_sign_digest(HDNode *node, const uint8_t *digest, uint8_t *sig,
|
||||
uint8_t *pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
|
||||
int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key, uint8_t *session_key, int *result_size);
|
||||
int hdnode_get_shared_key(const HDNode *node, const uint8_t *peer_public_key,
|
||||
uint8_t *session_key, int *result_size);
|
||||
|
||||
int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);
|
||||
int hdnode_serialize_public(const HDNode *node, uint32_t fingerprint,
|
||||
uint32_t version, char *str, int strsize);
|
||||
|
||||
int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint, uint32_t version, char *str, int strsize);
|
||||
int hdnode_serialize_private(const HDNode *node, uint32_t fingerprint,
|
||||
uint32_t version, char *str, int strsize);
|
||||
|
||||
int hdnode_deserialize(const char *str, uint32_t version_public, uint32_t version_private, const char *curve, HDNode *node, uint32_t *fingerprint);
|
||||
int hdnode_deserialize(const char *str, uint32_t version_public,
|
||||
uint32_t version_private, const char *curve,
|
||||
HDNode *node, uint32_t *fingerprint);
|
||||
|
||||
void hdnode_get_address_raw(HDNode *node, uint32_t version, uint8_t *addr_raw);
|
||||
void hdnode_get_address(HDNode *node, uint32_t version, char *addr, int addrsize);
|
||||
void hdnode_get_address(HDNode *node, uint32_t version, char *addr,
|
||||
int addrsize);
|
||||
|
||||
const curve_info *get_curve_by_name(const char *curve_name);
|
||||
|
||||
|
343
bip39.c
343
bip39.c
@ -21,216 +21,211 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bip39.h"
|
||||
#include "bip39_english.h"
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
#include "pbkdf2.h"
|
||||
#include "rand.h"
|
||||
#include "sha2.h"
|
||||
#include "pbkdf2.h"
|
||||
#include "bip39_english.h"
|
||||
#include "options.h"
|
||||
#include "memzero.h"
|
||||
|
||||
#if USE_BIP39_CACHE
|
||||
|
||||
static int bip39_cache_index = 0;
|
||||
|
||||
static CONFIDENTIAL struct {
|
||||
bool set;
|
||||
char mnemonic[256];
|
||||
char passphrase[64];
|
||||
uint8_t seed[512 / 8];
|
||||
bool set;
|
||||
char mnemonic[256];
|
||||
char passphrase[64];
|
||||
uint8_t seed[512 / 8];
|
||||
} bip39_cache[BIP39_CACHE_SIZE];
|
||||
|
||||
#endif
|
||||
|
||||
const char *mnemonic_generate(int strength)
|
||||
{
|
||||
if (strength % 32 || strength < 128 || strength > 256) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t data[32];
|
||||
random_buffer(data, 32);
|
||||
const char *r = mnemonic_from_data(data, strength / 8);
|
||||
memzero(data, sizeof(data));
|
||||
return r;
|
||||
const char *mnemonic_generate(int strength) {
|
||||
if (strength % 32 || strength < 128 || strength > 256) {
|
||||
return 0;
|
||||
}
|
||||
uint8_t data[32];
|
||||
random_buffer(data, 32);
|
||||
const char *r = mnemonic_from_data(data, strength / 8);
|
||||
memzero(data, sizeof(data));
|
||||
return r;
|
||||
}
|
||||
|
||||
static CONFIDENTIAL char mnemo[24 * 10];
|
||||
|
||||
const char *mnemonic_from_data(const uint8_t *data, int len)
|
||||
{
|
||||
if (len % 4 || len < 16 || len > 32) {
|
||||
return 0;
|
||||
}
|
||||
const char *mnemonic_from_data(const uint8_t *data, int len) {
|
||||
if (len % 4 || len < 16 || len > 32) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t bits[32 + 1];
|
||||
uint8_t bits[32 + 1];
|
||||
|
||||
sha256_Raw(data, len, bits);
|
||||
// checksum
|
||||
bits[len] = bits[0];
|
||||
// data
|
||||
memcpy(bits, data, len);
|
||||
sha256_Raw(data, len, bits);
|
||||
// checksum
|
||||
bits[len] = bits[0];
|
||||
// data
|
||||
memcpy(bits, data, len);
|
||||
|
||||
int mlen = len * 3 / 4;
|
||||
int mlen = len * 3 / 4;
|
||||
|
||||
int i, j, idx;
|
||||
char *p = mnemo;
|
||||
for (i = 0; i < mlen; i++) {
|
||||
idx = 0;
|
||||
for (j = 0; j < 11; j++) {
|
||||
idx <<= 1;
|
||||
idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
|
||||
}
|
||||
strcpy(p, wordlist[idx]);
|
||||
p += strlen(wordlist[idx]);
|
||||
*p = (i < mlen - 1) ? ' ' : 0;
|
||||
p++;
|
||||
}
|
||||
memzero(bits, sizeof(bits));
|
||||
int i, j, idx;
|
||||
char *p = mnemo;
|
||||
for (i = 0; i < mlen; i++) {
|
||||
idx = 0;
|
||||
for (j = 0; j < 11; j++) {
|
||||
idx <<= 1;
|
||||
idx += (bits[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0;
|
||||
}
|
||||
strcpy(p, wordlist[idx]);
|
||||
p += strlen(wordlist[idx]);
|
||||
*p = (i < mlen - 1) ? ' ' : 0;
|
||||
p++;
|
||||
}
|
||||
memzero(bits, sizeof(bits));
|
||||
|
||||
return mnemo;
|
||||
return mnemo;
|
||||
}
|
||||
|
||||
void mnemonic_clear(void)
|
||||
{
|
||||
memzero(mnemo, sizeof(mnemo));
|
||||
void mnemonic_clear(void) { memzero(mnemo, sizeof(mnemo)); }
|
||||
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy) {
|
||||
if (!mnemonic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i = 0, n = 0;
|
||||
|
||||
while (mnemonic[i]) {
|
||||
if (mnemonic[i] == ' ') {
|
||||
n++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
|
||||
// check number of words
|
||||
if (n != 12 && n != 18 && n != 24) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char current_word[10];
|
||||
uint32_t j, k, ki, bi = 0;
|
||||
uint8_t bits[32 + 1];
|
||||
|
||||
memzero(bits, sizeof(bits));
|
||||
i = 0;
|
||||
while (mnemonic[i]) {
|
||||
j = 0;
|
||||
while (mnemonic[i] != ' ' && mnemonic[i] != 0) {
|
||||
if (j >= sizeof(current_word) - 1) {
|
||||
return 0;
|
||||
}
|
||||
current_word[j] = mnemonic[i];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
current_word[j] = 0;
|
||||
if (mnemonic[i] != 0) {
|
||||
i++;
|
||||
}
|
||||
k = 0;
|
||||
for (;;) {
|
||||
if (!wordlist[k]) { // word not found
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k
|
||||
for (ki = 0; ki < 11; ki++) {
|
||||
if (k & (1 << (10 - ki))) {
|
||||
bits[bi / 8] |= 1 << (7 - (bi % 8));
|
||||
}
|
||||
bi++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
if (bi != n * 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(entropy, bits, sizeof(bits));
|
||||
return n * 11;
|
||||
}
|
||||
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy)
|
||||
{
|
||||
if (!mnemonic) {
|
||||
return 0;
|
||||
}
|
||||
int mnemonic_check(const char *mnemonic) {
|
||||
uint8_t bits[32 + 1];
|
||||
int seed_len = mnemonic_to_entropy(mnemonic, bits);
|
||||
if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {
|
||||
return 0;
|
||||
}
|
||||
int words = seed_len / 11;
|
||||
|
||||
uint32_t i = 0, n = 0;
|
||||
|
||||
while (mnemonic[i]) {
|
||||
if (mnemonic[i] == ' ') {
|
||||
n++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
|
||||
// check number of words
|
||||
if (n != 12 && n != 18 && n != 24) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char current_word[10];
|
||||
uint32_t j, k, ki, bi = 0;
|
||||
uint8_t bits[32 + 1];
|
||||
|
||||
memzero(bits, sizeof(bits));
|
||||
i = 0;
|
||||
while (mnemonic[i]) {
|
||||
j = 0;
|
||||
while (mnemonic[i] != ' ' && mnemonic[i] != 0) {
|
||||
if (j >= sizeof(current_word) - 1) {
|
||||
return 0;
|
||||
}
|
||||
current_word[j] = mnemonic[i];
|
||||
i++; j++;
|
||||
}
|
||||
current_word[j] = 0;
|
||||
if (mnemonic[i] != 0) {
|
||||
i++;
|
||||
}
|
||||
k = 0;
|
||||
for (;;) {
|
||||
if (!wordlist[k]) { // word not found
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(current_word, wordlist[k]) == 0) { // word found on index k
|
||||
for (ki = 0; ki < 11; ki++) {
|
||||
if (k & (1 << (10 - ki))) {
|
||||
bits[bi / 8] |= 1 << (7 - (bi % 8));
|
||||
}
|
||||
bi++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
if (bi != n * 11) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(entropy, bits, sizeof(bits));
|
||||
return n * 11;
|
||||
}
|
||||
|
||||
int mnemonic_check(const char *mnemonic)
|
||||
{
|
||||
uint8_t bits[32 + 1];
|
||||
int seed_len = mnemonic_to_entropy(mnemonic, bits);
|
||||
if (seed_len != (12 * 11) && seed_len != (18 * 11) && seed_len != (24 * 11)) {
|
||||
return 0;
|
||||
}
|
||||
int words = seed_len / 11;
|
||||
|
||||
uint8_t checksum = bits[words * 4 / 3];
|
||||
sha256_Raw(bits, words * 4 / 3, bits);
|
||||
if (words == 12) {
|
||||
return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits
|
||||
} else if (words == 18) {
|
||||
return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits
|
||||
} else if (words == 24) {
|
||||
return bits[0] == checksum; // compare 8 bits
|
||||
}
|
||||
return 0;
|
||||
uint8_t checksum = bits[words * 4 / 3];
|
||||
sha256_Raw(bits, words * 4 / 3, bits);
|
||||
if (words == 12) {
|
||||
return (bits[0] & 0xF0) == (checksum & 0xF0); // compare first 4 bits
|
||||
} else if (words == 18) {
|
||||
return (bits[0] & 0xFC) == (checksum & 0xFC); // compare first 6 bits
|
||||
} else if (words == 24) {
|
||||
return bits[0] == checksum; // compare 8 bits
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total))
|
||||
{
|
||||
int mnemoniclen = strlen(mnemonic);
|
||||
int passphraselen = strnlen(passphrase, 256);
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase,
|
||||
uint8_t seed[512 / 8],
|
||||
void (*progress_callback)(uint32_t current,
|
||||
uint32_t total)) {
|
||||
int mnemoniclen = strlen(mnemonic);
|
||||
int passphraselen = strnlen(passphrase, 256);
|
||||
#if USE_BIP39_CACHE
|
||||
// check cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
for (int i = 0; i < BIP39_CACHE_SIZE; i++) {
|
||||
if (!bip39_cache[i].set) continue;
|
||||
if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
|
||||
if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
|
||||
// found the correct entry
|
||||
memcpy(seed, bip39_cache[i].seed, 512 / 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// check cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
for (int i = 0; i < BIP39_CACHE_SIZE; i++) {
|
||||
if (!bip39_cache[i].set) continue;
|
||||
if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
|
||||
if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
|
||||
// found the correct entry
|
||||
memcpy(seed, bip39_cache[i].seed, 512 / 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
uint8_t salt[8 + 256];
|
||||
memcpy(salt, "mnemonic", 8);
|
||||
memcpy(salt + 8, passphrase, passphraselen);
|
||||
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt, passphraselen + 8, 1);
|
||||
if (progress_callback) {
|
||||
progress_callback(0, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
|
||||
if (progress_callback) {
|
||||
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, seed);
|
||||
memzero(salt, sizeof(salt));
|
||||
uint8_t salt[8 + 256];
|
||||
memcpy(salt, "mnemonic", 8);
|
||||
memcpy(salt + 8, passphrase, passphraselen);
|
||||
static CONFIDENTIAL PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, mnemoniclen, salt,
|
||||
passphraselen + 8, 1);
|
||||
if (progress_callback) {
|
||||
progress_callback(0, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
|
||||
if (progress_callback) {
|
||||
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16,
|
||||
BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
}
|
||||
pbkdf2_hmac_sha512_Final(&pctx, seed);
|
||||
memzero(salt, sizeof(salt));
|
||||
#if USE_BIP39_CACHE
|
||||
// store to cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
bip39_cache[bip39_cache_index].set = true;
|
||||
strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);
|
||||
strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);
|
||||
memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);
|
||||
bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;
|
||||
}
|
||||
// store to cache
|
||||
if (mnemoniclen < 256 && passphraselen < 64) {
|
||||
bip39_cache[bip39_cache_index].set = true;
|
||||
strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic);
|
||||
strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase);
|
||||
memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8);
|
||||
bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char * const *mnemonic_wordlist(void)
|
||||
{
|
||||
return wordlist;
|
||||
}
|
||||
const char *const *mnemonic_wordlist(void) { return wordlist; }
|
||||
|
9
bip39.h
9
bip39.h
@ -28,7 +28,7 @@
|
||||
|
||||
#define BIP39_PBKDF2_ROUNDS 2048
|
||||
|
||||
const char *mnemonic_generate(int strength); // strength in bits
|
||||
const char *mnemonic_generate(int strength); // strength in bits
|
||||
const char *mnemonic_from_data(const uint8_t *data, int len);
|
||||
void mnemonic_clear(void);
|
||||
|
||||
@ -37,8 +37,11 @@ int mnemonic_check(const char *mnemonic);
|
||||
int mnemonic_to_entropy(const char *mnemonic, uint8_t *entropy);
|
||||
|
||||
// passphrase must be at most 256 characters otherwise it would be truncated
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total));
|
||||
void mnemonic_to_seed(const char *mnemonic, const char *passphrase,
|
||||
uint8_t seed[512 / 8],
|
||||
void (*progress_callback)(uint32_t current,
|
||||
uint32_t total));
|
||||
|
||||
const char * const *mnemonic_wordlist(void);
|
||||
const char *const *mnemonic_wordlist(void);
|
||||
|
||||
#endif
|
||||
|
2393
bip39_english.h
2393
bip39_english.h
File diff suppressed because it is too large
Load Diff
@ -1,39 +1,25 @@
|
||||
static inline uint32_t load32( const void *src )
|
||||
{
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
static inline uint32_t load32(const void *src) {
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline uint64_t load64( const void *src )
|
||||
{
|
||||
static inline uint64_t load64(const void *src) {
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
}
|
||||
|
||||
static inline void store16( void *dst, uint16_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
static inline void store16(void *dst, uint16_t w) { memcpy(dst, &w, sizeof w); }
|
||||
|
||||
static inline void store32(void *dst, uint32_t w) { memcpy(dst, &w, sizeof w); }
|
||||
|
||||
static inline void store64(void *dst, uint64_t w) { memcpy(dst, &w, sizeof w); }
|
||||
|
||||
static inline uint32_t rotr32(const uint32_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (32 - c));
|
||||
}
|
||||
|
||||
static inline void store32( void *dst, uint32_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
static inline uint64_t rotr64(const uint64_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (64 - c));
|
||||
}
|
||||
|
||||
static inline void store64( void *dst, uint64_t w )
|
||||
{
|
||||
memcpy(dst, &w, sizeof w);
|
||||
}
|
||||
|
||||
static inline uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static inline uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
|
276
cash_addr.c
276
cash_addr.c
@ -19,8 +19,8 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cash_addr.h"
|
||||
@ -32,156 +32,158 @@
|
||||
#define CHECKSUM_SIZE 8
|
||||
|
||||
uint64_t cashaddr_polymod_step(uint64_t pre) {
|
||||
uint8_t b = pre >> 35;
|
||||
return ((pre & 0x7FFFFFFFFULL) << 5) ^
|
||||
(-((b >> 0) & 1) & 0x98f2bc8e61ULL) ^
|
||||
(-((b >> 1) & 1) & 0x79b76d99e2ULL) ^
|
||||
(-((b >> 2) & 1) & 0xf33e5fb3c4ULL) ^
|
||||
(-((b >> 3) & 1) & 0xae2eabe2a8ULL) ^
|
||||
(-((b >> 4) & 1) & 0x1e4f43e470ULL);
|
||||
uint8_t b = pre >> 35;
|
||||
return ((pre & 0x7FFFFFFFFULL) << 5) ^ (-((b >> 0) & 1) & 0x98f2bc8e61ULL) ^
|
||||
(-((b >> 1) & 1) & 0x79b76d99e2ULL) ^
|
||||
(-((b >> 2) & 1) & 0xf33e5fb3c4ULL) ^
|
||||
(-((b >> 3) & 1) & 0xae2eabe2a8ULL) ^
|
||||
(-((b >> 4) & 1) & 0x1e4f43e470ULL);
|
||||
}
|
||||
|
||||
static const char* charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
||||
|
||||
static const int8_t charset_rev[128] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
15, -1, 10, 17, 21, 20, 26, 30, 7, 5, -1, -1, -1, -1, -1, -1,
|
||||
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
|
||||
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1,
|
||||
-1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1,
|
||||
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
|
||||
};
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, -1, 10, 17, 21, 20, 26, 30, 7,
|
||||
5, -1, -1, -1, -1, -1, -1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22,
|
||||
31, 27, 19, -1, 1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1,
|
||||
-1, -1, 29, -1, 24, 13, 25, 9, 8, 23, -1, 18, 22, 31, 27, 19, -1, 1, 0,
|
||||
3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1};
|
||||
|
||||
int cash_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) {
|
||||
uint64_t chk = 1;
|
||||
size_t i = 0;
|
||||
while (hrp[i] != 0) {
|
||||
int ch = hrp[i];
|
||||
if (ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
*(output++) = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
++i;
|
||||
int cash_encode(char* output, const char* hrp, const uint8_t* data,
|
||||
size_t data_len) {
|
||||
uint64_t chk = 1;
|
||||
size_t i = 0;
|
||||
while (hrp[i] != 0) {
|
||||
int ch = hrp[i];
|
||||
if (ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
if (i + 1 + data_len + CHECKSUM_SIZE > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
*(output++) = ':';
|
||||
for (i = 0; i < data_len; ++i) {
|
||||
if (*data >> 5) return 0;
|
||||
chk = cashaddr_polymod_step(chk) ^ (*data);
|
||||
*(output++) = charset[*(data++)];
|
||||
}
|
||||
for (i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
}
|
||||
chk ^= 1;
|
||||
for (i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
*(output++) = charset[(chk >> ((CHECKSUM_SIZE - 1 - i) * 5)) & 0x1f];
|
||||
}
|
||||
*output = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cash_decode(char* hrp, uint8_t *data, size_t *data_len, const char *input) {
|
||||
uint64_t chk = 1;
|
||||
size_t i;
|
||||
size_t input_len = strlen(input);
|
||||
size_t hrp_len;
|
||||
int have_lower = 0, have_upper = 0;
|
||||
if (input_len < CHECKSUM_SIZE || input_len > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
*data_len = 0;
|
||||
while (*data_len < input_len && input[(input_len - 1) - *data_len] != ':') {
|
||||
++(*data_len);
|
||||
}
|
||||
hrp_len = input_len - (1 + *data_len);
|
||||
if (1 + *data_len >= input_len || hrp_len > MAX_HRP_SIZE ||
|
||||
*data_len < CHECKSUM_SIZE || *data_len > CHECKSUM_SIZE + MAX_BASE32_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
// subtract checksum
|
||||
*(data_len) -= CHECKSUM_SIZE;
|
||||
for (i = 0; i < hrp_len; ++i) {
|
||||
int ch = input[i];
|
||||
if (ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
have_lower = 1;
|
||||
} else if (ch >= 'A' && ch <= 'Z') {
|
||||
have_upper = 1;
|
||||
ch = (ch - 'A') + 'a';
|
||||
}
|
||||
hrp[i] = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
}
|
||||
hrp[i] = 0;
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
*(output++) = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
++i;
|
||||
while (i < input_len) {
|
||||
int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]];
|
||||
if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1;
|
||||
if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1;
|
||||
if (v == -1) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk) ^ v;
|
||||
if (i + CHECKSUM_SIZE < input_len) {
|
||||
data[i - (1 + hrp_len)] = v;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (have_lower && have_upper) {
|
||||
return 0;
|
||||
}
|
||||
return chk == 1;
|
||||
}
|
||||
if (i + 1 + data_len + CHECKSUM_SIZE > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
*(output++) = ':';
|
||||
for (i = 0; i < data_len; ++i) {
|
||||
if (*data >> 5) return 0;
|
||||
chk = cashaddr_polymod_step(chk) ^ (*data);
|
||||
*(output++) = charset[*(data++)];
|
||||
}
|
||||
for (i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
}
|
||||
chk ^= 1;
|
||||
for (i = 0; i < CHECKSUM_SIZE; ++i) {
|
||||
*(output++) = charset[(chk >> ((CHECKSUM_SIZE - 1 - i) * 5)) & 0x1f];
|
||||
}
|
||||
*output = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int convert_bits(uint8_t* out, size_t* outlen, int outbits, const uint8_t* in, size_t inlen, int inbits, int pad) {
|
||||
uint32_t val = 0;
|
||||
int bits = 0;
|
||||
uint32_t maxv = (((uint32_t)1) << outbits) - 1;
|
||||
while (inlen--) {
|
||||
val = (val << inbits) | *(in++);
|
||||
bits += inbits;
|
||||
while (bits >= outbits) {
|
||||
bits -= outbits;
|
||||
out[(*outlen)++] = (val >> bits) & maxv;
|
||||
}
|
||||
int cash_decode(char* hrp, uint8_t* data, size_t* data_len, const char* input) {
|
||||
uint64_t chk = 1;
|
||||
size_t i;
|
||||
size_t input_len = strlen(input);
|
||||
size_t hrp_len;
|
||||
int have_lower = 0, have_upper = 0;
|
||||
if (input_len < CHECKSUM_SIZE || input_len > MAX_CASHADDR_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
*data_len = 0;
|
||||
while (*data_len < input_len && input[(input_len - 1) - *data_len] != ':') {
|
||||
++(*data_len);
|
||||
}
|
||||
hrp_len = input_len - (1 + *data_len);
|
||||
if (1 + *data_len >= input_len || hrp_len > MAX_HRP_SIZE ||
|
||||
*data_len < CHECKSUM_SIZE ||
|
||||
*data_len > CHECKSUM_SIZE + MAX_BASE32_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
// subtract checksum
|
||||
*(data_len) -= CHECKSUM_SIZE;
|
||||
for (i = 0; i < hrp_len; ++i) {
|
||||
int ch = input[i];
|
||||
if (ch < 33 || ch > 126) {
|
||||
return 0;
|
||||
}
|
||||
if (pad) {
|
||||
if (bits) {
|
||||
out[(*outlen)++] = (val << (outbits - bits)) & maxv;
|
||||
}
|
||||
} else if (((val << (outbits - bits)) & maxv) || bits >= inbits) {
|
||||
return 0;
|
||||
if (ch >= 'a' && ch <= 'z') {
|
||||
have_lower = 1;
|
||||
} else if (ch >= 'A' && ch <= 'Z') {
|
||||
have_upper = 1;
|
||||
ch = (ch - 'A') + 'a';
|
||||
}
|
||||
return 1;
|
||||
hrp[i] = ch;
|
||||
chk = cashaddr_polymod_step(chk) ^ (ch & 0x1f);
|
||||
}
|
||||
hrp[i] = 0;
|
||||
chk = cashaddr_polymod_step(chk);
|
||||
++i;
|
||||
while (i < input_len) {
|
||||
int v = (input[i] & 0x80) ? -1 : charset_rev[(int)input[i]];
|
||||
if (input[i] >= 'a' && input[i] <= 'z') have_lower = 1;
|
||||
if (input[i] >= 'A' && input[i] <= 'Z') have_upper = 1;
|
||||
if (v == -1) {
|
||||
return 0;
|
||||
}
|
||||
chk = cashaddr_polymod_step(chk) ^ v;
|
||||
if (i + CHECKSUM_SIZE < input_len) {
|
||||
data[i - (1 + hrp_len)] = v;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
if (have_lower && have_upper) {
|
||||
return 0;
|
||||
}
|
||||
return chk == 1;
|
||||
}
|
||||
|
||||
int cash_addr_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len) {
|
||||
uint8_t base32[MAX_BASE32_SIZE];
|
||||
size_t base32len = 0;
|
||||
if (data_len < 2 || data_len > MAX_DATA_SIZE) return 0;
|
||||
convert_bits(base32, &base32len, 5, data, data_len, 8, 1);
|
||||
return cash_encode(output, hrp, base32, base32len);
|
||||
static int convert_bits(uint8_t* out, size_t* outlen, int outbits,
|
||||
const uint8_t* in, size_t inlen, int inbits, int pad) {
|
||||
uint32_t val = 0;
|
||||
int bits = 0;
|
||||
uint32_t maxv = (((uint32_t)1) << outbits) - 1;
|
||||
while (inlen--) {
|
||||
val = (val << inbits) | *(in++);
|
||||
bits += inbits;
|
||||
while (bits >= outbits) {
|
||||
bits -= outbits;
|
||||
out[(*outlen)++] = (val >> bits) & maxv;
|
||||
}
|
||||
}
|
||||
if (pad) {
|
||||
if (bits) {
|
||||
out[(*outlen)++] = (val << (outbits - bits)) & maxv;
|
||||
}
|
||||
} else if (((val << (outbits - bits)) & maxv) || bits >= inbits) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cash_addr_decode(uint8_t* witdata, size_t* witdata_len, const char* hrp, const char* addr) {
|
||||
uint8_t data[MAX_BASE32_SIZE];
|
||||
char hrp_actual[MAX_HRP_SIZE+1];
|
||||
size_t data_len;
|
||||
if (!cash_decode(hrp_actual, data, &data_len, addr)) return 0;
|
||||
if (data_len == 0 || data_len > MAX_BASE32_SIZE) return 0;
|
||||
if (strncmp(hrp, hrp_actual, MAX_HRP_SIZE + 1) != 0) return 0;
|
||||
*witdata_len = 0;
|
||||
if (!convert_bits(witdata, witdata_len, 8, data, data_len, 5, 0)) return 0;
|
||||
if (*witdata_len < 2 || *witdata_len > MAX_DATA_SIZE) return 0;
|
||||
return 1;
|
||||
int cash_addr_encode(char* output, const char* hrp, const uint8_t* data,
|
||||
size_t data_len) {
|
||||
uint8_t base32[MAX_BASE32_SIZE];
|
||||
size_t base32len = 0;
|
||||
if (data_len < 2 || data_len > MAX_DATA_SIZE) return 0;
|
||||
convert_bits(base32, &base32len, 5, data, data_len, 8, 1);
|
||||
return cash_encode(output, hrp, base32, base32len);
|
||||
}
|
||||
|
||||
int cash_addr_decode(uint8_t* witdata, size_t* witdata_len, const char* hrp,
|
||||
const char* addr) {
|
||||
uint8_t data[MAX_BASE32_SIZE];
|
||||
char hrp_actual[MAX_HRP_SIZE + 1];
|
||||
size_t data_len;
|
||||
if (!cash_decode(hrp_actual, data, &data_len, addr)) return 0;
|
||||
if (data_len == 0 || data_len > MAX_BASE32_SIZE) return 0;
|
||||
if (strncmp(hrp, hrp_actual, MAX_HRP_SIZE + 1) != 0) return 0;
|
||||
*witdata_len = 0;
|
||||
if (!convert_bits(witdata, witdata_len, 8, data, data_len, 5, 0)) return 0;
|
||||
if (*witdata_len < 2 || *witdata_len > MAX_DATA_SIZE) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
41
cash_addr.h
41
cash_addr.h
@ -34,30 +34,20 @@
|
||||
* prog_len: Number of data bytes in prog.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int cash_addr_encode(
|
||||
char *output,
|
||||
const char *hrp,
|
||||
const uint8_t *prog,
|
||||
size_t prog_len
|
||||
);
|
||||
int cash_addr_encode(char *output, const char *hrp, const uint8_t *prog,
|
||||
size_t prog_len);
|
||||
|
||||
/** Decode a CashAddr address
|
||||
*
|
||||
* Out: prog: Pointer to a buffer of size 65 that will be updated to
|
||||
* contain the witness program bytes.
|
||||
* prog_len: Pointer to a size_t that will be updated to contain the length
|
||||
* of bytes in prog.
|
||||
* hrp: Pointer to the null-terminated human readable part that is
|
||||
* expected (chain/network specific).
|
||||
* addr: Pointer to the null-terminated address.
|
||||
* Returns 1 if successful.
|
||||
* prog_len: Pointer to a size_t that will be updated to contain the
|
||||
* length of bytes in prog. hrp: Pointer to the null-terminated human
|
||||
* readable part that is expected (chain/network specific). addr: Pointer to
|
||||
* the null-terminated address. Returns 1 if successful.
|
||||
*/
|
||||
int cash_addr_decode(
|
||||
uint8_t* prog,
|
||||
size_t* prog_len,
|
||||
const char* hrp,
|
||||
const char* addr
|
||||
);
|
||||
int cash_addr_decode(uint8_t *prog, size_t *prog_len, const char *hrp,
|
||||
const char *addr);
|
||||
|
||||
/** Encode a Cash string
|
||||
*
|
||||
@ -68,12 +58,8 @@ int cash_addr_decode(
|
||||
* data_len: Length of the data array.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int cash_encode(
|
||||
char *output,
|
||||
const char *hrp,
|
||||
const uint8_t *data,
|
||||
size_t data_len
|
||||
);
|
||||
int cash_encode(char *output, const char *hrp, const uint8_t *data,
|
||||
size_t data_len);
|
||||
|
||||
/** Decode a Cash string
|
||||
*
|
||||
@ -86,11 +72,6 @@ int cash_encode(
|
||||
* In: input: Pointer to a null-terminated Cash string.
|
||||
* Returns 1 if succesful.
|
||||
*/
|
||||
int cash_decode(
|
||||
char *hrp,
|
||||
uint8_t *data,
|
||||
size_t *data_len,
|
||||
const char *input
|
||||
);
|
||||
int cash_decode(char *hrp, uint8_t *data, size_t *data_len, const char *input);
|
||||
|
||||
#endif
|
||||
|
91
ecdsa.h
91
ecdsa.h
@ -25,26 +25,25 @@
|
||||
#define __ECDSA_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "options.h"
|
||||
#include "bignum.h"
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
// curve point x and y
|
||||
typedef struct {
|
||||
bignum256 x, y;
|
||||
bignum256 x, y;
|
||||
} curve_point;
|
||||
|
||||
typedef struct {
|
||||
|
||||
bignum256 prime; // prime order of the finite field
|
||||
curve_point G; // initial curve point
|
||||
bignum256 order; // order of G
|
||||
bignum256 order_half; // order of G divided by 2
|
||||
int a; // coefficient 'a' of the elliptic curve
|
||||
bignum256 b; // coefficient 'b' of the elliptic curve
|
||||
bignum256 prime; // prime order of the finite field
|
||||
curve_point G; // initial curve point
|
||||
bignum256 order; // order of G
|
||||
bignum256 order_half; // order of G divided by 2
|
||||
int a; // coefficient 'a' of the elliptic curve
|
||||
bignum256 b; // coefficient 'b' of the elliptic curve
|
||||
|
||||
#if USE_PRECOMPUTED_CP
|
||||
const curve_point cp[64][8];
|
||||
const curve_point cp[64][8];
|
||||
#endif
|
||||
|
||||
} ecdsa_curve;
|
||||
@ -63,35 +62,65 @@ typedef struct {
|
||||
#define MAX_WIF_SIZE (57)
|
||||
|
||||
void point_copy(const curve_point *cp1, curve_point *cp2);
|
||||
void point_add(const ecdsa_curve *curve, const curve_point *cp1, curve_point *cp2);
|
||||
void point_add(const ecdsa_curve *curve, const curve_point *cp1,
|
||||
curve_point *cp2);
|
||||
void point_double(const ecdsa_curve *curve, curve_point *cp);
|
||||
void point_multiply(const ecdsa_curve *curve, const bignum256 *k, const curve_point *p, curve_point *res);
|
||||
void point_multiply(const ecdsa_curve *curve, const bignum256 *k,
|
||||
const curve_point *p, curve_point *res);
|
||||
void point_set_infinity(curve_point *p);
|
||||
int point_is_infinity(const curve_point *p);
|
||||
int point_is_equal(const curve_point *p, const curve_point *q);
|
||||
int point_is_negative_of(const curve_point *p, const curve_point *q);
|
||||
void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k, curve_point *res);
|
||||
int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *pub_key, uint8_t *session_key);
|
||||
void uncompress_coords(const ecdsa_curve *curve, uint8_t odd, const bignum256 *x, bignum256 *y);
|
||||
int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed);
|
||||
void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k,
|
||||
curve_point *res);
|
||||
int ecdh_multiply(const ecdsa_curve *curve, const uint8_t *priv_key,
|
||||
const uint8_t *pub_key, uint8_t *session_key);
|
||||
void uncompress_coords(const ecdsa_curve *curve, uint8_t odd,
|
||||
const bignum256 *x, bignum256 *y);
|
||||
int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key,
|
||||
uint8_t *uncompressed);
|
||||
|
||||
int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key);
|
||||
void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, uint8_t *pub_key);
|
||||
void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey, uint8_t *pubkeyhash);
|
||||
void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw);
|
||||
void ecdsa_get_address(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize);
|
||||
void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, uint8_t *addr_raw);
|
||||
void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version, HasherType hasher_pubkey, HasherType hasher_base58, char *addr, int addrsize);
|
||||
void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version, HasherType hasher_base58, char *wif, int wifsize);
|
||||
int ecdsa_sign(const ecdsa_curve *curve, HasherType hasher_sign,
|
||||
const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len,
|
||||
uint8_t *sig, uint8_t *pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key,
|
||||
const uint8_t *digest, uint8_t *sig, uint8_t *pby,
|
||||
int (*is_canonical)(uint8_t by, uint8_t sig[64]));
|
||||
void ecdsa_get_public_key33(const ecdsa_curve *curve, const uint8_t *priv_key,
|
||||
uint8_t *pub_key);
|
||||
void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key,
|
||||
uint8_t *pub_key);
|
||||
void ecdsa_get_pubkeyhash(const uint8_t *pub_key, HasherType hasher_pubkey,
|
||||
uint8_t *pubkeyhash);
|
||||
void ecdsa_get_address_raw(const uint8_t *pub_key, uint32_t version,
|
||||
HasherType hasher_pubkey, uint8_t *addr_raw);
|
||||
void ecdsa_get_address(const uint8_t *pub_key, uint32_t version,
|
||||
HasherType hasher_pubkey, HasherType hasher_base58,
|
||||
char *addr, int addrsize);
|
||||
void ecdsa_get_address_segwit_p2sh_raw(const uint8_t *pub_key, uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
uint8_t *addr_raw);
|
||||
void ecdsa_get_address_segwit_p2sh(const uint8_t *pub_key, uint32_t version,
|
||||
HasherType hasher_pubkey,
|
||||
HasherType hasher_base58, char *addr,
|
||||
int addrsize);
|
||||
void ecdsa_get_wif(const uint8_t *priv_key, uint32_t version,
|
||||
HasherType hasher_base58, char *wif, int wifsize);
|
||||
|
||||
int ecdsa_address_decode(const char *addr, uint32_t version, HasherType hasher_base58, uint8_t *out);
|
||||
int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, curve_point *pub);
|
||||
int ecdsa_address_decode(const char *addr, uint32_t version,
|
||||
HasherType hasher_base58, uint8_t *out);
|
||||
int ecdsa_read_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key,
|
||||
curve_point *pub);
|
||||
int ecdsa_validate_pubkey(const ecdsa_curve *curve, const curve_point *pub);
|
||||
int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
||||
int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest);
|
||||
int ecdsa_recover_pub_from_sig (const ecdsa_curve *curve, uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest, int recid);
|
||||
int ecdsa_verify(const ecdsa_curve *curve, HasherType hasher_sign,
|
||||
const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg,
|
||||
uint32_t msg_len);
|
||||
int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key,
|
||||
const uint8_t *sig, const uint8_t *digest);
|
||||
int ecdsa_recover_pub_from_sig(const ecdsa_curve *curve, uint8_t *pub_key,
|
||||
const uint8_t *sig, const uint8_t *digest,
|
||||
int recid);
|
||||
int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der);
|
||||
|
||||
#endif
|
||||
|
195
hasher.c
195
hasher.c
@ -23,122 +23,125 @@
|
||||
#include "hasher.h"
|
||||
#include "ripemd160.h"
|
||||
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size) {
|
||||
hasher->type = type;
|
||||
hasher->param = param;
|
||||
hasher->param_size = param_size;
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param,
|
||||
uint32_t param_size) {
|
||||
hasher->type = type;
|
||||
hasher->param = param;
|
||||
hasher->param_size = param_size;
|
||||
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Init(&hasher->ctx.sha2);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Init(&hasher->ctx.sha2);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
case HASHER_SHA3K:
|
||||
#endif
|
||||
sha3_256_Init(&hasher->ctx.sha3);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Init(&hasher->ctx.blake);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Init(&hasher->ctx.groestl);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
blake2b_Init(&hasher->ctx.blake2b, 32);
|
||||
break;
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_InitPersonal(&hasher->ctx.blake2b, 32, hasher->param, hasher->param_size);
|
||||
break;
|
||||
}
|
||||
sha3_256_Init(&hasher->ctx.sha3);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Init(&hasher->ctx.blake);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Init(&hasher->ctx.groestl);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
blake2b_Init(&hasher->ctx.blake2b, 32);
|
||||
break;
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_InitPersonal(&hasher->ctx.blake2b, 32, hasher->param,
|
||||
hasher->param_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Init(Hasher *hasher, HasherType type) {
|
||||
hasher_InitParam(hasher, type, NULL, 0);
|
||||
hasher_InitParam(hasher, type, NULL, 0);
|
||||
}
|
||||
|
||||
void hasher_Reset(Hasher *hasher) {
|
||||
hasher_InitParam(hasher, hasher->type, hasher->param, hasher->param_size);
|
||||
hasher_InitParam(hasher, hasher->type, hasher->param, hasher->param_size);
|
||||
}
|
||||
|
||||
void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length) {
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Update(&hasher->ctx.sha2, data, length);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
case HASHER_SHA2D:
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Update(&hasher->ctx.sha2, data, length);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
case HASHER_SHA3K:
|
||||
#endif
|
||||
sha3_Update(&hasher->ctx.sha3, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Update(&hasher->ctx.blake, data, length);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Update(&hasher->ctx.groestl, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Update(&hasher->ctx.blake2b, data, length);
|
||||
break;
|
||||
}
|
||||
sha3_Update(&hasher->ctx.sha3, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE:
|
||||
case HASHER_BLAKED:
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Update(&hasher->ctx.blake, data, length);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_Update(&hasher->ctx.groestl, data, length);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Update(&hasher->ctx.blake2b, data, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]) {
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
break;
|
||||
case HASHER_SHA2D:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
sha3_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
switch (hasher->type) {
|
||||
case HASHER_SHA2:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
break;
|
||||
case HASHER_SHA2D:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
hasher_Raw(HASHER_SHA2, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA2_RIPEMD:
|
||||
sha256_Final(&hasher->ctx.sha2, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_SHA3:
|
||||
sha3_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
#if USE_KECCAK
|
||||
case HASHER_SHA3K:
|
||||
keccak_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
case HASHER_SHA3K:
|
||||
keccak_Final(&hasher->ctx.sha3, hash);
|
||||
break;
|
||||
#endif
|
||||
case HASHER_BLAKE:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
break;
|
||||
case HASHER_BLAKED:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
hasher_Raw(HASHER_BLAKE, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_DoubleTrunc(&hasher->ctx.groestl, hash);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Final(&hasher->ctx.blake2b, hash, 32);
|
||||
break;
|
||||
}
|
||||
case HASHER_BLAKE:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
break;
|
||||
case HASHER_BLAKED:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
hasher_Raw(HASHER_BLAKE, hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_BLAKE_RIPEMD:
|
||||
blake256_Final(&hasher->ctx.blake, hash);
|
||||
ripemd160(hash, HASHER_DIGEST_LENGTH, hash);
|
||||
break;
|
||||
case HASHER_GROESTLD_TRUNC:
|
||||
groestl512_DoubleTrunc(&hasher->ctx.groestl, hash);
|
||||
break;
|
||||
case HASHER_BLAKE2B:
|
||||
case HASHER_BLAKE2B_PERSONAL:
|
||||
blake2b_Final(&hasher->ctx.blake2b, hash, 32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]) {
|
||||
Hasher hasher;
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length,
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH]) {
|
||||
Hasher hasher;
|
||||
|
||||
hasher_Init(&hasher, type);
|
||||
hasher_Update(&hasher, data, length);
|
||||
hasher_Final(&hasher, hash);
|
||||
hasher_Init(&hasher, type);
|
||||
hasher_Update(&hasher, data, length);
|
||||
hasher_Final(&hasher, hash);
|
||||
}
|
||||
|
54
hasher.h
54
hasher.h
@ -26,55 +26,57 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "blake256.h"
|
||||
#include "blake2b.h"
|
||||
#include "groestl.h"
|
||||
#include "sha2.h"
|
||||
#include "sha3.h"
|
||||
#include "blake256.h"
|
||||
#include "groestl.h"
|
||||
#include "blake2b.h"
|
||||
|
||||
#define HASHER_DIGEST_LENGTH 32
|
||||
|
||||
typedef enum {
|
||||
HASHER_SHA2,
|
||||
HASHER_SHA2D,
|
||||
HASHER_SHA2_RIPEMD,
|
||||
HASHER_SHA2,
|
||||
HASHER_SHA2D,
|
||||
HASHER_SHA2_RIPEMD,
|
||||
|
||||
HASHER_SHA3,
|
||||
HASHER_SHA3,
|
||||
#if USE_KECCAK
|
||||
HASHER_SHA3K,
|
||||
HASHER_SHA3K,
|
||||
#endif
|
||||
|
||||
HASHER_BLAKE,
|
||||
HASHER_BLAKED,
|
||||
HASHER_BLAKE_RIPEMD,
|
||||
HASHER_BLAKE,
|
||||
HASHER_BLAKED,
|
||||
HASHER_BLAKE_RIPEMD,
|
||||
|
||||
HASHER_GROESTLD_TRUNC, /* Double Groestl512 hasher truncated to 256 bits */
|
||||
HASHER_GROESTLD_TRUNC, /* Double Groestl512 hasher truncated to 256 bits */
|
||||
|
||||
HASHER_BLAKE2B,
|
||||
HASHER_BLAKE2B_PERSONAL,
|
||||
HASHER_BLAKE2B,
|
||||
HASHER_BLAKE2B_PERSONAL,
|
||||
} HasherType;
|
||||
|
||||
typedef struct {
|
||||
HasherType type;
|
||||
HasherType type;
|
||||
|
||||
union {
|
||||
SHA256_CTX sha2; // for HASHER_SHA2{,D}
|
||||
SHA3_CTX sha3; // for HASHER_SHA3{,K}
|
||||
BLAKE256_CTX blake; // for HASHER_BLAKE{,D}
|
||||
GROESTL512_CTX groestl; // for HASHER_GROESTLD_TRUNC
|
||||
BLAKE2B_CTX blake2b; // for HASHER_BLAKE2B{,_PERSONAL}
|
||||
} ctx;
|
||||
union {
|
||||
SHA256_CTX sha2; // for HASHER_SHA2{,D}
|
||||
SHA3_CTX sha3; // for HASHER_SHA3{,K}
|
||||
BLAKE256_CTX blake; // for HASHER_BLAKE{,D}
|
||||
GROESTL512_CTX groestl; // for HASHER_GROESTLD_TRUNC
|
||||
BLAKE2B_CTX blake2b; // for HASHER_BLAKE2B{,_PERSONAL}
|
||||
} ctx;
|
||||
|
||||
const void *param;
|
||||
uint32_t param_size;
|
||||
const void *param;
|
||||
uint32_t param_size;
|
||||
} Hasher;
|
||||
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param, uint32_t param_size);
|
||||
void hasher_InitParam(Hasher *hasher, HasherType type, const void *param,
|
||||
uint32_t param_size);
|
||||
void hasher_Init(Hasher *hasher, HasherType type);
|
||||
void hasher_Reset(Hasher *hasher);
|
||||
void hasher_Update(Hasher *hasher, const uint8_t *data, size_t length);
|
||||
void hasher_Final(Hasher *hasher, uint8_t hash[HASHER_DIGEST_LENGTH]);
|
||||
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length, uint8_t hash[HASHER_DIGEST_LENGTH]);
|
||||
void hasher_Raw(HasherType type, const uint8_t *data, size_t length,
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH]);
|
||||
|
||||
#endif
|
||||
|
236
hmac.c
236
hmac.c
@ -24,155 +24,153 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac.h"
|
||||
#include "options.h"
|
||||
#include "memzero.h"
|
||||
#include "options.h"
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen)
|
||||
{
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
sha256_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA256_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
sha256_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), i_key_pad, SHA256_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen)
|
||||
{
|
||||
sha256_Update(&(hctx->ctx), msg, msglen);
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha256_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac)
|
||||
{
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);
|
||||
sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA256_CTX));
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac) {
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
sha256_Init(&(hctx->ctx));
|
||||
sha256_Update(&(hctx->ctx), hctx->o_key_pad, SHA256_BLOCK_LENGTH);
|
||||
sha256_Update(&(hctx->ctx), hmac, SHA256_DIGEST_LENGTH);
|
||||
sha256_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac)
|
||||
{
|
||||
static CONFIDENTIAL HMAC_SHA256_CTX hctx;
|
||||
hmac_sha256_Init(&hctx, key, keylen);
|
||||
hmac_sha256_Update(&hctx, msg, msglen);
|
||||
hmac_sha256_Final(&hctx, hmac);
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
static CONFIDENTIAL HMAC_SHA256_CTX hctx;
|
||||
hmac_sha256_Init(&hctx, key, keylen);
|
||||
hmac_sha256_Update(&hctx, msg, msglen);
|
||||
hmac_sha256_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest)
|
||||
{
|
||||
static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint32_t *opad_digest, uint32_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint32_t key_pad[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA256_CTX context;
|
||||
sha256_Init(&context);
|
||||
sha256_Update(&context, key, keylen);
|
||||
sha256_Final(&context, (uint8_t*)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA256_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA256_CTX context;
|
||||
sha256_Init(&context);
|
||||
sha256_Update(&context, key, keylen);
|
||||
sha256_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) {
|
||||
uint32_t data;
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
uint32_t data;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(key_pad[i], data);
|
||||
REVERSE32(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);
|
||||
key_pad[i] = data ^ 0x5c5c5c5c;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH/(int)sizeof(uint32_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA256_BLOCK_LENGTH / (int)sizeof(uint32_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
|
||||
}
|
||||
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen)
|
||||
{
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
sha512_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen) {
|
||||
static CONFIDENTIAL uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
|
||||
memzero(i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
sha512_Raw(key, keylen, i_key_pad);
|
||||
} else {
|
||||
memcpy(i_key_pad, key, keylen);
|
||||
}
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH; i++) {
|
||||
hctx->o_key_pad[i] = i_key_pad[i] ^ 0x5c;
|
||||
i_key_pad[i] ^= 0x36;
|
||||
}
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), i_key_pad, SHA512_BLOCK_LENGTH);
|
||||
memzero(i_key_pad, sizeof(i_key_pad));
|
||||
}
|
||||
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen)
|
||||
{
|
||||
sha512_Update(&(hctx->ctx), msg, msglen);
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen) {
|
||||
sha512_Update(&(hctx->ctx), msg, msglen);
|
||||
}
|
||||
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac)
|
||||
{
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);
|
||||
sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA512_CTX));
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac) {
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
sha512_Init(&(hctx->ctx));
|
||||
sha512_Update(&(hctx->ctx), hctx->o_key_pad, SHA512_BLOCK_LENGTH);
|
||||
sha512_Update(&(hctx->ctx), hmac, SHA512_DIGEST_LENGTH);
|
||||
sha512_Final(&(hctx->ctx), hmac);
|
||||
memzero(hctx, sizeof(HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac)
|
||||
{
|
||||
HMAC_SHA512_CTX hctx;
|
||||
hmac_sha512_Init(&hctx, key, keylen);
|
||||
hmac_sha512_Update(&hctx, msg, msglen);
|
||||
hmac_sha512_Final(&hctx, hmac);
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac) {
|
||||
HMAC_SHA512_CTX hctx;
|
||||
hmac_sha512_Init(&hctx, key, keylen);
|
||||
hmac_sha512_Update(&hctx, msg, msglen);
|
||||
hmac_sha512_Final(&hctx, hmac);
|
||||
}
|
||||
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest)
|
||||
{
|
||||
static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint64_t *opad_digest, uint64_t *ipad_digest) {
|
||||
static CONFIDENTIAL uint64_t key_pad[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA512_CTX context;
|
||||
sha512_Init(&context);
|
||||
sha512_Update(&context, key, keylen);
|
||||
sha512_Final(&context, (uint8_t*)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
if (keylen > SHA512_BLOCK_LENGTH) {
|
||||
static CONFIDENTIAL SHA512_CTX context;
|
||||
sha512_Init(&context);
|
||||
sha512_Update(&context, key, keylen);
|
||||
sha512_Final(&context, (uint8_t *)key_pad);
|
||||
} else {
|
||||
memcpy(key_pad, key, keylen);
|
||||
}
|
||||
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) {
|
||||
uint64_t data;
|
||||
/* compute o_key_pad and its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
uint64_t data;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE64(key_pad[i], data);
|
||||
REVERSE64(key_pad[i], data);
|
||||
#else
|
||||
data = key_pad[i];
|
||||
data = key_pad[i];
|
||||
#endif
|
||||
key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);
|
||||
key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, opad_digest);
|
||||
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH/(int)sizeof(uint64_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
/* convert o_key_pad to i_key_pad and compute its digest */
|
||||
for (int i = 0; i < SHA512_BLOCK_LENGTH / (int)sizeof(uint64_t); i++) {
|
||||
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c5c5c5c5c ^ 0x3636363636363636;
|
||||
}
|
||||
sha512_Transform(sha512_initial_hash_value, key_pad, ipad_digest);
|
||||
memzero(key_pad, sizeof(key_pad));
|
||||
}
|
||||
|
32
hmac.h
32
hmac.h
@ -28,25 +28,33 @@
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _HMAC_SHA256_CTX {
|
||||
uint8_t o_key_pad[SHA256_BLOCK_LENGTH];
|
||||
SHA256_CTX ctx;
|
||||
uint8_t o_key_pad[SHA256_BLOCK_LENGTH];
|
||||
SHA256_CTX ctx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _HMAC_SHA512_CTX {
|
||||
uint8_t o_key_pad[SHA512_BLOCK_LENGTH];
|
||||
SHA512_CTX ctx;
|
||||
uint8_t o_key_pad[SHA512_BLOCK_LENGTH];
|
||||
SHA512_CTX ctx;
|
||||
} HMAC_SHA512_CTX;
|
||||
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t keylen);
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
|
||||
void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen);
|
||||
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen);
|
||||
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest);
|
||||
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint32_t *opad_digest, uint32_t *ipad_digest);
|
||||
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen);
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
|
||||
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key,
|
||||
const uint32_t keylen);
|
||||
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg,
|
||||
const uint32_t msglen);
|
||||
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest);
|
||||
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
|
||||
const uint32_t msglen, uint8_t *hmac);
|
||||
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen,
|
||||
uint64_t *opad_digest, uint64_t *ipad_digest);
|
||||
|
||||
#endif
|
||||
|
32
memzero.c
32
memzero.c
@ -1,5 +1,5 @@
|
||||
#ifndef __STDC_WANT_LIB_EXT1__
|
||||
#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface.
|
||||
#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface.
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
@ -18,12 +18,13 @@
|
||||
#endif
|
||||
|
||||
// GNU C Library version 2.25 or later.
|
||||
#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
|
||||
#if defined(__GLIBC__) && \
|
||||
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
// Newlib
|
||||
#if defined( __NEWLIB__)
|
||||
#if defined(__NEWLIB__)
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#endif
|
||||
|
||||
@ -42,25 +43,24 @@
|
||||
#define HAVE_EXPLICIT_MEMSET 1
|
||||
#endif
|
||||
|
||||
// Adapted from https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130
|
||||
// Adapted from
|
||||
// https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130
|
||||
|
||||
void memzero(void *const pnt, const size_t len)
|
||||
{
|
||||
void memzero(void *const pnt, const size_t len) {
|
||||
#ifdef _WIN32
|
||||
SecureZeroMemory(pnt, len);
|
||||
SecureZeroMemory(pnt, len);
|
||||
#elif defined(HAVE_MEMSET_S)
|
||||
memset_s(pnt, (rsize_t) len, 0, (rsize_t) len);
|
||||
memset_s(pnt, (rsize_t)len, 0, (rsize_t)len);
|
||||
#elif defined(HAVE_EXPLICIT_BZERO)
|
||||
explicit_bzero(pnt, len);
|
||||
explicit_bzero(pnt, len);
|
||||
#elif defined(HAVE_EXPLICIT_MEMSET)
|
||||
explicit_memset(pnt, 0, len);
|
||||
explicit_memset(pnt, 0, len);
|
||||
#else
|
||||
volatile unsigned char *volatile pnt_ =
|
||||
(volatile unsigned char *volatile) pnt;
|
||||
size_t i = (size_t) 0U;
|
||||
volatile unsigned char *volatile pnt_ = (volatile unsigned char *volatile)pnt;
|
||||
size_t i = (size_t)0U;
|
||||
|
||||
while (i < len) {
|
||||
pnt_[i++] = 0U;
|
||||
}
|
||||
while (i < len) {
|
||||
pnt_[i++] = 0U;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void memzero(void * const pnt, const size_t len);
|
||||
void memzero(void* const pnt, const size_t len);
|
||||
|
||||
#endif
|
||||
|
@ -14,8 +14,8 @@
|
||||
#endif
|
||||
|
||||
#include "base58.h"
|
||||
#include "range_proof.h"
|
||||
#include "serialize.h"
|
||||
#include "xmr.h"
|
||||
#include "range_proof.h"
|
||||
|
||||
#endif //TREZOR_CRYPTO_MONERO_H
|
||||
#endif // TREZOR_CRYPTO_MONERO_H
|
||||
|
@ -4,112 +4,112 @@
|
||||
|
||||
#include "range_proof.h"
|
||||
|
||||
|
||||
static void xmr_hash_ge25519_to_scalar(bignum256modm r, const ge25519 *p){
|
||||
unsigned char buff[32];
|
||||
ge25519_pack(buff, p);
|
||||
xmr_hash_to_scalar(r, buff, sizeof(buff));
|
||||
static void xmr_hash_ge25519_to_scalar(bignum256modm r, const ge25519 *p) {
|
||||
unsigned char buff[32];
|
||||
ge25519_pack(buff, p);
|
||||
xmr_hash_to_scalar(r, buff, sizeof(buff));
|
||||
}
|
||||
|
||||
void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask){
|
||||
bignum256modm ai[64];
|
||||
bignum256modm alpha[64];
|
||||
xmr_gen_range_sig_ex(sig, C, mask, amount, last_mask, ai, alpha);
|
||||
void xmr_gen_range_sig(xmr_range_sig_t *sig, ge25519 *C, bignum256modm mask,
|
||||
xmr_amount amount, bignum256modm *last_mask) {
|
||||
bignum256modm ai[64];
|
||||
bignum256modm alpha[64];
|
||||
xmr_gen_range_sig_ex(sig, C, mask, amount, last_mask, ai, alpha);
|
||||
}
|
||||
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask,
|
||||
bignum256modm ai[64], bignum256modm alpha[64])
|
||||
{
|
||||
const unsigned n = XMR_ATOMS;
|
||||
bignum256modm a={0};
|
||||
bignum256modm si={0};
|
||||
bignum256modm c={0};
|
||||
bignum256modm ee={0};
|
||||
unsigned char buff[32];
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t *sig, ge25519 *C, bignum256modm mask,
|
||||
xmr_amount amount, bignum256modm *last_mask,
|
||||
bignum256modm ai[64], bignum256modm alpha[64]) {
|
||||
const unsigned n = XMR_ATOMS;
|
||||
bignum256modm a = {0};
|
||||
bignum256modm si = {0};
|
||||
bignum256modm c = {0};
|
||||
bignum256modm ee = {0};
|
||||
unsigned char buff[32];
|
||||
|
||||
Hasher kck;
|
||||
xmr_hasher_init(&kck);
|
||||
Hasher kck;
|
||||
xmr_hasher_init(&kck);
|
||||
|
||||
ge25519 C_acc;
|
||||
ge25519 C_h;
|
||||
ge25519 C_tmp;
|
||||
ge25519 L;
|
||||
ge25519 Zero;
|
||||
ge25519 C_acc;
|
||||
ge25519 C_h;
|
||||
ge25519 C_tmp;
|
||||
ge25519 L;
|
||||
ge25519 Zero;
|
||||
|
||||
ge25519_set_neutral(&Zero);
|
||||
ge25519_set_neutral(&C_acc);
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
set256_modm(a, 0);
|
||||
ge25519_set_neutral(&Zero);
|
||||
ge25519_set_neutral(&C_acc);
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
set256_modm(a, 0);
|
||||
|
||||
#define BB(i) ((amount>>(i)) & 1)
|
||||
#define BB(i) ((amount >> (i)) & 1)
|
||||
|
||||
// First pass, generates: ai, alpha, Ci, ee, s1
|
||||
for(unsigned ii=0; ii<n; ++ii){
|
||||
xmr_random_scalar(ai[ii]);
|
||||
if (last_mask != NULL && ii == n - 1){
|
||||
sub256_modm(ai[ii], *last_mask, a);
|
||||
}
|
||||
// First pass, generates: ai, alpha, Ci, ee, s1
|
||||
for (unsigned ii = 0; ii < n; ++ii) {
|
||||
xmr_random_scalar(ai[ii]);
|
||||
if (last_mask != NULL && ii == n - 1) {
|
||||
sub256_modm(ai[ii], *last_mask, a);
|
||||
}
|
||||
|
||||
add256_modm(a, a, ai[ii]); // creating the total mask since you have to pass this to receiver...
|
||||
xmr_random_scalar(alpha[ii]);
|
||||
add256_modm(a, a, ai[ii]); // creating the total mask since you have to
|
||||
// pass this to receiver...
|
||||
xmr_random_scalar(alpha[ii]);
|
||||
|
||||
ge25519_scalarmult_base_niels(&L, ge25519_niels_base_multiples, alpha[ii]);
|
||||
ge25519_scalarmult_base_niels(&C_tmp, ge25519_niels_base_multiples, ai[ii]);
|
||||
ge25519_scalarmult_base_niels(&L, ge25519_niels_base_multiples, alpha[ii]);
|
||||
ge25519_scalarmult_base_niels(&C_tmp, ge25519_niels_base_multiples, ai[ii]);
|
||||
|
||||
// C_tmp += &Zero if BB(ii) == 0 else &C_h
|
||||
ge25519_add(&C_tmp, &C_tmp, BB(ii) == 0 ? &Zero : &C_h, 0);
|
||||
ge25519_add(&C_acc, &C_acc, &C_tmp, 0);
|
||||
// C_tmp += &Zero if BB(ii) == 0 else &C_h
|
||||
ge25519_add(&C_tmp, &C_tmp, BB(ii) == 0 ? &Zero : &C_h, 0);
|
||||
ge25519_add(&C_acc, &C_acc, &C_tmp, 0);
|
||||
|
||||
// Set Ci[ii] to sigs
|
||||
ge25519_pack(sig->Ci[ii], &C_tmp);
|
||||
// Set Ci[ii] to sigs
|
||||
ge25519_pack(sig->Ci[ii], &C_tmp);
|
||||
|
||||
if (BB(ii) == 0) {
|
||||
xmr_random_scalar(si);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
if (BB(ii) == 0) {
|
||||
xmr_random_scalar(si);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
|
||||
ge25519_add(&C_tmp, &C_tmp, &C_h, 1); // Ci[ii] -= c_h
|
||||
xmr_add_keys2_vartime(&L, si, c, &C_tmp);
|
||||
ge25519_add(&C_tmp, &C_tmp, &C_h, 1); // Ci[ii] -= c_h
|
||||
xmr_add_keys2_vartime(&L, si, c, &C_tmp);
|
||||
|
||||
// Set s1[ii] to sigs
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
// Set s1[ii] to sigs
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
|
||||
ge25519_pack(buff, &L);
|
||||
xmr_hasher_update(&kck, buff, sizeof(buff));
|
||||
ge25519_pack(buff, &L);
|
||||
xmr_hasher_update(&kck, buff, sizeof(buff));
|
||||
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
|
||||
// Compute ee
|
||||
xmr_hasher_final(&kck, buff);
|
||||
expand256_modm(ee, buff, sizeof(buff));
|
||||
// Compute ee
|
||||
xmr_hasher_final(&kck, buff);
|
||||
expand256_modm(ee, buff, sizeof(buff));
|
||||
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
|
||||
// Second pass, s0, s1
|
||||
for(unsigned ii=0; ii<n; ++ii){
|
||||
if (BB(ii) == 0){
|
||||
mulsub256_modm(si, ai[ii], ee, alpha[ii]);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
// Second pass, s0, s1
|
||||
for (unsigned ii = 0; ii < n; ++ii) {
|
||||
if (BB(ii) == 0) {
|
||||
mulsub256_modm(si, ai[ii], ee, alpha[ii]);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
|
||||
} else {
|
||||
xmr_random_scalar(si);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
} else {
|
||||
xmr_random_scalar(si);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
|
||||
ge25519_unpack_vartime(&C_tmp, sig->Ci[ii]);
|
||||
xmr_add_keys2_vartime(&L, si, ee, &C_tmp);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
ge25519_unpack_vartime(&C_tmp, sig->Ci[ii]);
|
||||
xmr_add_keys2_vartime(&L, si, ee, &C_tmp);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
|
||||
mulsub256_modm(si, ai[ii], c, alpha[ii]);
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
mulsub256_modm(si, ai[ii], c, alpha[ii]);
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
|
||||
ge25519_copy(C, &C_acc);
|
||||
copy256_modm(mask, a);
|
||||
contract256_modm(sig->asig.ee, ee);
|
||||
ge25519_copy(C, &C_acc);
|
||||
copy256_modm(mask, a);
|
||||
contract256_modm(sig->asig.ee, ee);
|
||||
#undef BB
|
||||
}
|
||||
|
||||
|
@ -12,19 +12,20 @@ typedef uint64_t xmr_amount;
|
||||
typedef xmr_key_t xmr_key64_t[64];
|
||||
|
||||
typedef struct xmr_boro_sig {
|
||||
xmr_key64_t s0;
|
||||
xmr_key64_t s1;
|
||||
xmr_key_t ee;
|
||||
xmr_key64_t s0;
|
||||
xmr_key64_t s1;
|
||||
xmr_key_t ee;
|
||||
} xmr_boro_sig_t;
|
||||
|
||||
typedef struct range_sig {
|
||||
xmr_boro_sig_t asig;
|
||||
xmr_key64_t Ci;
|
||||
xmr_boro_sig_t asig;
|
||||
xmr_key64_t Ci;
|
||||
} xmr_range_sig_t;
|
||||
|
||||
|
||||
void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask);
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask,
|
||||
void xmr_gen_range_sig(xmr_range_sig_t* sig, ge25519* C, bignum256modm mask,
|
||||
xmr_amount amount, bignum256modm* last_mask);
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t* sig, ge25519* C, bignum256modm mask,
|
||||
xmr_amount amount, bignum256modm* last_mask,
|
||||
bignum256modm ai[64], bignum256modm alpha[64]);
|
||||
|
||||
#endif //TREZOR_CRYPTO_RANGE_PROOF_H
|
||||
#endif // TREZOR_CRYPTO_RANGE_PROOF_H
|
||||
|
@ -4,51 +4,50 @@
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
int xmr_size_varint(uint64_t num){
|
||||
int ctr = 1;
|
||||
while (num >= 0x80) {
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
return ctr;
|
||||
int xmr_size_varint(uint64_t num) {
|
||||
int ctr = 1;
|
||||
while (num >= 0x80) {
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
|
||||
int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num){
|
||||
unsigned ctr = 0;
|
||||
while (num >= 0x80 && ctr < buff_size) {
|
||||
*buff = (uint8_t) (((num) & 0x7f) | 0x80);
|
||||
++buff;
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
int xmr_write_varint(uint8_t *buff, size_t buff_size, uint64_t num) {
|
||||
unsigned ctr = 0;
|
||||
while (num >= 0x80 && ctr < buff_size) {
|
||||
*buff = (uint8_t)(((num)&0x7f) | 0x80);
|
||||
++buff;
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
|
||||
/* writes the last one to dest */
|
||||
if (ctr < buff_size) {
|
||||
*buff = (uint8_t) num;
|
||||
++ctr;
|
||||
}
|
||||
return ctr <= buff_size ? (int)ctr : -1;
|
||||
/* writes the last one to dest */
|
||||
if (ctr < buff_size) {
|
||||
*buff = (uint8_t)num;
|
||||
++ctr;
|
||||
}
|
||||
return ctr <= buff_size ? (int)ctr : -1;
|
||||
}
|
||||
|
||||
int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val) {
|
||||
unsigned read = 0;
|
||||
int finished_ok = 0;
|
||||
*val = 0;
|
||||
int xmr_read_varint(uint8_t *buff, size_t buff_size, uint64_t *val) {
|
||||
unsigned read = 0;
|
||||
int finished_ok = 0;
|
||||
*val = 0;
|
||||
|
||||
for (int shift = 0; read < buff_size; shift += 7, ++read) {
|
||||
uint8_t byte = buff[read];
|
||||
if (byte == 0 && shift != 0) {
|
||||
return -1;
|
||||
}
|
||||
for (int shift = 0; read < buff_size; shift += 7, ++read) {
|
||||
uint8_t byte = buff[read];
|
||||
if (byte == 0 && shift != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*val |= (uint64_t)(byte & 0x7f) << shift;
|
||||
*val |= (uint64_t)(byte & 0x7f) << shift;
|
||||
|
||||
/* If there is no next */
|
||||
if ((byte & 0x80) == 0) {
|
||||
finished_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return finished_ok ? (int)read + 1 : -2;
|
||||
/* If there is no next */
|
||||
if ((byte & 0x80) == 0) {
|
||||
finished_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return finished_ok ? (int)read + 1 : -2;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
int xmr_size_varint(uint64_t num);
|
||||
int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num);
|
||||
int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val);
|
||||
int xmr_write_varint(uint8_t *buff, size_t buff_size, uint64_t num);
|
||||
int xmr_read_varint(uint8_t *buff, size_t buff_size, uint64_t *val);
|
||||
|
||||
#endif //TREZOR_XMR_SERIALIZE_H
|
||||
#endif // TREZOR_XMR_SERIALIZE_H
|
||||
|
191
monero/xmr.c
191
monero/xmr.c
@ -4,133 +4,140 @@
|
||||
|
||||
#include "xmr.h"
|
||||
#include "int-util.h"
|
||||
#include "serialize.h"
|
||||
#include "rand.h"
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
const ge25519 ALIGN(16) xmr_h = {
|
||||
{0x1861ec7, 0x1ceac77, 0x2f11626, 0x1f261d3, 0x346107c, 0x06d8c4a, 0x254201d, 0x1675c09, 0x1301c3f, 0x0211d73},
|
||||
{0x326feb4, 0x12e30cc, 0x0cf54b4, 0x1117305, 0x318f5d5, 0x06cf754, 0x2e578a1, 0x1daf058, 0x34430a1, 0x04410e9},
|
||||
{0x0fde4d2, 0x0774049, 0x22ca951, 0x05aec2b, 0x07a36a5, 0x1394f13, 0x3c5385c, 0x1adb924, 0x2b6c581, 0x0a55fa4},
|
||||
{0x24517f7, 0x05ee936, 0x3acf5d9, 0x14b08aa, 0x3363738, 0x1051745, 0x360601e, 0x0f3f2c9, 0x1ead2cd, 0x1d3e3df}
|
||||
};
|
||||
{0x1861ec7, 0x1ceac77, 0x2f11626, 0x1f261d3, 0x346107c, 0x06d8c4a,
|
||||
0x254201d, 0x1675c09, 0x1301c3f, 0x0211d73},
|
||||
{0x326feb4, 0x12e30cc, 0x0cf54b4, 0x1117305, 0x318f5d5, 0x06cf754,
|
||||
0x2e578a1, 0x1daf058, 0x34430a1, 0x04410e9},
|
||||
{0x0fde4d2, 0x0774049, 0x22ca951, 0x05aec2b, 0x07a36a5, 0x1394f13,
|
||||
0x3c5385c, 0x1adb924, 0x2b6c581, 0x0a55fa4},
|
||||
{0x24517f7, 0x05ee936, 0x3acf5d9, 0x14b08aa, 0x3363738, 0x1051745,
|
||||
0x360601e, 0x0f3f2c9, 0x1ead2cd, 0x1d3e3df}};
|
||||
|
||||
void ge25519_set_xmr_h(ge25519 *r) { ge25519_copy(r, &xmr_h); }
|
||||
|
||||
void ge25519_set_xmr_h(ge25519 *r){
|
||||
ge25519_copy(r, &xmr_h);
|
||||
void xmr_random_scalar(bignum256modm m) {
|
||||
unsigned char buff[32] = {0};
|
||||
random_buffer(buff, sizeof(buff));
|
||||
expand256_modm(m, buff, sizeof(buff));
|
||||
}
|
||||
|
||||
void xmr_random_scalar(bignum256modm m){
|
||||
unsigned char buff[32]={0};
|
||||
random_buffer(buff, sizeof(buff));
|
||||
expand256_modm(m, buff, sizeof(buff));
|
||||
void xmr_fast_hash(uint8_t *hash, const void *data, size_t length) {
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
}
|
||||
|
||||
void xmr_fast_hash(uint8_t * hash, const void *data, size_t length){
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
void xmr_hasher_init(Hasher *hasher) { hasher_Init(hasher, HASHER_SHA3K); }
|
||||
|
||||
void xmr_hasher_update(Hasher *hasher, const void *data, size_t length) {
|
||||
hasher_Update(hasher, data, length);
|
||||
}
|
||||
|
||||
void xmr_hasher_init(Hasher * hasher){
|
||||
hasher_Init(hasher, HASHER_SHA3K);
|
||||
void xmr_hasher_final(Hasher *hasher, uint8_t *hash) {
|
||||
hasher_Final(hasher, hash);
|
||||
}
|
||||
|
||||
void xmr_hasher_update(Hasher * hasher, const void *data, size_t length){
|
||||
hasher_Update(hasher, data, length);
|
||||
void xmr_hasher_copy(Hasher *dst, const Hasher *src) {
|
||||
memcpy(dst, src, sizeof(Hasher));
|
||||
}
|
||||
|
||||
void xmr_hasher_final(Hasher * hasher, uint8_t * hash){
|
||||
hasher_Final(hasher, hash);
|
||||
void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length) {
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
expand256_modm(r, hash, HASHER_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
void xmr_hasher_copy(Hasher * dst, const Hasher * src){
|
||||
memcpy(dst, src, sizeof(Hasher));
|
||||
void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length) {
|
||||
ge25519 point2;
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
|
||||
ge25519_fromfe_frombytes_vartime(&point2, hash);
|
||||
ge25519_mul8(P, &point2);
|
||||
}
|
||||
|
||||
void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length){
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
expand256_modm(r, hash, HASHER_DIGEST_LENGTH);
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 *p,
|
||||
uint32_t output_index) {
|
||||
uint8_t buff[32 + 8];
|
||||
ge25519_pack(buff, p);
|
||||
int written = xmr_write_varint(buff + 32, 8, output_index);
|
||||
xmr_hash_to_scalar(s, buff, 32u + written);
|
||||
}
|
||||
|
||||
void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length){
|
||||
ge25519 point2;
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
|
||||
ge25519_fromfe_frombytes_vartime(&point2, hash);
|
||||
ge25519_mul8(P, &point2);
|
||||
void xmr_generate_key_derivation(ge25519 *r, const ge25519 *A,
|
||||
const bignum256modm b) {
|
||||
ge25519 bA;
|
||||
ge25519_scalarmult(&bA, A, b);
|
||||
ge25519_mul8(r, &bA);
|
||||
}
|
||||
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index){
|
||||
uint8_t buff[32 + 8];
|
||||
ge25519_pack(buff, p);
|
||||
int written = xmr_write_varint(buff + 32, 8, output_index);
|
||||
xmr_hash_to_scalar(s, buff, 32u + written);
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 *deriv, uint32_t idx,
|
||||
const bignum256modm base) {
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
add256_modm(s, s, base);
|
||||
}
|
||||
|
||||
void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b){
|
||||
ge25519 bA;
|
||||
ge25519_scalarmult(&bA, A, b);
|
||||
ge25519_mul8(r, &bA);
|
||||
void xmr_derive_public_key(ge25519 *r, const ge25519 *deriv, uint32_t idx,
|
||||
const ge25519 *base) {
|
||||
bignum256modm s = {0};
|
||||
ge25519 p2;
|
||||
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
ge25519_scalarmult_base_niels(&p2, ge25519_niels_base_multiples, s);
|
||||
ge25519_add(r, base, &p2, 0);
|
||||
}
|
||||
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base){
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
add256_modm(s, s, base);
|
||||
void xmr_add_keys2(ge25519 *r, const bignum256modm a, const bignum256modm b,
|
||||
const ge25519 *B) {
|
||||
// aG + bB, G is basepoint
|
||||
ge25519 aG, bB;
|
||||
ge25519_scalarmult_base_niels(&aG, ge25519_niels_base_multiples, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_add(r, &aG, &bB, 0);
|
||||
}
|
||||
|
||||
void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base){
|
||||
bignum256modm s={0};
|
||||
ge25519 p2;
|
||||
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
ge25519_scalarmult_base_niels(&p2, ge25519_niels_base_multiples, s);
|
||||
ge25519_add(r, base, &p2, 0);
|
||||
void xmr_add_keys2_vartime(ge25519 *r, const bignum256modm a,
|
||||
const bignum256modm b, const ge25519 *B) {
|
||||
// aG + bB, G is basepoint
|
||||
ge25519_double_scalarmult_vartime(r, B, b, a);
|
||||
}
|
||||
|
||||
void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){
|
||||
// aG + bB, G is basepoint
|
||||
ge25519 aG, bB;
|
||||
ge25519_scalarmult_base_niels(&aG, ge25519_niels_base_multiples, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_add(r, &aG, &bB, 0);
|
||||
void xmr_add_keys3(ge25519 *r, const bignum256modm a, const ge25519 *A,
|
||||
const bignum256modm b, const ge25519 *B) {
|
||||
// aA + bB
|
||||
ge25519 aA, bB;
|
||||
ge25519_scalarmult(&aA, A, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_add(r, &aA, &bB, 0);
|
||||
}
|
||||
|
||||
void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){
|
||||
// aG + bB, G is basepoint
|
||||
ge25519_double_scalarmult_vartime(r, B, b, a);
|
||||
void xmr_add_keys3_vartime(ge25519 *r, const bignum256modm a, const ge25519 *A,
|
||||
const bignum256modm b, const ge25519 *B) {
|
||||
// aA + bB
|
||||
ge25519_double_scalarmult_vartime2(r, A, a, B, b);
|
||||
}
|
||||
|
||||
void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){
|
||||
// aA + bB
|
||||
ge25519 aA, bB;
|
||||
ge25519_scalarmult(&aA, A, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_add(r, &aA, &bB, 0);
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major,
|
||||
uint32_t minor, const bignum256modm m) {
|
||||
const char prefix[] = "SubAddr";
|
||||
unsigned char buff[32];
|
||||
contract256_modm(buff, m);
|
||||
|
||||
char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)];
|
||||
memcpy(data, prefix, sizeof(prefix));
|
||||
memcpy(data + sizeof(prefix), buff, sizeof(buff));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor,
|
||||
sizeof(uint32_t));
|
||||
|
||||
xmr_hash_to_scalar(r, data, sizeof(data));
|
||||
}
|
||||
|
||||
void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){
|
||||
// aA + bB
|
||||
ge25519_double_scalarmult_vartime2(r, A, a, B, b);
|
||||
}
|
||||
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m){
|
||||
const char prefix[] = "SubAddr";
|
||||
unsigned char buff[32];
|
||||
contract256_modm(buff, m);
|
||||
|
||||
char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)];
|
||||
memcpy(data, prefix, sizeof(prefix));
|
||||
memcpy(data + sizeof(prefix), buff, sizeof(buff));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor, sizeof(uint32_t));
|
||||
|
||||
xmr_hash_to_scalar(r, data, sizeof(data));
|
||||
}
|
||||
|
||||
void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount){
|
||||
// C = aG + bH
|
||||
bignum256modm b={0};
|
||||
set256_modm(b, amount);
|
||||
xmr_add_keys2(r, a, b, &xmr_h);
|
||||
void xmr_gen_c(ge25519 *r, const bignum256modm a, uint64_t amount) {
|
||||
// C = aG + bH
|
||||
bignum256modm b = {0};
|
||||
set256_modm(b, amount);
|
||||
xmr_add_keys2(r, a, b, &xmr_h);
|
||||
}
|
||||
|
41
monero/xmr.h
41
monero/xmr.h
@ -24,13 +24,13 @@ void ge25519_set_xmr_h(ge25519 *r);
|
||||
void xmr_random_scalar(bignum256modm m);
|
||||
|
||||
/* cn_fast_hash */
|
||||
void xmr_fast_hash(uint8_t * hash, const void *data, size_t length);
|
||||
void xmr_fast_hash(uint8_t *hash, const void *data, size_t length);
|
||||
|
||||
/* incremental hashing wrappers */
|
||||
void xmr_hasher_init(Hasher * hasher);
|
||||
void xmr_hasher_update(Hasher * hasher, const void *data, size_t length);
|
||||
void xmr_hasher_final(Hasher * hasher, uint8_t * hash);
|
||||
void xmr_hasher_copy(Hasher * dst, const Hasher * src);
|
||||
void xmr_hasher_init(Hasher *hasher);
|
||||
void xmr_hasher_update(Hasher *hasher, const void *data, size_t length);
|
||||
void xmr_hasher_final(Hasher *hasher, uint8_t *hash);
|
||||
void xmr_hasher_copy(Hasher *dst, const Hasher *src);
|
||||
|
||||
/* H_s(buffer) */
|
||||
void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length);
|
||||
@ -39,29 +39,38 @@ void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length);
|
||||
void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length);
|
||||
|
||||
/* derivation to scalar value */
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index);
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 *p,
|
||||
uint32_t output_index);
|
||||
|
||||
/* derivation */
|
||||
void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b);
|
||||
void xmr_generate_key_derivation(ge25519 *r, const ge25519 *A,
|
||||
const bignum256modm b);
|
||||
|
||||
/* H_s(derivation || varint(output_index)) + base */
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base);
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 *deriv, uint32_t idx,
|
||||
const bignum256modm base);
|
||||
|
||||
/* H_s(derivation || varint(output_index))G + base */
|
||||
void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base);
|
||||
void xmr_derive_public_key(ge25519 *r, const ge25519 *deriv, uint32_t idx,
|
||||
const ge25519 *base);
|
||||
|
||||
/* aG + bB, G is basepoint */
|
||||
void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys2(ge25519 *r, const bignum256modm a, const bignum256modm b,
|
||||
const ge25519 *B);
|
||||
void xmr_add_keys2_vartime(ge25519 *r, const bignum256modm a,
|
||||
const bignum256modm b, const ge25519 *B);
|
||||
|
||||
/* aA + bB */
|
||||
void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys3(ge25519 *r, const bignum256modm a, const ge25519 *A,
|
||||
const bignum256modm b, const ge25519 *B);
|
||||
void xmr_add_keys3_vartime(ge25519 *r, const bignum256modm a, const ge25519 *A,
|
||||
const bignum256modm b, const ge25519 *B);
|
||||
|
||||
/* subaddress secret */
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m);
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major,
|
||||
uint32_t minor, const bignum256modm m);
|
||||
|
||||
/* Generates Pedersen commitment C = aG + bH */
|
||||
void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount);
|
||||
void xmr_gen_c(ge25519 *r, const bignum256modm a, uint64_t amount);
|
||||
|
||||
#endif //TREZOR_CRYPTO_XMR_H
|
||||
#endif // TREZOR_CRYPTO_XMR_H
|
||||
|
757
nem.c
757
nem.c
@ -26,544 +26,483 @@
|
||||
|
||||
#include "base32.h"
|
||||
#include "ed25519-donna/ed25519-keccak.h"
|
||||
#include "memzero.h"
|
||||
#include "ripemd160.h"
|
||||
#include "sha3.h"
|
||||
#include "memzero.h"
|
||||
|
||||
#define CAN_WRITE(NEEDED) ((ctx->offset + (NEEDED)) <= ctx->size)
|
||||
|
||||
#define SERIALIZE_U32(DATA) \
|
||||
do { if (!nem_write_u32(ctx, (DATA))) return false; } while (0)
|
||||
#define SERIALIZE_U64(DATA) \
|
||||
do { if (!nem_write_u64(ctx, (DATA))) return false; } while (0)
|
||||
#define SERIALIZE_TAGGED(DATA, LENGTH) \
|
||||
do { if (!nem_write_tagged(ctx, (DATA), (LENGTH))) return false; } while (0)
|
||||
|
||||
#define SERIALIZE_U32(DATA) \
|
||||
do { \
|
||||
if (!nem_write_u32(ctx, (DATA))) return false; \
|
||||
} while (0)
|
||||
#define SERIALIZE_U64(DATA) \
|
||||
do { \
|
||||
if (!nem_write_u64(ctx, (DATA))) return false; \
|
||||
} while (0)
|
||||
#define SERIALIZE_TAGGED(DATA, LENGTH) \
|
||||
do { \
|
||||
if (!nem_write_tagged(ctx, (DATA), (LENGTH))) return false; \
|
||||
} while (0)
|
||||
|
||||
const char *nem_network_name(uint8_t network) {
|
||||
switch (network) {
|
||||
case NEM_NETWORK_MAINNET:
|
||||
return "NEM Mainnet";
|
||||
case NEM_NETWORK_TESTNET:
|
||||
return "NEM Testnet";
|
||||
case NEM_NETWORK_MIJIN:
|
||||
return "Mijin";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
switch (network) {
|
||||
case NEM_NETWORK_MAINNET:
|
||||
return "NEM Mainnet";
|
||||
case NEM_NETWORK_TESTNET:
|
||||
return "NEM Testnet";
|
||||
case NEM_NETWORK_MIJIN:
|
||||
return "Mijin";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool nem_write_checked(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) {
|
||||
if (!CAN_WRITE(length)) {
|
||||
return false;
|
||||
}
|
||||
static inline bool nem_write_checked(nem_transaction_ctx *ctx,
|
||||
const uint8_t *data, uint32_t length) {
|
||||
if (!CAN_WRITE(length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[ctx->offset], data, length);
|
||||
ctx->offset += length;
|
||||
return true;
|
||||
memcpy(&ctx->buffer[ctx->offset], data, length);
|
||||
ctx->offset += length;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool nem_write_u32(nem_transaction_ctx *ctx, uint32_t data) {
|
||||
if (!CAN_WRITE(4)) {
|
||||
return false;
|
||||
}
|
||||
if (!CAN_WRITE(4)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->buffer[ctx->offset++] = (data >> 0) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 8) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 16) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 24) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 0) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 8) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 16) & 0xff;
|
||||
ctx->buffer[ctx->offset++] = (data >> 24) & 0xff;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool nem_write_u64(nem_transaction_ctx *ctx, uint64_t data) {
|
||||
SERIALIZE_U32((data >> 0) & 0xffffffff);
|
||||
SERIALIZE_U32((data >> 32) & 0xffffffff);
|
||||
SERIALIZE_U32((data >> 0) & 0xffffffff);
|
||||
SERIALIZE_U32((data >> 32) & 0xffffffff);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool nem_write_tagged(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) {
|
||||
SERIALIZE_U32(length);
|
||||
static inline bool nem_write_tagged(nem_transaction_ctx *ctx,
|
||||
const uint8_t *data, uint32_t length) {
|
||||
SERIALIZE_U32(length);
|
||||
|
||||
return nem_write_checked(ctx, data, length);
|
||||
return nem_write_checked(ctx, data, length);
|
||||
}
|
||||
|
||||
static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx, const char *name, const char *value) {
|
||||
uint32_t name_length = strlen(name);
|
||||
uint32_t value_length = strlen(value);
|
||||
static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx,
|
||||
const char *name, const char *value) {
|
||||
uint32_t name_length = strlen(name);
|
||||
uint32_t value_length = strlen(value);
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t) + name_length + sizeof(uint32_t) + value_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) name, name_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) value, value_length);
|
||||
SERIALIZE_U32(sizeof(uint32_t) + name_length + sizeof(uint32_t) +
|
||||
value_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)name, name_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)value, value_length);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool nem_write_mosaic_bool(nem_transaction_ctx *ctx, const char *name, bool value) {
|
||||
return nem_write_mosaic_str(ctx, name, value ? "true" : "false");
|
||||
static inline bool nem_write_mosaic_bool(nem_transaction_ctx *ctx,
|
||||
const char *name, bool value) {
|
||||
return nem_write_mosaic_str(ctx, name, value ? "true" : "false");
|
||||
}
|
||||
|
||||
static inline bool nem_write_mosaic_u64(nem_transaction_ctx *ctx, const char *name, uint64_t value) {
|
||||
char buffer[21];
|
||||
static inline bool nem_write_mosaic_u64(nem_transaction_ctx *ctx,
|
||||
const char *name, uint64_t value) {
|
||||
char buffer[21];
|
||||
|
||||
if (bn_format_uint64(value, NULL, NULL, 0, 0, false, buffer, sizeof(buffer)) == 0) {
|
||||
return false;
|
||||
}
|
||||
if (bn_format_uint64(value, NULL, NULL, 0, 0, false, buffer,
|
||||
sizeof(buffer)) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return nem_write_mosaic_str(ctx, name, buffer);
|
||||
return nem_write_mosaic_str(ctx, name, buffer);
|
||||
}
|
||||
|
||||
void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, uint8_t *address) {
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version,
|
||||
uint8_t *address) {
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
|
||||
/* 1. Perform 256-bit Sha3 on the public key */
|
||||
keccak_256(public_key, sizeof(ed25519_public_key), hash);
|
||||
/* 1. Perform 256-bit Sha3 on the public key */
|
||||
keccak_256(public_key, sizeof(ed25519_public_key), hash);
|
||||
|
||||
/* 2. Perform 160-bit Ripemd of hash resulting from step 1. */
|
||||
ripemd160(hash, SHA3_256_DIGEST_LENGTH, &address[1]);
|
||||
/* 2. Perform 160-bit Ripemd of hash resulting from step 1. */
|
||||
ripemd160(hash, SHA3_256_DIGEST_LENGTH, &address[1]);
|
||||
|
||||
/* 3. Prepend version byte to Ripemd hash (either 0x68 or 0x98) */
|
||||
address[0] = version;
|
||||
/* 3. Prepend version byte to Ripemd hash (either 0x68 or 0x98) */
|
||||
address[0] = version;
|
||||
|
||||
/* 4. Perform 256-bit Sha3 on the result, take the first four bytes as a checksum */
|
||||
keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash);
|
||||
/* 4. Perform 256-bit Sha3 on the result, take the first four bytes as a
|
||||
* checksum */
|
||||
keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash);
|
||||
|
||||
/* 5. Concatenate output of step 3 and the checksum from step 4 */
|
||||
memcpy(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4);
|
||||
/* 5. Concatenate output of step 3 and the checksum from step 4 */
|
||||
memcpy(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4);
|
||||
|
||||
memzero(hash, sizeof(hash));
|
||||
memzero(hash, sizeof(hash));
|
||||
}
|
||||
|
||||
bool nem_get_address(const ed25519_public_key public_key, uint8_t version, char *address) {
|
||||
uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW];
|
||||
bool nem_get_address(const ed25519_public_key public_key, uint8_t version,
|
||||
char *address) {
|
||||
uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW];
|
||||
|
||||
nem_get_address_raw(public_key, version, pubkeyhash);
|
||||
nem_get_address_raw(public_key, version, pubkeyhash);
|
||||
|
||||
char *ret = base32_encode(pubkeyhash, sizeof(pubkeyhash), address, NEM_ADDRESS_SIZE + 1, BASE32_ALPHABET_RFC4648);
|
||||
char *ret = base32_encode(pubkeyhash, sizeof(pubkeyhash), address,
|
||||
NEM_ADDRESS_SIZE + 1, BASE32_ALPHABET_RFC4648);
|
||||
|
||||
memzero(pubkeyhash, sizeof(pubkeyhash));
|
||||
return (ret != NULL);
|
||||
memzero(pubkeyhash, sizeof(pubkeyhash));
|
||||
return (ret != NULL);
|
||||
}
|
||||
|
||||
bool nem_validate_address_raw(const uint8_t *address, uint8_t network) {
|
||||
if (!nem_network_name(network) || address[0] != network) {
|
||||
return false;
|
||||
}
|
||||
if (!nem_network_name(network) || address[0] != network) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
|
||||
keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash);
|
||||
bool valid = (memcmp(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4) == 0);
|
||||
keccak_256(address, 1 + RIPEMD160_DIGEST_LENGTH, hash);
|
||||
bool valid = (memcmp(&address[1 + RIPEMD160_DIGEST_LENGTH], hash, 4) == 0);
|
||||
|
||||
memzero(hash, sizeof(hash));
|
||||
return valid;
|
||||
memzero(hash, sizeof(hash));
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool nem_validate_address(const char *address, uint8_t network) {
|
||||
uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW];
|
||||
uint8_t pubkeyhash[NEM_ADDRESS_SIZE_RAW];
|
||||
|
||||
if (strlen(address) != NEM_ADDRESS_SIZE) {
|
||||
return false;
|
||||
}
|
||||
if (strlen(address) != NEM_ADDRESS_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t *ret = base32_decode(address, NEM_ADDRESS_SIZE, pubkeyhash, sizeof(pubkeyhash), BASE32_ALPHABET_RFC4648);
|
||||
bool valid = (ret != NULL) && nem_validate_address_raw(pubkeyhash, network);
|
||||
uint8_t *ret = base32_decode(address, NEM_ADDRESS_SIZE, pubkeyhash,
|
||||
sizeof(pubkeyhash), BASE32_ALPHABET_RFC4648);
|
||||
bool valid = (ret != NULL) && nem_validate_address_raw(pubkeyhash, network);
|
||||
|
||||
memzero(pubkeyhash, sizeof(pubkeyhash));
|
||||
return valid;
|
||||
memzero(pubkeyhash, sizeof(pubkeyhash));
|
||||
return valid;
|
||||
}
|
||||
|
||||
void nem_transaction_start(nem_transaction_ctx *ctx, const ed25519_public_key public_key, uint8_t *buffer, size_t size) {
|
||||
memcpy(ctx->public_key, public_key, sizeof(ctx->public_key));
|
||||
void nem_transaction_start(nem_transaction_ctx *ctx,
|
||||
const ed25519_public_key public_key, uint8_t *buffer,
|
||||
size_t size) {
|
||||
memcpy(ctx->public_key, public_key, sizeof(ctx->public_key));
|
||||
|
||||
ctx->buffer = buffer;
|
||||
ctx->offset = 0;
|
||||
ctx->size = size;
|
||||
ctx->buffer = buffer;
|
||||
ctx->offset = 0;
|
||||
ctx->size = size;
|
||||
}
|
||||
|
||||
size_t nem_transaction_end(nem_transaction_ctx *ctx, const ed25519_secret_key private_key, ed25519_signature signature) {
|
||||
if (private_key != NULL && signature != NULL) {
|
||||
ed25519_sign_keccak(ctx->buffer, ctx->offset, private_key, ctx->public_key, signature);
|
||||
}
|
||||
size_t nem_transaction_end(nem_transaction_ctx *ctx,
|
||||
const ed25519_secret_key private_key,
|
||||
ed25519_signature signature) {
|
||||
if (private_key != NULL && signature != NULL) {
|
||||
ed25519_sign_keccak(ctx->buffer, ctx->offset, private_key, ctx->public_key,
|
||||
signature);
|
||||
}
|
||||
|
||||
return ctx->offset;
|
||||
return ctx->offset;
|
||||
}
|
||||
|
||||
bool nem_transaction_write_common(nem_transaction_ctx *ctx,
|
||||
uint32_t type,
|
||||
uint32_t version,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline) {
|
||||
bool nem_transaction_write_common(nem_transaction_ctx *ctx, uint32_t type,
|
||||
uint32_t version, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee,
|
||||
uint32_t deadline) {
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_U32(version);
|
||||
SERIALIZE_U32(timestamp);
|
||||
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||
SERIALIZE_U64(fee);
|
||||
SERIALIZE_U32(deadline);
|
||||
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_U32(version);
|
||||
SERIALIZE_U32(timestamp);
|
||||
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||
SERIALIZE_U64(fee);
|
||||
SERIALIZE_U32(deadline);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_transfer(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *recipient,
|
||||
uint64_t amount,
|
||||
const uint8_t *payload,
|
||||
uint32_t length,
|
||||
bool encrypted,
|
||||
uint32_t mosaics) {
|
||||
bool nem_transaction_create_transfer(nem_transaction_ctx *ctx, uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee, uint32_t deadline,
|
||||
const char *recipient, uint64_t amount,
|
||||
const uint8_t *payload, uint32_t length,
|
||||
bool encrypted, uint32_t mosaics) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
if (!payload) {
|
||||
length = 0;
|
||||
}
|
||||
|
||||
if (!payload) {
|
||||
length = 0;
|
||||
}
|
||||
bool ret =
|
||||
nem_transaction_write_common(ctx, NEM_TRANSACTION_TYPE_TRANSFER,
|
||||
(uint32_t)network << 24 | (mosaics ? 2 : 1),
|
||||
timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_TRANSFER,
|
||||
(uint32_t) network << 24 | (mosaics ? 2 : 1),
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
SERIALIZE_TAGGED((const uint8_t *)recipient, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(amount);
|
||||
|
||||
SERIALIZE_TAGGED((const uint8_t *) recipient, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(amount);
|
||||
if (length) {
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + length);
|
||||
SERIALIZE_U32(encrypted ? 0x02 : 0x01);
|
||||
SERIALIZE_TAGGED(payload, length);
|
||||
} else {
|
||||
SERIALIZE_U32(0);
|
||||
}
|
||||
|
||||
if (length) {
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + length);
|
||||
SERIALIZE_U32(encrypted ? 0x02 : 0x01);
|
||||
SERIALIZE_TAGGED(payload, length);
|
||||
} else {
|
||||
SERIALIZE_U32(0);
|
||||
}
|
||||
if (mosaics) {
|
||||
SERIALIZE_U32(mosaics);
|
||||
}
|
||||
|
||||
if (mosaics) {
|
||||
|
||||
SERIALIZE_U32(mosaics);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_write_mosaic(nem_transaction_ctx *ctx,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
uint64_t quantity) {
|
||||
const char *namespace, const char *mosaic,
|
||||
uint64_t quantity) {
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length =
|
||||
sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length);
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length);
|
||||
SERIALIZE_U64(quantity);
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length);
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||
SERIALIZE_U64(quantity);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_multisig(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const nem_transaction_ctx *inner) {
|
||||
bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee, uint32_t deadline,
|
||||
const nem_transaction_ctx *inner) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(ctx, NEM_TRANSACTION_TYPE_MULTISIG,
|
||||
(uint32_t)network << 24 | 1,
|
||||
timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_MULTISIG,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
SERIALIZE_TAGGED(inner->buffer, inner->offset);
|
||||
|
||||
SERIALIZE_TAGGED(inner->buffer, inner->offset);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_multisig_signature(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const nem_transaction_ctx *inner) {
|
||||
bool nem_transaction_create_multisig_signature(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const nem_transaction_ctx *inner) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE, (uint32_t)network << 24 | 1,
|
||||
timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
char address[NEM_ADDRESS_SIZE + 1];
|
||||
nem_get_address(inner->public_key, network, address);
|
||||
|
||||
char address[NEM_ADDRESS_SIZE + 1];
|
||||
nem_get_address(inner->public_key, network, address);
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
keccak_256(inner->buffer, inner->offset, hash);
|
||||
|
||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||
keccak_256(inner->buffer, inner->offset, hash);
|
||||
SERIALIZE_U32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH);
|
||||
SERIALIZE_TAGGED(hash, SHA3_256_DIGEST_LENGTH);
|
||||
SERIALIZE_TAGGED((const uint8_t *)address, NEM_ADDRESS_SIZE);
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH);
|
||||
SERIALIZE_TAGGED(hash, SHA3_256_DIGEST_LENGTH);
|
||||
SERIALIZE_TAGGED((const uint8_t *) address, NEM_ADDRESS_SIZE);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_provision_namespace(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *parent,
|
||||
const char *rental_sink,
|
||||
uint64_t rental_fee) {
|
||||
bool nem_transaction_create_provision_namespace(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *parent, const char *rental_sink,
|
||||
uint64_t rental_fee) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE,
|
||||
(uint32_t)network << 24 | 1, timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
if (parent) {
|
||||
SERIALIZE_TAGGED((const uint8_t *)rental_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(rental_fee);
|
||||
SERIALIZE_TAGGED((const uint8_t *)namespace, strlen(namespace));
|
||||
SERIALIZE_TAGGED((const uint8_t *)parent, strlen(parent));
|
||||
} else {
|
||||
SERIALIZE_TAGGED((const uint8_t *)rental_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(rental_fee);
|
||||
SERIALIZE_TAGGED((const uint8_t *)namespace, strlen(namespace));
|
||||
SERIALIZE_U32(0xffffffff);
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(rental_fee);
|
||||
SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace));
|
||||
SERIALIZE_TAGGED((const uint8_t *) parent, strlen(parent));
|
||||
} else {
|
||||
SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(rental_fee);
|
||||
SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace));
|
||||
SERIALIZE_U32(0xffffffff);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
const char *description,
|
||||
uint32_t divisibility,
|
||||
uint64_t supply,
|
||||
bool mutable_supply,
|
||||
bool transferable,
|
||||
uint32_t levy_type,
|
||||
uint64_t levy_fee,
|
||||
const char *levy_address,
|
||||
const char *levy_namespace,
|
||||
const char *levy_mosaic,
|
||||
const char *creation_sink,
|
||||
uint64_t creation_fee) {
|
||||
bool nem_transaction_create_mosaic_creation(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *mosaic, const char *description,
|
||||
uint32_t divisibility, uint64_t supply, bool mutable_supply,
|
||||
bool transferable, uint32_t levy_type, uint64_t levy_fee,
|
||||
const char *levy_address, const char *levy_namespace,
|
||||
const char *levy_mosaic, const char *creation_sink, uint64_t creation_fee) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_MOSAIC_CREATION, (uint32_t)network << 24 | 1,
|
||||
timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_MOSAIC_CREATION,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length =
|
||||
sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
// This length will be rewritten later on
|
||||
nem_transaction_ctx state;
|
||||
memcpy(&state, ctx, sizeof(state));
|
||||
|
||||
// This length will be rewritten later on
|
||||
nem_transaction_ctx state;
|
||||
memcpy(&state, ctx, sizeof(state));
|
||||
SERIALIZE_U32(0);
|
||||
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)description, strlen(description));
|
||||
SERIALIZE_U32(4); // Number of properties
|
||||
|
||||
SERIALIZE_U32(0);
|
||||
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) description, strlen(description));
|
||||
SERIALIZE_U32(4); // Number of properties
|
||||
if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false;
|
||||
if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false;
|
||||
if (!nem_write_mosaic_bool(ctx, "supplyMutable", mutable_supply))
|
||||
return false;
|
||||
if (!nem_write_mosaic_bool(ctx, "transferable", transferable)) return false;
|
||||
|
||||
if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false;
|
||||
if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false;
|
||||
if (!nem_write_mosaic_bool(ctx, "supplyMutable", mutable_supply)) return false;
|
||||
if (!nem_write_mosaic_bool(ctx, "transferable", transferable)) return false;
|
||||
if (levy_type) {
|
||||
size_t levy_namespace_length = strlen(levy_namespace);
|
||||
size_t levy_mosaic_length = strlen(levy_mosaic);
|
||||
size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length +
|
||||
sizeof(uint32_t) + levy_mosaic_length;
|
||||
|
||||
if (levy_type) {
|
||||
size_t levy_namespace_length = strlen(levy_namespace);
|
||||
size_t levy_mosaic_length = strlen(levy_mosaic);
|
||||
size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length + sizeof(uint32_t) + levy_mosaic_length;
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE +
|
||||
sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t));
|
||||
SERIALIZE_U32(levy_type);
|
||||
SERIALIZE_TAGGED((const uint8_t *)levy_address, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U32(levy_identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)levy_namespace, levy_namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)levy_mosaic, levy_mosaic_length);
|
||||
SERIALIZE_U64(levy_fee);
|
||||
} else {
|
||||
SERIALIZE_U32(0);
|
||||
}
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE + sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t));
|
||||
SERIALIZE_U32(levy_type);
|
||||
SERIALIZE_TAGGED((const uint8_t *) levy_address, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U32(levy_identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) levy_namespace, levy_namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) levy_mosaic, levy_mosaic_length);
|
||||
SERIALIZE_U64(levy_fee);
|
||||
} else {
|
||||
SERIALIZE_U32(0);
|
||||
}
|
||||
// Rewrite length
|
||||
nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t));
|
||||
|
||||
// Rewrite length
|
||||
nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t));
|
||||
|
||||
SERIALIZE_TAGGED((const uint8_t *) creation_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(creation_fee);
|
||||
|
||||
return true;
|
||||
SERIALIZE_TAGGED((const uint8_t *)creation_sink, NEM_ADDRESS_SIZE);
|
||||
SERIALIZE_U64(creation_fee);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_mosaic_supply_change(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
uint32_t type,
|
||||
uint64_t delta) {
|
||||
bool nem_transaction_create_mosaic_supply_change(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *mosaic, uint32_t type, uint64_t delta) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE,
|
||||
(uint32_t)network << 24 | 1, timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length =
|
||||
sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
|
||||
size_t namespace_length = strlen(namespace);
|
||||
size_t mosaic_length = strlen(mosaic);
|
||||
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *)mosaic, mosaic_length);
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_U64(delta);
|
||||
|
||||
SERIALIZE_U32(identifier_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_U64(delta);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_aggregate_modification(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
uint32_t modifications,
|
||||
bool relative_change) {
|
||||
bool nem_transaction_create_aggregate_modification(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
uint32_t modifications, bool relative_change) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION,
|
||||
(uint32_t)network << 24 | (relative_change ? 2 : 1), timestamp, signer,
|
||||
fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION,
|
||||
(uint32_t) network << 24 | (relative_change ? 2 : 1),
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
SERIALIZE_U32(modifications);
|
||||
|
||||
SERIALIZE_U32(modifications);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx,
|
||||
uint32_t type,
|
||||
const ed25519_public_key cosignatory) {
|
||||
bool nem_transaction_write_cosignatory_modification(
|
||||
nem_transaction_ctx *ctx, uint32_t type,
|
||||
const ed25519_public_key cosignatory) {
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) +
|
||||
sizeof(ed25519_public_key));
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_TAGGED(cosignatory, sizeof(ed25519_public_key));
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(ed25519_public_key));
|
||||
SERIALIZE_U32(type);
|
||||
SERIALIZE_TAGGED(cosignatory, sizeof(ed25519_public_key));
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx,
|
||||
int32_t relative_change) {
|
||||
int32_t relative_change) {
|
||||
SERIALIZE_U32(sizeof(uint32_t));
|
||||
SERIALIZE_U32((uint32_t)relative_change);
|
||||
|
||||
SERIALIZE_U32(sizeof(uint32_t));
|
||||
SERIALIZE_U32((uint32_t) relative_change);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nem_transaction_create_importance_transfer(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
uint32_t mode,
|
||||
const ed25519_public_key remote) {
|
||||
bool nem_transaction_create_importance_transfer(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
uint32_t mode, const ed25519_public_key remote) {
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
|
||||
if (!signer) {
|
||||
signer = ctx->public_key;
|
||||
}
|
||||
bool ret = nem_transaction_write_common(
|
||||
ctx, NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER,
|
||||
(uint32_t)network << 24 | 1, timestamp, signer, fee, deadline);
|
||||
if (!ret) return false;
|
||||
|
||||
bool ret = nem_transaction_write_common(ctx,
|
||||
NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER,
|
||||
(uint32_t) network << 24 | 1,
|
||||
timestamp,
|
||||
signer,
|
||||
fee,
|
||||
deadline);
|
||||
if (!ret) return false;
|
||||
SERIALIZE_U32(mode);
|
||||
SERIALIZE_TAGGED(remote, sizeof(ed25519_public_key));
|
||||
|
||||
SERIALIZE_U32(mode);
|
||||
SERIALIZE_TAGGED(remote, sizeof(ed25519_public_key));
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
203
nem.h
203
nem.h
@ -31,161 +31,126 @@
|
||||
#include "ed25519-donna/ed25519.h"
|
||||
|
||||
#define NEM_LEVY_PERCENTILE_DIVISOR 4
|
||||
#define NEM_MAX_DIVISIBILITY 6
|
||||
#define NEM_MAX_SUPPLY 9000000000
|
||||
#define NEM_MAX_DIVISIBILITY 6
|
||||
#define NEM_MAX_SUPPLY 9000000000
|
||||
|
||||
#define NEM_NETWORK_MAINNET 0x68
|
||||
#define NEM_NETWORK_TESTNET 0x98
|
||||
#define NEM_NETWORK_MIJIN 0x60
|
||||
#define NEM_NETWORK_MIJIN 0x60
|
||||
|
||||
#define NEM_ADDRESS_SIZE 40
|
||||
#define NEM_ADDRESS_SIZE_RAW 25
|
||||
|
||||
#define NEM_TRANSACTION_TYPE_TRANSFER 0x0101
|
||||
#define NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER 0x0801
|
||||
#define NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION 0x1001
|
||||
#define NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE 0x1002
|
||||
#define NEM_TRANSACTION_TYPE_MULTISIG 0x1004
|
||||
#define NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE 0x2001
|
||||
#define NEM_TRANSACTION_TYPE_MOSAIC_CREATION 0x4001
|
||||
#define NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE 0x4002
|
||||
#define NEM_TRANSACTION_TYPE_TRANSFER 0x0101
|
||||
#define NEM_TRANSACTION_TYPE_IMPORTANCE_TRANSFER 0x0801
|
||||
#define NEM_TRANSACTION_TYPE_AGGREGATE_MODIFICATION 0x1001
|
||||
#define NEM_TRANSACTION_TYPE_MULTISIG_SIGNATURE 0x1002
|
||||
#define NEM_TRANSACTION_TYPE_MULTISIG 0x1004
|
||||
#define NEM_TRANSACTION_TYPE_PROVISION_NAMESPACE 0x2001
|
||||
#define NEM_TRANSACTION_TYPE_MOSAIC_CREATION 0x4001
|
||||
#define NEM_TRANSACTION_TYPE_MOSAIC_SUPPLY_CHANGE 0x4002
|
||||
|
||||
#define NEM_SALT_SIZE sizeof(ed25519_public_key)
|
||||
|
||||
#define NEM_ENCRYPTED_SIZE(size) (((size) + AES_BLOCK_SIZE) / AES_BLOCK_SIZE * AES_BLOCK_SIZE)
|
||||
#define NEM_ENCRYPTED_PAYLOAD_SIZE(size) (AES_BLOCK_SIZE + NEM_SALT_SIZE + NEM_ENCRYPTED_SIZE(size))
|
||||
#define NEM_ENCRYPTED_SIZE(size) \
|
||||
(((size) + AES_BLOCK_SIZE) / AES_BLOCK_SIZE * AES_BLOCK_SIZE)
|
||||
#define NEM_ENCRYPTED_PAYLOAD_SIZE(size) \
|
||||
(AES_BLOCK_SIZE + NEM_SALT_SIZE + NEM_ENCRYPTED_SIZE(size))
|
||||
|
||||
#define _NEM_PADDING_SIZE(buffer, size) ((buffer)[(size) - 1])
|
||||
#define NEM_PADDING_SIZE(buffer, size) (_NEM_PADDING_SIZE(buffer, size) > (size) ? (size) : _NEM_PADDING_SIZE(buffer, size))
|
||||
#define _NEM_PADDING_SIZE(buffer, size) ((buffer)[(size)-1])
|
||||
#define NEM_PADDING_SIZE(buffer, size) \
|
||||
(_NEM_PADDING_SIZE(buffer, size) > (size) ? (size) \
|
||||
: _NEM_PADDING_SIZE(buffer, size))
|
||||
|
||||
#define NEM_DECRYPTED_SIZE(buffer, size) ((size) - NEM_PADDING_SIZE(buffer, size))
|
||||
#define NEM_DECRYPTED_SIZE(buffer, size) ((size)-NEM_PADDING_SIZE(buffer, size))
|
||||
|
||||
typedef struct {
|
||||
ed25519_public_key public_key;
|
||||
uint8_t *buffer;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
ed25519_public_key public_key;
|
||||
uint8_t *buffer;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
} nem_transaction_ctx;
|
||||
|
||||
const char *nem_network_name(uint8_t network);
|
||||
|
||||
void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version, uint8_t *address);
|
||||
bool nem_get_address(const ed25519_public_key public_key, uint8_t version, char *address);
|
||||
void nem_get_address_raw(const ed25519_public_key public_key, uint8_t version,
|
||||
uint8_t *address);
|
||||
bool nem_get_address(const ed25519_public_key public_key, uint8_t version,
|
||||
char *address);
|
||||
|
||||
bool nem_validate_address_raw(const uint8_t *address, uint8_t network);
|
||||
bool nem_validate_address(const char *address, uint8_t network);
|
||||
|
||||
void nem_transaction_start(nem_transaction_ctx *ctx, const ed25519_public_key public_key, uint8_t *buffer, size_t size);
|
||||
size_t nem_transaction_end(nem_transaction_ctx *ctx, const ed25519_secret_key private_key, ed25519_signature signature);
|
||||
void nem_transaction_start(nem_transaction_ctx *ctx,
|
||||
const ed25519_public_key public_key, uint8_t *buffer,
|
||||
size_t size);
|
||||
size_t nem_transaction_end(nem_transaction_ctx *ctx,
|
||||
const ed25519_secret_key private_key,
|
||||
ed25519_signature signature);
|
||||
|
||||
bool nem_transaction_write_common(nem_transaction_ctx *context,
|
||||
uint32_t type,
|
||||
uint32_t version,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline);
|
||||
bool nem_transaction_write_common(nem_transaction_ctx *context, uint32_t type,
|
||||
uint32_t version, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee,
|
||||
uint32_t deadline);
|
||||
|
||||
bool nem_transaction_create_transfer(nem_transaction_ctx *context,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *recipient,
|
||||
uint64_t amount,
|
||||
const uint8_t *payload,
|
||||
uint32_t length,
|
||||
bool encrypted,
|
||||
uint32_t mosaics);
|
||||
uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee, uint32_t deadline,
|
||||
const char *recipient, uint64_t amount,
|
||||
const uint8_t *payload, uint32_t length,
|
||||
bool encrypted, uint32_t mosaics);
|
||||
|
||||
bool nem_transaction_write_mosaic(nem_transaction_ctx *ctx,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
uint64_t quantity);
|
||||
const char *namespace, const char *mosaic,
|
||||
uint64_t quantity);
|
||||
|
||||
bool nem_transaction_create_multisig(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const nem_transaction_ctx *inner);
|
||||
bool nem_transaction_create_multisig(nem_transaction_ctx *ctx, uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee, uint32_t deadline,
|
||||
const nem_transaction_ctx *inner);
|
||||
|
||||
bool nem_transaction_create_multisig_signature(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const nem_transaction_ctx *inner);
|
||||
bool nem_transaction_create_multisig_signature(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const nem_transaction_ctx *inner);
|
||||
|
||||
bool nem_transaction_create_provision_namespace(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *parent,
|
||||
const char *rental_sink,
|
||||
uint64_t rental_fee);
|
||||
bool nem_transaction_create_provision_namespace(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *parent, const char *rental_sink,
|
||||
uint64_t rental_fee);
|
||||
|
||||
bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
const char *description,
|
||||
uint32_t divisibility,
|
||||
uint64_t supply,
|
||||
bool mutable_supply,
|
||||
bool transferable,
|
||||
uint32_t levy_type,
|
||||
uint64_t levy_fee,
|
||||
const char *levy_address,
|
||||
const char *levy_namespace,
|
||||
const char *levy_mosaic,
|
||||
const char *creation_sink,
|
||||
uint64_t creation_fee);
|
||||
bool nem_transaction_create_mosaic_creation(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *mosaic, const char *description,
|
||||
uint32_t divisibility, uint64_t supply, bool mutable_supply,
|
||||
bool transferable, uint32_t levy_type, uint64_t levy_fee,
|
||||
const char *levy_address, const char *levy_namespace,
|
||||
const char *levy_mosaic, const char *creation_sink, uint64_t creation_fee);
|
||||
|
||||
bool nem_transaction_create_mosaic_supply_change(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
const char *namespace,
|
||||
const char *mosaic,
|
||||
uint32_t type,
|
||||
uint64_t delta);
|
||||
bool nem_transaction_create_mosaic_supply_change(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
const char *namespace, const char *mosaic, uint32_t type, uint64_t delta);
|
||||
|
||||
bool nem_transaction_create_aggregate_modification(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
uint32_t modifications,
|
||||
bool relative_change);
|
||||
bool nem_transaction_create_aggregate_modification(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
uint32_t modifications, bool relative_change);
|
||||
|
||||
bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx,
|
||||
uint32_t type,
|
||||
const ed25519_public_key cosignatory);
|
||||
bool nem_transaction_write_cosignatory_modification(
|
||||
nem_transaction_ctx *ctx, uint32_t type,
|
||||
const ed25519_public_key cosignatory);
|
||||
|
||||
bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx,
|
||||
int32_t relative_change);
|
||||
int32_t relative_change);
|
||||
|
||||
bool nem_transaction_create_importance_transfer(nem_transaction_ctx *ctx,
|
||||
uint8_t network,
|
||||
uint32_t timestamp,
|
||||
const ed25519_public_key signer,
|
||||
uint64_t fee,
|
||||
uint32_t deadline,
|
||||
uint32_t mode,
|
||||
const ed25519_public_key remote);
|
||||
bool nem_transaction_create_importance_transfer(
|
||||
nem_transaction_ctx *ctx, uint8_t network, uint32_t timestamp,
|
||||
const ed25519_public_key signer, uint64_t fee, uint32_t deadline,
|
||||
uint32_t mode, const ed25519_public_key remote);
|
||||
|
||||
#endif
|
||||
|
55
nist256p1.c
55
nist256p1.c
@ -24,42 +24,45 @@
|
||||
#include "nist256p1.h"
|
||||
|
||||
const ecdsa_curve nist256p1 = {
|
||||
/* .prime */ {
|
||||
/*.val =*/ {0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0, 0x1000, 0x3fffc000, 0xffff}
|
||||
},
|
||||
/* .prime */ {/*.val =*/{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0,
|
||||
0x1000, 0x3fffc000, 0xffff}},
|
||||
|
||||
/* G */ {
|
||||
/*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b, 0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b, 0x6b17}},
|
||||
/*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da, 0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86, 0x4fe3}}
|
||||
},
|
||||
/* G */
|
||||
{/*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b,
|
||||
0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b,
|
||||
0x6b17}},
|
||||
/*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da,
|
||||
0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86,
|
||||
0x4fe3}}},
|
||||
|
||||
/* order */ {
|
||||
/*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc, 0x3fffffff, 0xfff, 0x3fffc000, 0xffff}
|
||||
},
|
||||
/* order */
|
||||
{/*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc,
|
||||
0x3fffffff, 0xfff, 0x3fffc000, 0xffff}},
|
||||
|
||||
/* order_half */ {
|
||||
/*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde, 0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff}
|
||||
},
|
||||
/* order_half */
|
||||
{/*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde,
|
||||
0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff}},
|
||||
|
||||
/* a */ -3,
|
||||
/* a */ -3,
|
||||
|
||||
/* b */ {
|
||||
/*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65, 0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6}
|
||||
}
|
||||
/* b */
|
||||
{/*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65,
|
||||
0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6}}
|
||||
|
||||
#if USE_PRECOMPUTED_CP
|
||||
,
|
||||
/* cp */ {
|
||||
,
|
||||
/* cp */
|
||||
{
|
||||
#include "nist256p1.table"
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
const curve_info nist256p1_info = {
|
||||
.bip32_name = "Nist256p1 seed",
|
||||
.params = &nist256p1,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
.bip32_name = "Nist256p1 seed",
|
||||
.params = &nist256p1,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
@ -26,8 +26,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ecdsa.h"
|
||||
#include "bip32.h"
|
||||
#include "ecdsa.h"
|
||||
|
||||
extern const ecdsa_curve nist256p1;
|
||||
extern const curve_info nist256p1_info;
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
// support constructing BIP32 nodes from ed25519 and curve25519 curves.
|
||||
#ifndef USE_BIP32_25519_CURVES
|
||||
#define USE_BIP32_25519_CURVES 1
|
||||
#define USE_BIP32_25519_CURVES 1
|
||||
#endif
|
||||
|
||||
// implement BIP39 caching
|
||||
|
240
pbkdf2.c
240
pbkdf2.c
@ -21,157 +21,159 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "pbkdf2.h"
|
||||
#include <string.h>
|
||||
#include "hmac.h"
|
||||
#include "sha2.h"
|
||||
#include "memzero.h"
|
||||
#include "sha2.h"
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA256_CTX ctx;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x80000000;
|
||||
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x80000000;
|
||||
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy (ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
|
||||
sha256_Update(&ctx, salt, saltlen);
|
||||
sha256_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));
|
||||
sha256_Final(&ctx, (uint8_t*)pctx->g);
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
|
||||
sha256_Update(&ctx, salt, saltlen);
|
||||
sha256_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha256_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations)
|
||||
{
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha256_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH/sizeof(uint32_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha256_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha256_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH / sizeof(uint32_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key)
|
||||
{
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH/sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
|
||||
REVERSE32(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
|
||||
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)
|
||||
{
|
||||
uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA256_CTX pctx;
|
||||
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha256_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH];
|
||||
pbkdf2_hmac_sha256_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA256_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA256_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA256_CTX pctx;
|
||||
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha256_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH];
|
||||
pbkdf2_hmac_sha256_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA256_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr)
|
||||
{
|
||||
SHA512_CTX ctx;
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr) {
|
||||
SHA512_CTX ctx;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
|
||||
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x8000000000000000;
|
||||
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
|
||||
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
|
||||
memzero(pctx->g, sizeof(pctx->g));
|
||||
pctx->g[8] = 0x8000000000000000;
|
||||
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
|
||||
|
||||
memcpy (ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
|
||||
ctx.bitcount[1] = 0;
|
||||
sha512_Update(&ctx, salt, saltlen);
|
||||
sha512_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));
|
||||
sha512_Final(&ctx, (uint8_t*)pctx->g);
|
||||
memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
|
||||
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
|
||||
ctx.bitcount[1] = 0;
|
||||
sha512_Update(&ctx, salt, saltlen);
|
||||
sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
|
||||
sha512_Final(&ctx, (uint8_t *)pctx->g);
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->g[k], pctx->g[k]);
|
||||
}
|
||||
#endif
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
|
||||
pctx->first = 1;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations)
|
||||
{
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha512_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
|
||||
uint32_t iterations) {
|
||||
for (uint32_t i = pctx->first; i < iterations; i++) {
|
||||
sha512_Transform(pctx->idig, pctx->g, pctx->g);
|
||||
sha512_Transform(pctx->odig, pctx->g, pctx->g);
|
||||
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
|
||||
pctx->f[j] ^= pctx->g[j];
|
||||
}
|
||||
}
|
||||
pctx->first = 0;
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)
|
||||
{
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key) {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH/sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
|
||||
REVERSE64(pctx->f[k], pctx->f[k]);
|
||||
}
|
||||
#endif
|
||||
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
|
||||
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
|
||||
memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)
|
||||
{
|
||||
uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha512_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA512_DIGEST_LENGTH];
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen) {
|
||||
uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
|
||||
uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
|
||||
if (last_block_size) {
|
||||
blocks_count++;
|
||||
} else {
|
||||
last_block_size = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
|
||||
PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
|
||||
pbkdf2_hmac_sha512_Update(&pctx, iterations);
|
||||
uint8_t digest[SHA512_DIGEST_LENGTH];
|
||||
pbkdf2_hmac_sha512_Final(&pctx, digest);
|
||||
uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
|
||||
if (blocknr < blocks_count) {
|
||||
memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
|
||||
} else {
|
||||
memcpy(key + key_offset, digest, last_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
42
pbkdf2.h
42
pbkdf2.h
@ -28,29 +28,39 @@
|
||||
#include "sha2.h"
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA256_CTX {
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
char first;
|
||||
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
|
||||
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA256_CTX;
|
||||
|
||||
typedef struct _PBKDF2_HMAC_SHA512_CTX {
|
||||
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
char first;
|
||||
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
|
||||
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
|
||||
char first;
|
||||
} PBKDF2_HMAC_SHA512_CTX;
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations);
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx,
|
||||
uint32_t iterations);
|
||||
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen);
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations);
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
|
||||
int passlen, const uint8_t *salt, int saltlen,
|
||||
uint32_t blocknr);
|
||||
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
|
||||
uint32_t iterations);
|
||||
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key);
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen);
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
|
||||
int saltlen, uint32_t iterations, uint8_t *key,
|
||||
int keylen);
|
||||
|
||||
#endif
|
||||
|
69
rand.c
69
rand.c
@ -25,28 +25,27 @@
|
||||
|
||||
#ifndef RAND_PLATFORM_INDEPENDENT
|
||||
|
||||
#pragma message("NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.")
|
||||
#pragma message( \
|
||||
"NOT SUITABLE FOR PRODUCTION USE! Replace random32() function with your own secure code.")
|
||||
|
||||
// The following code is not supposed to be used in a production environment.
|
||||
// It's included only to make the library testable.
|
||||
// The message above tries to prevent any accidental use outside of the test environment.
|
||||
// The message above tries to prevent any accidental use outside of the test
|
||||
// environment.
|
||||
//
|
||||
// You are supposed to replace the random8() and random32() function with your own secure code.
|
||||
// There is also a possibility to replace the random_buffer() function as it is defined as a weak symbol.
|
||||
// You are supposed to replace the random8() and random32() function with your
|
||||
// own secure code. There is also a possibility to replace the random_buffer()
|
||||
// function as it is defined as a weak symbol.
|
||||
|
||||
static uint32_t seed = 0;
|
||||
|
||||
void random_reseed(const uint32_t value)
|
||||
{
|
||||
seed = value;
|
||||
}
|
||||
void random_reseed(const uint32_t value) { seed = value; }
|
||||
|
||||
uint32_t random32(void)
|
||||
{
|
||||
// Linear congruential generator from Numerical Recipes
|
||||
// https://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
seed = 1664525 * seed + 1013904223;
|
||||
return seed;
|
||||
uint32_t random32(void) {
|
||||
// Linear congruential generator from Numerical Recipes
|
||||
// https://en.wikipedia.org/wiki/Linear_congruential_generator
|
||||
seed = 1664525 * seed + 1013904223;
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif /* RAND_PLATFORM_INDEPENDENT */
|
||||
@ -55,30 +54,28 @@ uint32_t random32(void)
|
||||
// The following code is platform independent
|
||||
//
|
||||
|
||||
void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len)
|
||||
{
|
||||
uint32_t r = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i % 4 == 0) {
|
||||
r = random32();
|
||||
}
|
||||
buf[i] = (r >> ((i % 4) * 8)) & 0xFF;
|
||||
}
|
||||
void __attribute__((weak)) random_buffer(uint8_t *buf, size_t len) {
|
||||
uint32_t r = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i % 4 == 0) {
|
||||
r = random32();
|
||||
}
|
||||
buf[i] = (r >> ((i % 4) * 8)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t random_uniform(uint32_t n)
|
||||
{
|
||||
uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n);
|
||||
while ((x = random32()) >= max);
|
||||
return x / (max / n);
|
||||
uint32_t random_uniform(uint32_t n) {
|
||||
uint32_t x, max = 0xFFFFFFFF - (0xFFFFFFFF % n);
|
||||
while ((x = random32()) >= max)
|
||||
;
|
||||
return x / (max / n);
|
||||
}
|
||||
|
||||
void random_permute(char *str, size_t len)
|
||||
{
|
||||
for (int i = len - 1; i >= 1; i--) {
|
||||
int j = random_uniform(i + 1);
|
||||
char t = str[j];
|
||||
str[j] = str[i];
|
||||
str[i] = t;
|
||||
}
|
||||
void random_permute(char *str, size_t len) {
|
||||
for (int i = len - 1; i >= 1; i--) {
|
||||
int j = random_uniform(i + 1);
|
||||
char t = str[j];
|
||||
str[j] = str[i];
|
||||
str[i] = t;
|
||||
}
|
||||
}
|
||||
|
40
rc4.c
40
rc4.c
@ -23,34 +23,34 @@
|
||||
#include "rc4.h"
|
||||
|
||||
static inline void rc4_swap(RC4_CTX *ctx, uint8_t i, uint8_t j) {
|
||||
uint8_t temp = ctx->S[i];
|
||||
ctx->S[i] = ctx->S[j];
|
||||
ctx->S[j] = temp;
|
||||
uint8_t temp = ctx->S[i];
|
||||
ctx->S[i] = ctx->S[j];
|
||||
ctx->S[j] = temp;
|
||||
}
|
||||
|
||||
void rc4_init(RC4_CTX *ctx, const uint8_t *key, size_t length) {
|
||||
ctx->i = 0;
|
||||
ctx->j = 0;
|
||||
ctx->i = 0;
|
||||
ctx->j = 0;
|
||||
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
ctx->S[i] = i;
|
||||
}
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
ctx->S[i] = i;
|
||||
}
|
||||
|
||||
uint8_t j = 0;
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
j += ctx->S[i] + key[i % length];
|
||||
rc4_swap(ctx, i, j);
|
||||
}
|
||||
uint8_t j = 0;
|
||||
for (size_t i = 0; i < 256; i++) {
|
||||
j += ctx->S[i] + key[i % length];
|
||||
rc4_swap(ctx, i, j);
|
||||
}
|
||||
}
|
||||
|
||||
void rc4_encrypt(RC4_CTX *ctx, uint8_t *buffer, size_t length) {
|
||||
for (size_t idx = 0; idx < length; idx++) {
|
||||
ctx->i++;
|
||||
ctx->j += ctx->S[ctx->i];
|
||||
for (size_t idx = 0; idx < length; idx++) {
|
||||
ctx->i++;
|
||||
ctx->j += ctx->S[ctx->i];
|
||||
|
||||
rc4_swap(ctx, ctx->i, ctx->j);
|
||||
rc4_swap(ctx, ctx->i, ctx->j);
|
||||
|
||||
uint8_t K = ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256];
|
||||
buffer[idx] ^= K;
|
||||
}
|
||||
uint8_t K = ctx->S[(ctx->S[ctx->i] + ctx->S[ctx->j]) % 256];
|
||||
buffer[idx] ^= K;
|
||||
}
|
||||
}
|
||||
|
6
rc4.h
6
rc4.h
@ -23,12 +23,12 @@
|
||||
#ifndef __RC4_H__
|
||||
#define __RC4_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t S[256];
|
||||
uint8_t i, j;
|
||||
uint8_t S[256];
|
||||
uint8_t i, j;
|
||||
} RC4_CTX;
|
||||
|
||||
void rc4_init(RC4_CTX *ctx, const uint8_t *key, size_t length);
|
||||
|
71
rfc6979.c
71
rfc6979.c
@ -22,57 +22,56 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rfc6979.h"
|
||||
#include <string.h>
|
||||
#include "hmac.h"
|
||||
#include "memzero.h"
|
||||
|
||||
void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *state) {
|
||||
uint8_t bx[2*32];
|
||||
uint8_t buf[32 + 1 + 2*32];
|
||||
void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash,
|
||||
rfc6979_state *state) {
|
||||
uint8_t bx[2 * 32];
|
||||
uint8_t buf[32 + 1 + 2 * 32];
|
||||
|
||||
memcpy(bx, priv_key, 32);
|
||||
memcpy(bx+32, hash, 32);
|
||||
memcpy(bx, priv_key, 32);
|
||||
memcpy(bx + 32, hash, 32);
|
||||
|
||||
memset(state->v, 1, sizeof(state->v));
|
||||
memset(state->k, 0, sizeof(state->k));
|
||||
memset(state->v, 1, sizeof(state->v));
|
||||
memset(state->k, 0, sizeof(state->k));
|
||||
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x00;
|
||||
memcpy(buf + sizeof(state->v) + 1, bx, 64);
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x00;
|
||||
memcpy(buf + sizeof(state->v) + 1, bx, 64);
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x01;
|
||||
memcpy(buf + sizeof(state->v) + 1, bx, 64);
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x01;
|
||||
memcpy(buf + sizeof(state->v) + 1, bx, 64);
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(buf), state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
|
||||
memzero(bx, sizeof(bx));
|
||||
memzero(buf, sizeof(buf));
|
||||
memzero(bx, sizeof(bx));
|
||||
memzero(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
// generate next number from deterministic random number generator
|
||||
void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state)
|
||||
{
|
||||
uint8_t buf[32 + 1];
|
||||
void generate_rfc6979(uint8_t rnd[32], rfc6979_state *state) {
|
||||
uint8_t buf[32 + 1];
|
||||
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x00;
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(rnd, buf, 32);
|
||||
memzero(buf, sizeof(buf));
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(buf, state->v, sizeof(state->v));
|
||||
buf[sizeof(state->v)] = 0x00;
|
||||
hmac_sha256(state->k, sizeof(state->k), buf, sizeof(state->v) + 1, state->k);
|
||||
hmac_sha256(state->k, sizeof(state->k), state->v, sizeof(state->v), state->v);
|
||||
memcpy(rnd, buf, 32);
|
||||
memzero(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
// generate K in a deterministic way, according to RFC6979
|
||||
// http://tools.ietf.org/html/rfc6979
|
||||
void generate_k_rfc6979(bignum256 *k, rfc6979_state *state)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
generate_rfc6979(buf, state);
|
||||
bn_read_be(buf, k);
|
||||
memzero(buf, sizeof(buf));
|
||||
void generate_k_rfc6979(bignum256 *k, rfc6979_state *state) {
|
||||
uint8_t buf[32];
|
||||
generate_rfc6979(buf, state);
|
||||
bn_read_be(buf, k);
|
||||
memzero(buf, sizeof(buf));
|
||||
}
|
||||
|
@ -30,10 +30,11 @@
|
||||
|
||||
// rfc6979 pseudo random number generator state
|
||||
typedef struct {
|
||||
uint8_t v[32], k[32];
|
||||
uint8_t v[32], k[32];
|
||||
} rfc6979_state;
|
||||
|
||||
void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash, rfc6979_state *rng);
|
||||
void init_rfc6979(const uint8_t *priv_key, const uint8_t *hash,
|
||||
rfc6979_state *rng);
|
||||
void generate_rfc6979(uint8_t rnd[32], rfc6979_state *rng);
|
||||
void generate_k_rfc6979(bignum256 *k, rfc6979_state *rng);
|
||||
|
||||
|
16
ripemd160.h
16
ripemd160.h
@ -3,18 +3,20 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RIPEMD160_BLOCK_LENGTH 64
|
||||
#define RIPEMD160_DIGEST_LENGTH 20
|
||||
#define RIPEMD160_BLOCK_LENGTH 64
|
||||
#define RIPEMD160_DIGEST_LENGTH 20
|
||||
|
||||
typedef struct _RIPEMD160_CTX {
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[5]; /*!< intermediate digest state */
|
||||
uint8_t buffer[RIPEMD160_BLOCK_LENGTH]; /*!< data block being processed */
|
||||
} RIPEMD160_CTX;
|
||||
|
||||
void ripemd160_Init(RIPEMD160_CTX *ctx);
|
||||
void ripemd160_Update(RIPEMD160_CTX *ctx, const uint8_t *input, uint32_t ilen);
|
||||
void ripemd160_Final(RIPEMD160_CTX *ctx, uint8_t output[RIPEMD160_DIGEST_LENGTH]);
|
||||
void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t hash[RIPEMD160_DIGEST_LENGTH]);
|
||||
void ripemd160_Final(RIPEMD160_CTX *ctx,
|
||||
uint8_t output[RIPEMD160_DIGEST_LENGTH]);
|
||||
void ripemd160(const uint8_t *msg, uint32_t msg_len,
|
||||
uint8_t hash[RIPEMD160_DIGEST_LENGTH]);
|
||||
|
||||
#endif
|
||||
|
68
script.c
68
script.c
@ -20,45 +20,47 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "script.h"
|
||||
#include <string.h>
|
||||
#include "base58.h"
|
||||
#include "script.h"
|
||||
|
||||
int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, int addrsize)
|
||||
{
|
||||
uint8_t raw[35];
|
||||
int script_output_to_address(const uint8_t *script, int scriptlen, char *addr,
|
||||
int addrsize) {
|
||||
uint8_t raw[35];
|
||||
|
||||
// P2PKH
|
||||
if (scriptlen == 25 && script[0] == 0x76 && script[1] == 0xA9 && script[2] == 0x14 && script[23] == 0x88 && script[24] == 0xAC) {
|
||||
raw[0] = 0x00;
|
||||
memcpy(raw + 1, script + 3, 20);
|
||||
return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
// P2PKH
|
||||
if (scriptlen == 25 && script[0] == 0x76 && script[1] == 0xA9 &&
|
||||
script[2] == 0x14 && script[23] == 0x88 && script[24] == 0xAC) {
|
||||
raw[0] = 0x00;
|
||||
memcpy(raw + 1, script + 3, 20);
|
||||
return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
|
||||
// P2SH
|
||||
if (scriptlen == 23 && script[0] == 0xA9 && script[1] == 0x14 && script[22] == 0x87) {
|
||||
raw[0] = 0x05;
|
||||
memcpy(raw + 1, script + 2, 20);
|
||||
return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
// P2SH
|
||||
if (scriptlen == 23 && script[0] == 0xA9 && script[1] == 0x14 &&
|
||||
script[22] == 0x87) {
|
||||
raw[0] = 0x05;
|
||||
memcpy(raw + 1, script + 2, 20);
|
||||
return base58_encode_check(raw, 1 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
|
||||
// P2WPKH
|
||||
if (scriptlen == 22 && script[0] == 0x00 && script[1] == 0x14) {
|
||||
raw[0] = 0x06;
|
||||
raw[1] = 0x00;
|
||||
raw[2] = 0x00;
|
||||
memcpy(raw + 3, script + 2, 20);
|
||||
return base58_encode_check(raw, 3 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
// P2WPKH
|
||||
if (scriptlen == 22 && script[0] == 0x00 && script[1] == 0x14) {
|
||||
raw[0] = 0x06;
|
||||
raw[1] = 0x00;
|
||||
raw[2] = 0x00;
|
||||
memcpy(raw + 3, script + 2, 20);
|
||||
return base58_encode_check(raw, 3 + 20, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
|
||||
// P2WSH
|
||||
if (scriptlen == 34 && script[0] == 0x00 && script[1] == 0x20) {
|
||||
raw[0] = 0x0A;
|
||||
raw[1] = 0x00;
|
||||
raw[2] = 0x00;
|
||||
memcpy(raw + 3, script + 2, 32);
|
||||
return base58_encode_check(raw, 3 + 32, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
// P2WSH
|
||||
if (scriptlen == 34 && script[0] == 0x00 && script[1] == 0x20) {
|
||||
raw[0] = 0x0A;
|
||||
raw[1] = 0x00;
|
||||
raw[2] = 0x00;
|
||||
memcpy(raw + 3, script + 2, 32);
|
||||
return base58_encode_check(raw, 3 + 32, HASHER_SHA2D, addr, addrsize);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
3
script.h
3
script.h
@ -25,6 +25,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, int addrsize);
|
||||
int script_output_to_address(const uint8_t *script, int scriptlen, char *addr,
|
||||
int addrsize);
|
||||
|
||||
#endif
|
||||
|
89
secp256k1.c
89
secp256k1.c
@ -24,69 +24,70 @@
|
||||
#include "secp256k1.h"
|
||||
|
||||
const ecdsa_curve secp256k1 = {
|
||||
/* .prime */ {
|
||||
/*.val =*/ {0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}
|
||||
},
|
||||
/* .prime */ {/*.val =*/{0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff,
|
||||
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
|
||||
0xffff}},
|
||||
|
||||
/* G */ {
|
||||
/*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb, 0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}},
|
||||
/*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229, 0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8, 0x483a}}
|
||||
},
|
||||
/* G */
|
||||
{/*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb,
|
||||
0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}},
|
||||
/*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229,
|
||||
0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8,
|
||||
0x483a}}},
|
||||
|
||||
/* order */ {
|
||||
/*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}
|
||||
},
|
||||
/* order */
|
||||
{/*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba,
|
||||
0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}},
|
||||
|
||||
/* order_half */ {
|
||||
/*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff}
|
||||
},
|
||||
/* order_half */
|
||||
{/*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d,
|
||||
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff}},
|
||||
|
||||
/* a */ 0,
|
||||
/* a */ 0,
|
||||
|
||||
/* b */ {
|
||||
/*.val =*/{7}
|
||||
}
|
||||
/* b */ {/*.val =*/{7}}
|
||||
|
||||
#if USE_PRECOMPUTED_CP
|
||||
,
|
||||
/* cp */ {
|
||||
,
|
||||
/* cp */
|
||||
{
|
||||
#include "secp256k1.table"
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
const curve_info secp256k1_info = {
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_SHA2D,
|
||||
.hasher_sign = HASHER_SHA2D,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
const curve_info secp256k1_decred_info = {
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_BLAKED,
|
||||
.hasher_sign = HASHER_BLAKE,
|
||||
.hasher_pubkey = HASHER_BLAKE_RIPEMD,
|
||||
.hasher_script = HASHER_BLAKE,
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_BLAKED,
|
||||
.hasher_sign = HASHER_BLAKE,
|
||||
.hasher_pubkey = HASHER_BLAKE_RIPEMD,
|
||||
.hasher_script = HASHER_BLAKE,
|
||||
};
|
||||
|
||||
const curve_info secp256k1_groestl_info = {
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_GROESTLD_TRUNC,
|
||||
.hasher_sign = HASHER_SHA2,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_GROESTLD_TRUNC,
|
||||
.hasher_sign = HASHER_SHA2,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
||||
const curve_info secp256k1_smart_info = {
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_SHA3K,
|
||||
.hasher_sign = HASHER_SHA2,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
.bip32_name = "Bitcoin seed",
|
||||
.params = &secp256k1,
|
||||
.hasher_base58 = HASHER_SHA3K,
|
||||
.hasher_sign = HASHER_SHA2,
|
||||
.hasher_pubkey = HASHER_SHA2_RIPEMD,
|
||||
.hasher_script = HASHER_SHA2,
|
||||
};
|
||||
|
@ -26,8 +26,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ecdsa.h"
|
||||
#include "bip32.h"
|
||||
#include "ecdsa.h"
|
||||
|
||||
extern const ecdsa_curve secp256k1;
|
||||
extern const curve_info secp256k1_info;
|
||||
|
@ -35,13 +35,8 @@
|
||||
* prog_len: Number of data bytes in prog.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int segwit_addr_encode(
|
||||
char *output,
|
||||
const char *hrp,
|
||||
int ver,
|
||||
const uint8_t *prog,
|
||||
size_t prog_len
|
||||
);
|
||||
int segwit_addr_encode(char *output, const char *hrp, int ver,
|
||||
const uint8_t *prog, size_t prog_len);
|
||||
|
||||
/** Decode a SegWit address
|
||||
*
|
||||
@ -49,20 +44,13 @@ int segwit_addr_encode(
|
||||
* program version (between 0 and 16 inclusive).
|
||||
* prog: Pointer to a buffer of size 40 that will be updated to
|
||||
* contain the witness program bytes.
|
||||
* prog_len: Pointer to a size_t that will be updated to contain the length
|
||||
* of bytes in prog.
|
||||
* hrp: Pointer to the null-terminated human readable part that is
|
||||
* expected (chain/network specific).
|
||||
* addr: Pointer to the null-terminated address.
|
||||
* Returns 1 if successful.
|
||||
* prog_len: Pointer to a size_t that will be updated to contain the
|
||||
* length of bytes in prog. hrp: Pointer to the null-terminated human
|
||||
* readable part that is expected (chain/network specific). addr: Pointer to
|
||||
* the null-terminated address. Returns 1 if successful.
|
||||
*/
|
||||
int segwit_addr_decode(
|
||||
int* ver,
|
||||
uint8_t* prog,
|
||||
size_t* prog_len,
|
||||
const char* hrp,
|
||||
const char* addr
|
||||
);
|
||||
int segwit_addr_decode(int *ver, uint8_t *prog, size_t *prog_len,
|
||||
const char *hrp, const char *addr);
|
||||
|
||||
/** Encode a Bech32 string
|
||||
*
|
||||
@ -73,12 +61,8 @@ int segwit_addr_decode(
|
||||
* data_len: Length of the data array.
|
||||
* Returns 1 if successful.
|
||||
*/
|
||||
int bech32_encode(
|
||||
char *output,
|
||||
const char *hrp,
|
||||
const uint8_t *data,
|
||||
size_t data_len
|
||||
);
|
||||
int bech32_encode(char *output, const char *hrp, const uint8_t *data,
|
||||
size_t data_len);
|
||||
|
||||
/** Decode a Bech32 string
|
||||
*
|
||||
@ -91,11 +75,7 @@ int bech32_encode(
|
||||
* In: input: Pointer to a null-terminated Bech32 string.
|
||||
* Returns 1 if succesful.
|
||||
*/
|
||||
int bech32_decode(
|
||||
char *hrp,
|
||||
uint8_t *data,
|
||||
size_t *data_len,
|
||||
const char *input
|
||||
);
|
||||
int bech32_decode(char *hrp, uint8_t *data, size_t *data_len,
|
||||
const char *input);
|
||||
|
||||
#endif
|
||||
|
@ -2,5 +2,5 @@ with import <nixpkgs> {};
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "trezor-crypto-dev";
|
||||
buildInputs = [ gnumake gcc pkgconfig openssl check valgrind ];
|
||||
buildInputs = [ gnumake gcc pkgconfig openssl check valgrind clang-tools ];
|
||||
}
|
||||
|
11745
tests/test_check.c
11745
tests/test_check.c
File diff suppressed because it is too large
Load Diff
@ -1,215 +1,379 @@
|
||||
// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128
|
||||
START_TEST(test_ed25519_cardano_sign_vectors)
|
||||
{
|
||||
ed25519_public_key public_key;
|
||||
ed25519_secret_key secret_key;
|
||||
ed25519_secret_key secret_key_extension;
|
||||
ed25519_signature signature;
|
||||
START_TEST(test_ed25519_cardano_sign_vectors) {
|
||||
ed25519_public_key public_key;
|
||||
ed25519_secret_key secret_key;
|
||||
ed25519_secret_key secret_key_extension;
|
||||
ed25519_signature signature;
|
||||
|
||||
static const char *vectors[] = {
|
||||
"6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53", // private key
|
||||
"60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e", // private key extension
|
||||
"64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1", // public key
|
||||
"45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c79331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10d", // signature
|
||||
static const char
|
||||
*vectors[] =
|
||||
{
|
||||
"6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea5"
|
||||
"3", // private key
|
||||
"60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8"
|
||||
"e", // private key extension
|
||||
"64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe"
|
||||
"1", // public key
|
||||
"45b1a75fe3119e13c6f60ab9ba674b42f946fdc558e07c83dfa0751c2eba69c7"
|
||||
"9331bd8a4a975662b23628a438a0eba76367e44c12ca91b39ec59063f860f10"
|
||||
"d", // signature
|
||||
|
||||
"e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c", // private key
|
||||
"794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4", // private key extension
|
||||
"95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df", // public key
|
||||
"f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b19ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560f", // signature
|
||||
"e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830"
|
||||
"c", // private key
|
||||
"794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a"
|
||||
"4", // private key extension
|
||||
"95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931d"
|
||||
"f", // public key
|
||||
"f2c9171782e7df7665126ac545ae53b05964b0160536efdb545e2460dbbec2b1"
|
||||
"9ec6b338b8f1bf4dfee94360ed024b115e37b1d7e6f3f9ae4beb79539428560"
|
||||
"f", // signature
|
||||
|
||||
"9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c", // private key
|
||||
"b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb", // private key extension
|
||||
"79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f", // public key
|
||||
"2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800f", // signature
|
||||
"9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0"
|
||||
"c", // private key
|
||||
"b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedeb"
|
||||
"b", // private key extension
|
||||
"79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19"
|
||||
"f", // public key
|
||||
"2ba1439ae648a7e8da7c9ab1ee6da94fd4ebe37abd0978306e8fba2afa8f111a"
|
||||
"88a993dbf008bedae9167f4f68409e4c9ddaf02cba12418447b1848907ad800"
|
||||
"f", // signature
|
||||
|
||||
"52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c", // private key
|
||||
"6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803", // private key extension
|
||||
"dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6", // public key
|
||||
"0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a62a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd781602", // signature
|
||||
"52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40"
|
||||
"c", // private key
|
||||
"6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a2580"
|
||||
"3", // private key extension
|
||||
"dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d"
|
||||
"6", // public key
|
||||
"0cd34f84e0d2fcb1800bdb0e869b9041349955ced66aedbe6bda187ebe8d36a6"
|
||||
"2a05b39647e92fcc42aa7a7368174240afba08b8c81f981a22f942d6bd78160"
|
||||
"2", // signature
|
||||
|
||||
"11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04", // private key
|
||||
"c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352", // private key extension
|
||||
"839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78", // public key
|
||||
"e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa4905", // signature
|
||||
"11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec0"
|
||||
"4", // private key
|
||||
"c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a547340235"
|
||||
"2", // private key extension
|
||||
"839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db7"
|
||||
"8", // public key
|
||||
"e41f73db2f8d2896a687802b2be76b7cabb73dfbb4891494883a0cbd9bbb9e5f"
|
||||
"9d3e14d2d0b06c6674333508496db660936737c0efd9511514147dac79fa490"
|
||||
"5", // signature
|
||||
|
||||
"5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505", // private key
|
||||
"ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd", // private key extension
|
||||
"75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76", // public key
|
||||
"631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fbc10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda598906", // signature
|
||||
"5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e50"
|
||||
"5", // private key
|
||||
"ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098c"
|
||||
"d", // private key extension
|
||||
"75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb7"
|
||||
"6", // public key
|
||||
"631015357cee3051116b4c2ff4d1c5beb13b6e5023635aa1eeb0563cadf0d4fb"
|
||||
"c10bd5e31b4a4220c67875558c41b5cc0328104ae39cc7ff20ff0c2bda59890"
|
||||
"6", // signature
|
||||
|
||||
"624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d", // private key
|
||||
"097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02", // private key extension
|
||||
"0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00", // public key
|
||||
"1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f901", // signature
|
||||
"624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50"
|
||||
"d", // private key
|
||||
"097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b0"
|
||||
"2", // private key extension
|
||||
"0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b0"
|
||||
"0", // public key
|
||||
"1de1d275428ba9491a433cd473cd076c027f61e7a8b5391df9dea5cb4bc88d8a"
|
||||
"57b095906a30b13e68259851a8dd3f57b6f0ffa37a5d3ffc171240f2d404f90"
|
||||
"1", // signature
|
||||
|
||||
0, 0,
|
||||
};
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
const char **test_data;
|
||||
test_data = vectors;
|
||||
while (*test_data) {
|
||||
memcpy(secret_key, fromhex(*test_data), 32);
|
||||
MARK_SECRET_DATA(secret_key, sizeof(secret_key));
|
||||
const char **test_data;
|
||||
test_data = vectors;
|
||||
while (*test_data) {
|
||||
memcpy(secret_key, fromhex(*test_data), 32);
|
||||
MARK_SECRET_DATA(secret_key, sizeof(secret_key));
|
||||
|
||||
memcpy(secret_key_extension, fromhex(*(test_data + 1)), 32);
|
||||
MARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
|
||||
memcpy(secret_key_extension, fromhex(*(test_data + 1)), 32);
|
||||
MARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
|
||||
|
||||
ed25519_publickey_ext(secret_key, secret_key_extension, public_key);
|
||||
UNMARK_SECRET_DATA(public_key, sizeof(public_key));
|
||||
ed25519_publickey_ext(secret_key, secret_key_extension, public_key);
|
||||
UNMARK_SECRET_DATA(public_key, sizeof(public_key));
|
||||
|
||||
ck_assert_mem_eq(public_key, fromhex(*(test_data + 2)), 32);
|
||||
ck_assert_mem_eq(public_key, fromhex(*(test_data + 2)), 32);
|
||||
|
||||
const uint8_t * message = (const uint8_t *) "Hello World";
|
||||
ed25519_sign_ext(message, 11, secret_key, secret_key_extension, public_key, signature);
|
||||
UNMARK_SECRET_DATA(signature, sizeof(signature));
|
||||
const uint8_t *message = (const uint8_t *)"Hello World";
|
||||
ed25519_sign_ext(message, 11, secret_key, secret_key_extension, public_key,
|
||||
signature);
|
||||
UNMARK_SECRET_DATA(signature, sizeof(signature));
|
||||
|
||||
ck_assert_mem_eq(signature, fromhex(*(test_data + 3)), 64);
|
||||
ck_assert_mem_eq(signature, fromhex(*(test_data + 3)), 64);
|
||||
|
||||
UNMARK_SECRET_DATA(secret_key, sizeof(secret_key));
|
||||
UNMARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
|
||||
UNMARK_SECRET_DATA(secret_key, sizeof(secret_key));
|
||||
UNMARK_SECRET_DATA(secret_key_extension, sizeof(secret_key_extension));
|
||||
|
||||
test_data += 4;
|
||||
}
|
||||
test_data += 4;
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_1)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_1) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("9a1d04808b4c0682816961cf666e82a7fd35949658aba5354c517eccf12aacb4"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"affbc325d9027c0f2d9f925b1dcf6c12bf5c1dd08904474066a4f2c00db56173"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"08a14df748e477a69d21c97c56db151fc19e2521f31dd0ac5360f269e5b6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"daeb991f2d2128e2525415c56a07f4366baa26c1e48572a5e073934b6de35fbc"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"9a1d04808b4c0682816961cf666e82a7fd35949658aba5354c517eccf12aacb4"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_2)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_2) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("104c6a0736e501c9bfe2966ba3773f5320495b19c3f2ed222234850af2ccd5b1"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("6064bf06b2e981d7c9792b1482eeecd40ec3cfa12143f4a1f149d48ce8b6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("64aa9a16331f14c981b769efcf96addcc4c6db44047fe7a7feae0be23d33bf54"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("c651c14a13c2311fc30a7acf244add1fdac3683e7ba89b4571e4cbcab509b915"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"104c6a0736e501c9bfe2966ba3773f5320495b19c3f2ed222234850af2ccd5b1"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"6064bf06b2e981d7c9792b1482eeecd40ec3cfa12143f4a1f149d48ce8b6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"64aa9a16331f14c981b769efcf96addcc4c6db44047fe7a7feae0be23d33bf54"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"c651c14a13c2311fc30a7acf244add1fdac3683e7ba89b4571e4cbcab509b915"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_3)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_3) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("da99870d7e69de2a76f255ba8c7ed22428c7e5b0a8df978753c707c95ec3d4ca"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("c85fa69f4a1891fd98d1d1fc5f0cf9b1d6e44b0e6906744ab23ea766edb6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("b4fc241feffe840b8a54a26ab447f5a5caa31032db3a8091fca14f38b86ed539"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("5a5b0c92530cd366f05cf072509c806f904262c259e79a0080bbd5ee35706bb1"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"da99870d7e69de2a76f255ba8c7ed22428c7e5b0a8df978753c707c95ec3d4ca"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"c85fa69f4a1891fd98d1d1fc5f0cf9b1d6e44b0e6906744ab23ea766edb6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"b4fc241feffe840b8a54a26ab447f5a5caa31032db3a8091fca14f38b86ed539"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"5a5b0c92530cd366f05cf072509c806f904262c259e79a0080bbd5ee35706bb1"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_4)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_4) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("b40c44dfd9be08591b62be7f9991c85f812d8196927f3c824d9fcb17d275089e"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("d064dcf1449d9c3e47f5b422680343561989035bf2e4e23fc34cb61fedb6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("a3071959013af95aaecf78a7a2e1b9838bbbc4864d6a8a2295243782078345cd"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("aaaca5e7adc69a03ef1f5c017ed02879e8ca871df028461ed9bf19fb8fa15038"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"b40c44dfd9be08591b62be7f9991c85f812d8196927f3c824d9fcb17d275089e"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"d064dcf1449d9c3e47f5b422680343561989035bf2e4e23fc34cb61fedb6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"a3071959013af95aaecf78a7a2e1b9838bbbc4864d6a8a2295243782078345cd"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"aaaca5e7adc69a03ef1f5c017ed02879e8ca871df028461ed9bf19fb8fa15038"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_5)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_5) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("2593896baf92f6ab2c0f253787ab16be0244ba95e0d48ba09da1a7fd3f926c72"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("0811b6d5d6f7120cb05d4ce5453d6ce42825c2a8e53b6d370a6b05ccf4b6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("5bebf1eea68acd04932653d944b064b10baaf5886dd73c185cc285059bf93363"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("1c87a32c5babad2fe33e0586bdc523574c6126f8368bc76598e17ea46201f980"), 32);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"2593896baf92f6ab2c0f253787ab16be0244ba95e0d48ba09da1a7fd3f926c72"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"0811b6d5d6f7120cb05d4ce5453d6ce42825c2a8e53b6d370a6b05ccf4b6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"5bebf1eea68acd04932653d944b064b10baaf5886dd73c185cc285059bf93363"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"1c87a32c5babad2fe33e0586bdc523574c6126f8368bc76598e17ea46201f980"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_6)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_6) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("fe8c6c2ab1e30385513fcffb49dcfe3e7805260425ea76b3b72b9f5bbe3b3d40"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("6019b9f5ef6ca530b657bcdb500de5455db8d51afb951fa045b6fbb3f6b6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("466332cb097934b43008701e7e27044aa56c7859019e4eba18d91a3bea23dff7"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("0b8f04755481ced76b4e5795aaafdb3cbd757c10fe60e9c58f48cf29a7ec3575"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"fe8c6c2ab1e30385513fcffb49dcfe3e7805260425ea76b3b72b9f5bbe3b3d40"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"6019b9f5ef6ca530b657bcdb500de5455db8d51afb951fa045b6fbb3f6b6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"466332cb097934b43008701e7e27044aa56c7859019e4eba18d91a3bea23dff7"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"0b8f04755481ced76b4e5795aaafdb3cbd757c10fe60e9c58f48cf29a7ec3575"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_7)
|
||||
{
|
||||
HDNode node;
|
||||
START_TEST(test_bip32_cardano_hdnode_vector_7) {
|
||||
HDNode node;
|
||||
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy("ring crime symptom enough erupt lady behave ramp apart settle citizen junk", seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
uint8_t seed[66];
|
||||
int seed_len = mnemonic_to_entropy(
|
||||
"ring crime symptom enough erupt lady behave ramp apart settle citizen "
|
||||
"junk",
|
||||
seed);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano((const uint8_t *)"", 0, seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0xBB9ACA00);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000002);
|
||||
hdnode_private_ckd_cardano(&node, 0xBB9ACA00);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("ff77c08d37471c1d4cedd3fae2642c009324d9712492efc74dedab09c9bf973c"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("488f34840bba516f7920f91676b8681d0dd833b4ce14468e0810b255f9b6ea46"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("01eccef768a79859f824a1d3c3e35e131184e2940c3fca9a4c9b307741f65363"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("148605be54585773b44ba87e79265149ae444c4cc37cb1f8db8c08482fba293b"), 32);
|
||||
ck_assert_mem_eq(
|
||||
node.chain_code,
|
||||
fromhex(
|
||||
"ff77c08d37471c1d4cedd3fae2642c009324d9712492efc74dedab09c9bf973c"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key,
|
||||
fromhex(
|
||||
"488f34840bba516f7920f91676b8681d0dd833b4ce14468e0810b255f9b6ea46"),
|
||||
32);
|
||||
ck_assert_mem_eq(
|
||||
node.private_key_extension,
|
||||
fromhex(
|
||||
"01eccef768a79859f824a1d3c3e35e131184e2940c3fca9a4c9b307741f65363"),
|
||||
32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(
|
||||
node.public_key + 1,
|
||||
fromhex(
|
||||
"148605be54585773b44ba87e79265149ae444c4cc37cb1f8db8c08482fba293b"),
|
||||
32);
|
||||
}
|
||||
END_TEST
|
||||
|
@ -1,76 +1,67 @@
|
||||
#include "cash_addr.h"
|
||||
|
||||
static const char* valid_cashchecksum[] = {
|
||||
"prefix:x64nx6hz",
|
||||
"p:gpf8m4h7",
|
||||
"bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn",
|
||||
"bchtest:testnetaddress4d6njnut",
|
||||
"bchreg:555555555555555555555555555555555555555555555udxmlmrz",
|
||||
"prefix:x64nx6hz",
|
||||
"p:gpf8m4h7",
|
||||
"bitcoincash:qpzry9x8gf2tvdw0s3jn54khce6mua7lcw20ayyn",
|
||||
"bchtest:testnetaddress4d6njnut",
|
||||
"bchreg:555555555555555555555555555555555555555555555udxmlmrz",
|
||||
};
|
||||
|
||||
struct valid_cashaddr_data {
|
||||
const char* legacy;
|
||||
const char* cashaddress;
|
||||
const char* legacy;
|
||||
const char* cashaddress;
|
||||
};
|
||||
|
||||
static struct valid_cashaddr_data valid_cashaddr[] = {
|
||||
{
|
||||
"1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu",
|
||||
"bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"
|
||||
},
|
||||
{
|
||||
"1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR",
|
||||
"bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"
|
||||
},
|
||||
{
|
||||
"16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb",
|
||||
"bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"
|
||||
},
|
||||
{
|
||||
"3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC",
|
||||
"bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"
|
||||
},
|
||||
{
|
||||
"3LDsS579y7sruadqu11beEJoTjdFiFCdX4",
|
||||
"bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"
|
||||
},
|
||||
{
|
||||
"31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw",
|
||||
"bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"
|
||||
}
|
||||
};
|
||||
{"1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu",
|
||||
"bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a"},
|
||||
{"1KXrWXciRDZUpQwQmuM1DbwsKDLYAYsVLR",
|
||||
"bitcoincash:qr95sy3j9xwd2ap32xkykttr4cvcu7as4y0qverfuy"},
|
||||
{"16w1D5WRVKJuZUsSRzdLp9w3YGcgoxDXb",
|
||||
"bitcoincash:qqq3728yw0y47sqn6l2na30mcw6zm78dzqre909m2r"},
|
||||
{"3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC",
|
||||
"bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq"},
|
||||
{"3LDsS579y7sruadqu11beEJoTjdFiFCdX4",
|
||||
"bitcoincash:pr95sy3j9xwd2ap32xkykttr4cvcu7as4yc93ky28e"},
|
||||
{"31nwvkZwyPdgzjBJZXfDmSWsC4ZLKpYyUw",
|
||||
"bitcoincash:pqq3728yw0y47sqn6l2na30mcw6zm78dzq5ucqzc37"}};
|
||||
|
||||
START_TEST(test_cashaddr)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(valid_cashchecksum) / sizeof(valid_cashchecksum[0]); ++i) {
|
||||
uint8_t data[82];
|
||||
char rebuild[92];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = cash_decode(hrp, data, &data_len, valid_cashchecksum[i]);
|
||||
ck_assert_int_eq(res, 1);
|
||||
res = cash_encode(rebuild, hrp, data, data_len);
|
||||
ck_assert_int_eq(res, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashchecksum[i], 92), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(valid_cashaddr) / sizeof(valid_cashaddr[0]); ++i) {
|
||||
uint8_t prog[65];
|
||||
size_t prog_len;
|
||||
const char* hrp = "bitcoincash";
|
||||
uint8_t rawdata[65];
|
||||
size_t rawdata_len;
|
||||
char rebuild[93];
|
||||
int ret = cash_addr_decode(prog, &prog_len, hrp, valid_cashaddr[i].cashaddress);
|
||||
ck_assert_int_eq(ret, 1);
|
||||
ck_assert_int_eq(prog_len, 21);
|
||||
rawdata_len = base58_decode_check(valid_cashaddr[i].legacy, HASHER_SHA2D, rawdata, sizeof(rawdata));
|
||||
ck_assert_int_eq(rawdata_len, 21);
|
||||
ck_assert_int_eq(prog[0], rawdata[0] == 0 ? 0x00 : rawdata[0] == 5 ? 0x08 : -1);
|
||||
ck_assert_int_eq(memcmp(rawdata + 1, prog + 1, 20), 0);
|
||||
ret = cash_addr_encode(rebuild, hrp, prog, 21);
|
||||
ck_assert_int_eq(ret, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashaddr[i].cashaddress, 92), 0);
|
||||
}
|
||||
START_TEST(test_cashaddr) {
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(valid_cashchecksum) / sizeof(valid_cashchecksum[0]);
|
||||
++i) {
|
||||
uint8_t data[82];
|
||||
char rebuild[92];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = cash_decode(hrp, data, &data_len, valid_cashchecksum[i]);
|
||||
ck_assert_int_eq(res, 1);
|
||||
res = cash_encode(rebuild, hrp, data, data_len);
|
||||
ck_assert_int_eq(res, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashchecksum[i], 92), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(valid_cashaddr) / sizeof(valid_cashaddr[0]); ++i) {
|
||||
uint8_t prog[65];
|
||||
size_t prog_len;
|
||||
const char* hrp = "bitcoincash";
|
||||
uint8_t rawdata[65];
|
||||
size_t rawdata_len;
|
||||
char rebuild[93];
|
||||
int ret =
|
||||
cash_addr_decode(prog, &prog_len, hrp, valid_cashaddr[i].cashaddress);
|
||||
ck_assert_int_eq(ret, 1);
|
||||
ck_assert_int_eq(prog_len, 21);
|
||||
rawdata_len = base58_decode_check(valid_cashaddr[i].legacy, HASHER_SHA2D,
|
||||
rawdata, sizeof(rawdata));
|
||||
ck_assert_int_eq(rawdata_len, 21);
|
||||
ck_assert_int_eq(prog[0],
|
||||
rawdata[0] == 0 ? 0x00 : rawdata[0] == 5 ? 0x08 : -1);
|
||||
ck_assert_int_eq(memcmp(rawdata + 1, prog + 1, 20), 0);
|
||||
ret = cash_addr_encode(rebuild, hrp, prog, 21);
|
||||
ck_assert_int_eq(ret, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_cashaddr[i].cashaddress, 92),
|
||||
0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,184 +1,160 @@
|
||||
#include "segwit_addr.h"
|
||||
|
||||
static const char* valid_checksum[] = {
|
||||
"A12UEL5L",
|
||||
"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs",
|
||||
"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
|
||||
"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j",
|
||||
"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
|
||||
"A12UEL5L",
|
||||
"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedchar"
|
||||
"actersbio1tt5tgs",
|
||||
"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
|
||||
"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
|
||||
"qqqqqqqqqqc8247j",
|
||||
"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
|
||||
};
|
||||
|
||||
static const char* invalid_checksum[] = {
|
||||
" 1nwldj5",
|
||||
"\x7f""1axkwrx",
|
||||
"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx",
|
||||
"pzry9x0s0muk",
|
||||
"1pzry9x0s0muk",
|
||||
"x1b4n0q5v",
|
||||
"li1dgmt3",
|
||||
"de1lg7wt\xff",
|
||||
" 1nwldj5",
|
||||
"\x7f"
|
||||
"1axkwrx",
|
||||
"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcha"
|
||||
"ractersbio1569pvx",
|
||||
"pzry9x0s0muk",
|
||||
"1pzry9x0s0muk",
|
||||
"x1b4n0q5v",
|
||||
"li1dgmt3",
|
||||
"de1lg7wt\xff",
|
||||
};
|
||||
|
||||
struct valid_address_data {
|
||||
const char* address;
|
||||
size_t scriptPubKeyLen;
|
||||
const uint8_t scriptPubKey[42];
|
||||
const char* address;
|
||||
size_t scriptPubKeyLen;
|
||||
const uint8_t scriptPubKey[42];
|
||||
};
|
||||
|
||||
struct invalid_address_data {
|
||||
const char* hrp;
|
||||
int version;
|
||||
size_t program_length;
|
||||
const char* hrp;
|
||||
int version;
|
||||
size_t program_length;
|
||||
};
|
||||
|
||||
static struct valid_address_data valid_address[] = {
|
||||
{
|
||||
"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
|
||||
22, {
|
||||
0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
||||
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6
|
||||
}
|
||||
},
|
||||
{
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
||||
34, {
|
||||
0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04,
|
||||
0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78,
|
||||
0xcd, 0x4d, 0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32,
|
||||
0x62
|
||||
}
|
||||
},
|
||||
{
|
||||
"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
|
||||
42, {
|
||||
0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
||||
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6,
|
||||
0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c,
|
||||
0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6
|
||||
}
|
||||
},
|
||||
{
|
||||
"BC1SW50QA3JX3S",
|
||||
4, {
|
||||
0x60, 0x02, 0x75, 0x1e
|
||||
}
|
||||
},
|
||||
{
|
||||
"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
|
||||
18, {
|
||||
0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
||||
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23
|
||||
}
|
||||
},
|
||||
{
|
||||
"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
|
||||
34, {
|
||||
0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21,
|
||||
0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5,
|
||||
0xe9, 0x1c, 0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64,
|
||||
0x33
|
||||
}
|
||||
}
|
||||
};
|
||||
{"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
|
||||
22,
|
||||
{0x00, 0x14, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
||||
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}},
|
||||
{"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
|
||||
34,
|
||||
{0x00, 0x20, 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, 0x04, 0xbd,
|
||||
0x19, 0x20, 0x33, 0x56, 0xda, 0x13, 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d,
|
||||
0x27, 0xa1, 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}},
|
||||
{"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grpl"
|
||||
"x",
|
||||
42,
|
||||
{0x51, 0x28, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54,
|
||||
0x94, 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6,
|
||||
0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, 0x1c,
|
||||
0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}},
|
||||
{"BC1SW50QA3JX3S", 4, {0x60, 0x02, 0x75, 0x1e}},
|
||||
{"bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
|
||||
18,
|
||||
{0x52, 0x10, 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94,
|
||||
0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23}},
|
||||
{"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
|
||||
34,
|
||||
{0x00, 0x20, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, 0x21, 0xb2,
|
||||
0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c,
|
||||
0x6c, 0xe2, 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}}};
|
||||
|
||||
static const char* invalid_address[] = {
|
||||
"tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
|
||||
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5",
|
||||
"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
|
||||
"bc1rw5uspcuh",
|
||||
"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90",
|
||||
"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
|
||||
"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du",
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
|
||||
"bc1gmk9yu",
|
||||
"tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty",
|
||||
"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5",
|
||||
"BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2",
|
||||
"bc1rw5uspcuh",
|
||||
"bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs"
|
||||
"90",
|
||||
"BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P",
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7",
|
||||
"bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du",
|
||||
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv",
|
||||
"bc1gmk9yu",
|
||||
};
|
||||
|
||||
static struct invalid_address_data invalid_address_enc[] = {
|
||||
{"BC", 0, 20},
|
||||
{"bc", 0, 21},
|
||||
{"bc", 17, 32},
|
||||
{"bc", 1, 1},
|
||||
{"bc", 16, 41},
|
||||
{"BC", 0, 20}, {"bc", 0, 21}, {"bc", 17, 32}, {"bc", 1, 1}, {"bc", 16, 41},
|
||||
};
|
||||
|
||||
static void segwit_scriptpubkey(uint8_t* scriptpubkey, size_t* scriptpubkeylen, int witver, const uint8_t* witprog, size_t witprog_len) {
|
||||
scriptpubkey[0] = witver ? (0x50 + witver) : 0;
|
||||
scriptpubkey[1] = witprog_len;
|
||||
memcpy(scriptpubkey + 2, witprog, witprog_len);
|
||||
*scriptpubkeylen = witprog_len + 2;
|
||||
static void segwit_scriptpubkey(uint8_t* scriptpubkey, size_t* scriptpubkeylen,
|
||||
int witver, const uint8_t* witprog,
|
||||
size_t witprog_len) {
|
||||
scriptpubkey[0] = witver ? (0x50 + witver) : 0;
|
||||
scriptpubkey[1] = witprog_len;
|
||||
memcpy(scriptpubkey + 2, witprog, witprog_len);
|
||||
*scriptpubkeylen = witprog_len + 2;
|
||||
}
|
||||
|
||||
int my_strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
size_t i = 0;
|
||||
while (i < n) {
|
||||
char c1 = s1[i];
|
||||
char c2 = s2[i];
|
||||
if (c1 >= 'A' && c1 <= 'Z') c1 = (c1 - 'A') + 'a';
|
||||
if (c2 >= 'A' && c2 <= 'Z') c2 = (c2 - 'A') + 'a';
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
if (c1 == 0) return 0;
|
||||
++i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
START_TEST(test_segwit)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(valid_checksum) / sizeof(valid_checksum[0]); ++i) {
|
||||
uint8_t data[82];
|
||||
char rebuild[92];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = bech32_decode(hrp, data, &data_len, valid_checksum[i]);
|
||||
ck_assert_int_eq(res, 1);
|
||||
res = bech32_encode(rebuild, hrp, data, data_len);
|
||||
ck_assert_int_eq(res, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_checksum[i], 92), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_checksum) / sizeof(invalid_checksum[0]); ++i) {
|
||||
uint8_t data[82];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = bech32_decode(hrp, data, &data_len, invalid_checksum[i]);
|
||||
ck_assert_int_eq(res, 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(valid_address) / sizeof(valid_address[0]); ++i) {
|
||||
uint8_t witprog[40];
|
||||
size_t witprog_len;
|
||||
int witver;
|
||||
const char* hrp = "bc";
|
||||
uint8_t scriptpubkey[42];
|
||||
size_t scriptpubkey_len;
|
||||
char rebuild[93];
|
||||
int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, valid_address[i].address);
|
||||
if (!ret) {
|
||||
hrp = "tb";
|
||||
ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp, valid_address[i].address);
|
||||
}
|
||||
ck_assert_int_eq(ret, 1);
|
||||
segwit_scriptpubkey(scriptpubkey, &scriptpubkey_len, witver, witprog, witprog_len);
|
||||
ck_assert_int_eq(scriptpubkey_len, valid_address[i].scriptPubKeyLen);
|
||||
ck_assert_int_eq(memcmp(scriptpubkey, valid_address[i].scriptPubKey, scriptpubkey_len), 0);
|
||||
ck_assert_int_eq(segwit_addr_encode(rebuild, hrp, witver, witprog, witprog_len), 1);
|
||||
ck_assert_int_eq(my_strncasecmp(valid_address[i].address, rebuild, 93), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_address) / sizeof(invalid_address[0]); ++i) {
|
||||
uint8_t witprog[40];
|
||||
size_t witprog_len;
|
||||
int witver;
|
||||
int ret = segwit_addr_decode(&witver, witprog, &witprog_len, "bc", invalid_address[i]);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ret = segwit_addr_decode(&witver, witprog, &witprog_len, "tb", invalid_address[i]);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_address_enc) / sizeof(invalid_address_enc[0]); ++i) {
|
||||
char rebuild[93];
|
||||
static const uint8_t program[42] = {0};
|
||||
int ret = segwit_addr_encode(rebuild, invalid_address_enc[i].hrp, invalid_address_enc[i].version, program, invalid_address_enc[i].program_length);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
START_TEST(test_segwit) {
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(valid_checksum) / sizeof(valid_checksum[0]); ++i) {
|
||||
uint8_t data[82];
|
||||
char rebuild[92];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = bech32_decode(hrp, data, &data_len, valid_checksum[i]);
|
||||
ck_assert_int_eq(res, 1);
|
||||
res = bech32_encode(rebuild, hrp, data, data_len);
|
||||
ck_assert_int_eq(res, 1);
|
||||
ck_assert_int_eq(my_strncasecmp(rebuild, valid_checksum[i], 92), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_checksum) / sizeof(invalid_checksum[0]); ++i) {
|
||||
uint8_t data[82];
|
||||
char hrp[84];
|
||||
size_t data_len;
|
||||
int res = bech32_decode(hrp, data, &data_len, invalid_checksum[i]);
|
||||
ck_assert_int_eq(res, 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(valid_address) / sizeof(valid_address[0]); ++i) {
|
||||
uint8_t witprog[40];
|
||||
size_t witprog_len;
|
||||
int witver;
|
||||
const char* hrp = "bc";
|
||||
uint8_t scriptpubkey[42];
|
||||
size_t scriptpubkey_len;
|
||||
char rebuild[93];
|
||||
int ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp,
|
||||
valid_address[i].address);
|
||||
if (!ret) {
|
||||
hrp = "tb";
|
||||
ret = segwit_addr_decode(&witver, witprog, &witprog_len, hrp,
|
||||
valid_address[i].address);
|
||||
}
|
||||
ck_assert_int_eq(ret, 1);
|
||||
segwit_scriptpubkey(scriptpubkey, &scriptpubkey_len, witver, witprog,
|
||||
witprog_len);
|
||||
ck_assert_int_eq(scriptpubkey_len, valid_address[i].scriptPubKeyLen);
|
||||
ck_assert_int_eq(
|
||||
memcmp(scriptpubkey, valid_address[i].scriptPubKey, scriptpubkey_len),
|
||||
0);
|
||||
ck_assert_int_eq(
|
||||
segwit_addr_encode(rebuild, hrp, witver, witprog, witprog_len), 1);
|
||||
ck_assert_int_eq(my_strncasecmp(valid_address[i].address, rebuild, 93), 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_address) / sizeof(invalid_address[0]); ++i) {
|
||||
uint8_t witprog[40];
|
||||
size_t witprog_len;
|
||||
int witver;
|
||||
int ret = segwit_addr_decode(&witver, witprog, &witprog_len, "bc",
|
||||
invalid_address[i]);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
ret = segwit_addr_decode(&witver, witprog, &witprog_len, "tb",
|
||||
invalid_address[i]);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
for (i = 0; i < sizeof(invalid_address_enc) / sizeof(invalid_address_enc[0]);
|
||||
++i) {
|
||||
char rebuild[93];
|
||||
static const uint8_t program[42] = {0};
|
||||
int ret = segwit_addr_encode(rebuild, invalid_address_enc[i].hrp,
|
||||
invalid_address_enc[i].version, program,
|
||||
invalid_address_enc[i].program_length);
|
||||
ck_assert_int_eq(ret, 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
@ -27,118 +27,117 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/obj_mac.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/sha.h>
|
||||
#undef SHA256_CTX
|
||||
#undef SHA512_CTX
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ecdsa.h"
|
||||
#include "rand.h"
|
||||
#include "hasher.h"
|
||||
#include "rand.h"
|
||||
|
||||
#include "nist256p1.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
#include "memzero.h"
|
||||
|
||||
void openssl_check(unsigned int iterations, int nid, const ecdsa_curve *curve)
|
||||
{
|
||||
uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256], hash[32];
|
||||
struct SHA256state_st sha256;
|
||||
EC_GROUP *ecgroup;
|
||||
void openssl_check(unsigned int iterations, int nid, const ecdsa_curve *curve) {
|
||||
uint8_t sig[64], pub_key33[33], pub_key65[65], priv_key[32], msg[256],
|
||||
hash[32];
|
||||
struct SHA256state_st sha256;
|
||||
EC_GROUP *ecgroup;
|
||||
|
||||
ecgroup = EC_GROUP_new_by_curve_name(nid);
|
||||
ecgroup = EC_GROUP_new_by_curve_name(nid);
|
||||
|
||||
for (unsigned int iter = 0; iter < iterations; iter++) {
|
||||
for (unsigned int iter = 0; iter < iterations; iter++) {
|
||||
// random message len between 1 and 256
|
||||
int msg_len = (random32() & 0xFF) + 1;
|
||||
// create random message
|
||||
random_buffer(msg, msg_len);
|
||||
|
||||
// random message len between 1 and 256
|
||||
int msg_len = (random32() & 0xFF) + 1;
|
||||
// create random message
|
||||
random_buffer(msg, msg_len);
|
||||
// new ECDSA key
|
||||
EC_KEY *eckey = EC_KEY_new();
|
||||
EC_KEY_set_group(eckey, ecgroup);
|
||||
|
||||
// new ECDSA key
|
||||
EC_KEY *eckey = EC_KEY_new();
|
||||
EC_KEY_set_group(eckey, ecgroup);
|
||||
// generate the key
|
||||
EC_KEY_generate_key(eckey);
|
||||
// copy key to buffer
|
||||
const BIGNUM *K = EC_KEY_get0_private_key(eckey);
|
||||
int bn_off = sizeof(priv_key) - BN_num_bytes(K);
|
||||
memzero(priv_key, bn_off);
|
||||
BN_bn2bin(K, priv_key + bn_off);
|
||||
|
||||
// generate the key
|
||||
EC_KEY_generate_key(eckey);
|
||||
// copy key to buffer
|
||||
const BIGNUM *K = EC_KEY_get0_private_key(eckey);
|
||||
int bn_off = sizeof(priv_key) - BN_num_bytes(K);
|
||||
memzero(priv_key, bn_off);
|
||||
BN_bn2bin(K, priv_key + bn_off);
|
||||
// use our ECDSA signer to sign the message with the key
|
||||
if (ecdsa_sign(curve, HASHER_SHA2, priv_key, msg, msg_len, sig, NULL,
|
||||
NULL) != 0) {
|
||||
printf("trezor-crypto signing failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// use our ECDSA signer to sign the message with the key
|
||||
if (ecdsa_sign(curve, HASHER_SHA2, priv_key, msg, msg_len, sig, NULL, NULL) != 0) {
|
||||
printf("trezor-crypto signing failed\n");
|
||||
return;
|
||||
}
|
||||
// generate public key from private key
|
||||
ecdsa_get_public_key33(curve, priv_key, pub_key33);
|
||||
ecdsa_get_public_key65(curve, priv_key, pub_key65);
|
||||
|
||||
// generate public key from private key
|
||||
ecdsa_get_public_key33(curve, priv_key, pub_key33);
|
||||
ecdsa_get_public_key65(curve, priv_key, pub_key65);
|
||||
// use our ECDSA verifier to verify the message signature
|
||||
if (ecdsa_verify(curve, HASHER_SHA2, pub_key65, sig, msg, msg_len) != 0) {
|
||||
printf("trezor-crypto verification failed (pub_key_len = 65)\n");
|
||||
return;
|
||||
}
|
||||
if (ecdsa_verify(curve, HASHER_SHA2, pub_key33, sig, msg, msg_len) != 0) {
|
||||
printf("trezor-crypto verification failed (pub_key_len = 33)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// use our ECDSA verifier to verify the message signature
|
||||
if (ecdsa_verify(curve, HASHER_SHA2, pub_key65, sig, msg, msg_len) != 0) {
|
||||
printf("trezor-crypto verification failed (pub_key_len = 65)\n");
|
||||
return;
|
||||
}
|
||||
if (ecdsa_verify(curve, HASHER_SHA2, pub_key33, sig, msg, msg_len) != 0) {
|
||||
printf("trezor-crypto verification failed (pub_key_len = 33)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy signature to the OpenSSL struct
|
||||
ECDSA_SIG *signature = ECDSA_SIG_new();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
BN_bin2bn(sig, 32, signature->r);
|
||||
BN_bin2bn(sig + 32, 32, signature->s);
|
||||
// copy signature to the OpenSSL struct
|
||||
ECDSA_SIG *signature = ECDSA_SIG_new();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
BN_bin2bn(sig, 32, signature->r);
|
||||
BN_bin2bn(sig + 32, 32, signature->s);
|
||||
#else
|
||||
BIGNUM *R = BN_bin2bn(sig, 32, NULL);
|
||||
BIGNUM *S = BN_bin2bn(sig + 32, 32, NULL);
|
||||
ECDSA_SIG_set0(signature, R, S);
|
||||
BIGNUM *R = BN_bin2bn(sig, 32, NULL);
|
||||
BIGNUM *S = BN_bin2bn(sig + 32, 32, NULL);
|
||||
ECDSA_SIG_set0(signature, R, S);
|
||||
#endif
|
||||
|
||||
// compute the digest of the message
|
||||
// note: these are OpenSSL functions, not our own
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, msg, msg_len);
|
||||
SHA256_Final(hash, &sha256);
|
||||
// compute the digest of the message
|
||||
// note: these are OpenSSL functions, not our own
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, msg, msg_len);
|
||||
SHA256_Final(hash, &sha256);
|
||||
|
||||
// verify all went well, i.e. we can decrypt our signature with OpenSSL
|
||||
int v = ECDSA_do_verify(hash, 32, signature, eckey);
|
||||
if (v != 1) {
|
||||
printf("OpenSSL verification failed (%d)\n", v);
|
||||
return;
|
||||
}
|
||||
// verify all went well, i.e. we can decrypt our signature with OpenSSL
|
||||
int v = ECDSA_do_verify(hash, 32, signature, eckey);
|
||||
if (v != 1) {
|
||||
printf("OpenSSL verification failed (%d)\n", v);
|
||||
return;
|
||||
}
|
||||
|
||||
ECDSA_SIG_free(signature);
|
||||
EC_KEY_free(eckey);
|
||||
if (((iter + 1) % 100) == 0) printf("Passed ... %d\n", iter + 1);
|
||||
}
|
||||
EC_GROUP_free(ecgroup);
|
||||
printf("All OK\n");
|
||||
ECDSA_SIG_free(signature);
|
||||
EC_KEY_free(eckey);
|
||||
if (((iter + 1) % 100) == 0) printf("Passed ... %d\n", iter + 1);
|
||||
}
|
||||
EC_GROUP_free(ecgroup);
|
||||
printf("All OK\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("Usage: test_openssl iterations\n");
|
||||
return 1;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
printf("Usage: test_openssl iterations\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int iterations;
|
||||
sscanf(argv[1], "%u", &iterations);
|
||||
unsigned int iterations;
|
||||
sscanf(argv[1], "%u", &iterations);
|
||||
|
||||
printf("Testing secp256k1:\n");
|
||||
openssl_check(iterations, NID_secp256k1, &secp256k1);
|
||||
printf("Testing secp256k1:\n");
|
||||
openssl_check(iterations, NID_secp256k1, &secp256k1);
|
||||
|
||||
printf("Testing nist256p1:\n");
|
||||
openssl_check(iterations, NID_X9_62_prime256v1, &nist256p1);
|
||||
printf("Testing nist256p1:\n");
|
||||
openssl_check(iterations, NID_X9_62_prime256v1, &nist256p1);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,215 +1,233 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "bip32.h"
|
||||
#include "curves.h"
|
||||
#include "ecdsa.h"
|
||||
#include "bip32.h"
|
||||
#include "secp256k1.h"
|
||||
#include "nist256p1.h"
|
||||
#include "ed25519-donna/ed25519.h"
|
||||
#include "hasher.h"
|
||||
#include "nist256p1.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
static uint8_t msg[256];
|
||||
|
||||
void prepare_msg(void)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(msg); i++) {
|
||||
msg[i] = i * 1103515245;
|
||||
}
|
||||
void prepare_msg(void) {
|
||||
for (size_t i = 0; i < sizeof(msg); i++) {
|
||||
msg[i] = i * 1103515245;
|
||||
}
|
||||
}
|
||||
|
||||
void bench_sign_secp256k1(int iterations)
|
||||
{
|
||||
uint8_t sig[64], priv[32], pby;
|
||||
void bench_sign_secp256k1(int iterations) {
|
||||
uint8_t sig[64], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_sign_nist256p1(int iterations)
|
||||
{
|
||||
uint8_t sig[64], priv[32], pby;
|
||||
void bench_sign_nist256p1(int iterations) {
|
||||
uint8_t sig[64], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_sign_ed25519(int iterations)
|
||||
{
|
||||
ed25519_public_key pk;
|
||||
ed25519_secret_key sk;
|
||||
ed25519_signature sig;
|
||||
void bench_sign_ed25519(int iterations) {
|
||||
ed25519_public_key pk;
|
||||
ed25519_secret_key sk;
|
||||
ed25519_signature sig;
|
||||
|
||||
memcpy(pk, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ed25519_publickey(sk, pk);
|
||||
memcpy(pk,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ed25519_publickey(sk, pk);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ed25519_sign(msg, sizeof(msg), sk, pk, sig);
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ed25519_sign(msg, sizeof(msg), sk, pk, sig);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_verify_secp256k1_33(int iterations)
|
||||
{
|
||||
uint8_t sig[64], pub[33], priv[32], pby;
|
||||
void bench_verify_secp256k1_33(int iterations) {
|
||||
uint8_t sig[64], pub[33], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ecdsa_get_public_key33(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ecdsa_get_public_key33(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_verify_secp256k1_65(int iterations)
|
||||
{
|
||||
uint8_t sig[64], pub[65], priv[32], pby;
|
||||
void bench_verify_secp256k1_65(int iterations) {
|
||||
uint8_t sig[64], pub[65], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
const ecdsa_curve *curve = &secp256k1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ecdsa_get_public_key65(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ecdsa_get_public_key65(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_verify_nist256p1_33(int iterations)
|
||||
{
|
||||
uint8_t sig[64], pub[33], priv[32], pby;
|
||||
void bench_verify_nist256p1_33(int iterations) {
|
||||
uint8_t sig[64], pub[33], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ecdsa_get_public_key33(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ecdsa_get_public_key33(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_verify_nist256p1_65(int iterations)
|
||||
{
|
||||
uint8_t sig[64], pub[65], priv[32], pby;
|
||||
void bench_verify_nist256p1_65(int iterations) {
|
||||
uint8_t sig[64], pub[65], priv[32], pby;
|
||||
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
const ecdsa_curve *curve = &nist256p1;
|
||||
|
||||
memcpy(priv, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ecdsa_get_public_key65(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
memcpy(priv,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ecdsa_get_public_key65(curve, priv, pub);
|
||||
ecdsa_sign(curve, HASHER_SHA2, priv, msg, sizeof(msg), sig, &pby, NULL);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ecdsa_verify(curve, HASHER_SHA2, pub, sig, msg, sizeof(msg));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_verify_ed25519(int iterations)
|
||||
{
|
||||
ed25519_public_key pk;
|
||||
ed25519_secret_key sk;
|
||||
ed25519_signature sig;
|
||||
void bench_verify_ed25519(int iterations) {
|
||||
ed25519_public_key pk;
|
||||
ed25519_secret_key sk;
|
||||
ed25519_signature sig;
|
||||
|
||||
memcpy(pk, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
ed25519_publickey(sk, pk);
|
||||
ed25519_sign(msg, sizeof(msg), sk, pk, sig);
|
||||
memcpy(pk,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
ed25519_publickey(sk, pk);
|
||||
ed25519_sign(msg, sizeof(msg), sk, pk, sig);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
ed25519_sign_open(msg, sizeof(msg), pk, sig);
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
ed25519_sign_open(msg, sizeof(msg), pk, sig);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_multiply_curve25519(int iterations)
|
||||
{
|
||||
uint8_t result[32];
|
||||
uint8_t secret[32];
|
||||
uint8_t basepoint[32];
|
||||
void bench_multiply_curve25519(int iterations) {
|
||||
uint8_t result[32];
|
||||
uint8_t secret[32];
|
||||
uint8_t basepoint[32];
|
||||
|
||||
memcpy(secret, "\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5", 32);
|
||||
memcpy(basepoint, "\x96\x47\xda\xbe\x1e\xea\xaf\x25\x47\x1e\x68\x0b\x4d\x7c\x6f\xd1\x14\x38\x76\xbb\x77\x59\xd8\x3d\x0f\xf7\xa2\x49\x08\xfd\xda\xbc", 32);
|
||||
memcpy(secret,
|
||||
"\xc5\x5e\xce\x85\x8b\x0d\xdd\x52\x63\xf9\x68\x10\xfe\x14\x43\x7c\xd3"
|
||||
"\xb5\xe1\xfb\xd7\xc6\xa2\xec\x1e\x03\x1f\x05\xe8\x6d\x8b\xd5",
|
||||
32);
|
||||
memcpy(basepoint,
|
||||
"\x96\x47\xda\xbe\x1e\xea\xaf\x25\x47\x1e\x68\x0b\x4d\x7c\x6f\xd1\x14"
|
||||
"\x38\x76\xbb\x77\x59\xd8\x3d\x0f\xf7\xa2\x49\x08\xfd\xda\xbc",
|
||||
32);
|
||||
|
||||
for (int i = 0 ; i < iterations; i++) {
|
||||
curve25519_scalarmult(result, secret, basepoint);
|
||||
}
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
curve25519_scalarmult(result, secret, basepoint);
|
||||
}
|
||||
}
|
||||
|
||||
static HDNode root;
|
||||
|
||||
void prepare_node(void)
|
||||
{
|
||||
hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root);
|
||||
hdnode_fill_public_key(&root);
|
||||
void prepare_node(void) {
|
||||
hdnode_from_seed((uint8_t *)"NothingToSeeHere", 16, SECP256K1_NAME, &root);
|
||||
hdnode_fill_public_key(&root);
|
||||
}
|
||||
|
||||
void bench_ckd_normal(int iterations)
|
||||
{
|
||||
char addr[MAX_ADDR_SIZE];
|
||||
HDNode node;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
memcpy(&node, &root, sizeof(HDNode));
|
||||
hdnode_public_ckd(&node, i);
|
||||
hdnode_fill_public_key(&node);
|
||||
ecdsa_get_address(node.public_key, HASHER_SHA2, HASHER_SHA2D, 0, addr, sizeof(addr));
|
||||
}
|
||||
void bench_ckd_normal(int iterations) {
|
||||
char addr[MAX_ADDR_SIZE];
|
||||
HDNode node;
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
memcpy(&node, &root, sizeof(HDNode));
|
||||
hdnode_public_ckd(&node, i);
|
||||
hdnode_fill_public_key(&node);
|
||||
ecdsa_get_address(node.public_key, HASHER_SHA2, HASHER_SHA2D, 0, addr,
|
||||
sizeof(addr));
|
||||
}
|
||||
}
|
||||
|
||||
void bench_ckd_optimized(int iterations)
|
||||
{
|
||||
char addr[MAX_ADDR_SIZE];
|
||||
curve_point pub;
|
||||
ecdsa_read_pubkey(&secp256k1, root.public_key, &pub);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0, HASHER_SHA2, HASHER_SHA2D, addr, sizeof(addr), false);
|
||||
}
|
||||
void bench_ckd_optimized(int iterations) {
|
||||
char addr[MAX_ADDR_SIZE];
|
||||
curve_point pub;
|
||||
ecdsa_read_pubkey(&secp256k1, root.public_key, &pub);
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
hdnode_public_ckd_address_optimized(&pub, root.chain_code, i, 0,
|
||||
HASHER_SHA2, HASHER_SHA2D, addr,
|
||||
sizeof(addr), false);
|
||||
}
|
||||
}
|
||||
|
||||
void bench(void (*func)(int), const char *name, int iterations)
|
||||
{
|
||||
clock_t t = clock();
|
||||
func(iterations);
|
||||
float speed = iterations / ((float)(clock() - t) / CLOCKS_PER_SEC);
|
||||
printf("%25s: %8.2f ops/s\n", name, speed);
|
||||
void bench(void (*func)(int), const char *name, int iterations) {
|
||||
clock_t t = clock();
|
||||
func(iterations);
|
||||
float speed = iterations / ((float)(clock() - t) / CLOCKS_PER_SEC);
|
||||
printf("%25s: %8.2f ops/s\n", name, speed);
|
||||
}
|
||||
|
||||
#define BENCH(FUNC, ITER) bench(FUNC, #FUNC, ITER)
|
||||
|
||||
int main(void) {
|
||||
prepare_msg();
|
||||
|
||||
prepare_msg();
|
||||
BENCH(bench_sign_secp256k1, 500);
|
||||
BENCH(bench_verify_secp256k1_33, 500);
|
||||
BENCH(bench_verify_secp256k1_65, 500);
|
||||
|
||||
BENCH(bench_sign_secp256k1, 500);
|
||||
BENCH(bench_verify_secp256k1_33, 500);
|
||||
BENCH(bench_verify_secp256k1_65, 500);
|
||||
BENCH(bench_sign_nist256p1, 500);
|
||||
BENCH(bench_verify_nist256p1_33, 500);
|
||||
BENCH(bench_verify_nist256p1_65, 500);
|
||||
|
||||
BENCH(bench_sign_nist256p1, 500);
|
||||
BENCH(bench_verify_nist256p1_33, 500);
|
||||
BENCH(bench_verify_nist256p1_65, 500);
|
||||
BENCH(bench_sign_ed25519, 4000);
|
||||
BENCH(bench_verify_ed25519, 4000);
|
||||
|
||||
BENCH(bench_sign_ed25519, 4000);
|
||||
BENCH(bench_verify_ed25519, 4000);
|
||||
BENCH(bench_multiply_curve25519, 4000);
|
||||
|
||||
BENCH(bench_multiply_curve25519, 4000);
|
||||
prepare_node();
|
||||
|
||||
prepare_node();
|
||||
BENCH(bench_ckd_normal, 1000);
|
||||
BENCH(bench_ckd_optimized, 1000);
|
||||
|
||||
BENCH(bench_ckd_normal, 1000);
|
||||
BENCH(bench_ckd_optimized, 1000);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include "bip39.h"
|
||||
#include <time.h>
|
||||
#include "bip32.h"
|
||||
#include "ecdsa.h"
|
||||
#include "bip39.h"
|
||||
#include "curves.h"
|
||||
#include "ecdsa.h"
|
||||
#include "secp256k1.h"
|
||||
|
||||
char iter[256];
|
||||
@ -26,63 +26,64 @@ clock_t start;
|
||||
// address: "1N3uJ5AU3FTYQ1ZQgTMtYmgSvMBmQiGVBS"
|
||||
// passphrase: "testing"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n");
|
||||
return 1;
|
||||
}
|
||||
const char *address = argv[1];
|
||||
const char *mnemonic, *item;
|
||||
if (argc == 3) {
|
||||
mnemonic = argv[2];
|
||||
item = "passphrase";
|
||||
} else {
|
||||
mnemonic = NULL;
|
||||
item = "mnemonic";
|
||||
}
|
||||
if (mnemonic && !mnemonic_check(mnemonic)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic);
|
||||
return 2;
|
||||
}
|
||||
if (!ecdsa_address_decode(address, 0, secp256k1_info.hasher_base58, addr)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid address\n", address);
|
||||
return 3;
|
||||
}
|
||||
printf("Reading %ss from stdin ...\n", item);
|
||||
start = clock();
|
||||
for (;;) {
|
||||
if (fgets(iter, 256, stdin) == NULL) break;
|
||||
int len = strlen(iter);
|
||||
if (len <= 0) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
iter[len - 1] = 0;
|
||||
if (mnemonic) {
|
||||
mnemonic_to_seed(mnemonic, iter, seed, NULL);
|
||||
} else {
|
||||
mnemonic_to_seed(iter, "", seed, NULL);
|
||||
}
|
||||
hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node);
|
||||
hdnode_private_ckd_prime(&node, 44);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_fill_public_key(&node);
|
||||
ecdsa_get_pubkeyhash(node.public_key, secp256k1_info.hasher_pubkey, pubkeyhash);
|
||||
if (memcmp(addr + 1, pubkeyhash, 20) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float dur = (float)(clock() - start) / CLOCKS_PER_SEC;
|
||||
printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur, (float)count/dur);
|
||||
if (found) {
|
||||
printf("Correct %s found! :-)\n\"%s\"\n", item, iter);
|
||||
return 0;
|
||||
}
|
||||
printf("Correct %s not found. :-(\n", item);
|
||||
return 4;
|
||||
int main(int argc, char **argv) {
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage: bip39bruteforce address [mnemonic]\n");
|
||||
return 1;
|
||||
}
|
||||
const char *address = argv[1];
|
||||
const char *mnemonic, *item;
|
||||
if (argc == 3) {
|
||||
mnemonic = argv[2];
|
||||
item = "passphrase";
|
||||
} else {
|
||||
mnemonic = NULL;
|
||||
item = "mnemonic";
|
||||
}
|
||||
if (mnemonic && !mnemonic_check(mnemonic)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid mnemonic\n", mnemonic);
|
||||
return 2;
|
||||
}
|
||||
if (!ecdsa_address_decode(address, 0, secp256k1_info.hasher_base58, addr)) {
|
||||
fprintf(stderr, "\"%s\" is not a valid address\n", address);
|
||||
return 3;
|
||||
}
|
||||
printf("Reading %ss from stdin ...\n", item);
|
||||
start = clock();
|
||||
for (;;) {
|
||||
if (fgets(iter, 256, stdin) == NULL) break;
|
||||
int len = strlen(iter);
|
||||
if (len <= 0) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
iter[len - 1] = 0;
|
||||
if (mnemonic) {
|
||||
mnemonic_to_seed(mnemonic, iter, seed, NULL);
|
||||
} else {
|
||||
mnemonic_to_seed(iter, "", seed, NULL);
|
||||
}
|
||||
hdnode_from_seed(seed, 512 / 8, SECP256K1_NAME, &node);
|
||||
hdnode_private_ckd_prime(&node, 44);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd_prime(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_private_ckd(&node, 0);
|
||||
hdnode_fill_public_key(&node);
|
||||
ecdsa_get_pubkeyhash(node.public_key, secp256k1_info.hasher_pubkey,
|
||||
pubkeyhash);
|
||||
if (memcmp(addr + 1, pubkeyhash, 20) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float dur = (float)(clock() - start) / CLOCKS_PER_SEC;
|
||||
printf("Tried %d %ss in %f seconds = %f tries/second\n", count, item, dur,
|
||||
(float)count / dur);
|
||||
if (found) {
|
||||
printf("Correct %s found! :-)\n\"%s\"\n", item, iter);
|
||||
return 0;
|
||||
}
|
||||
printf("Correct %s not found. :-(\n", item);
|
||||
return 4;
|
||||
}
|
||||
|
106
tools/mktable.c
106
tools/mktable.c
@ -1,8 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "bignum.h"
|
||||
#include "ecdsa.h"
|
||||
#include "bip32.h"
|
||||
#include "ecdsa.h"
|
||||
#include "rand.h"
|
||||
|
||||
/*
|
||||
@ -11,58 +11,58 @@
|
||||
* where G is the generator of the specified elliptic curve.
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
int i,j,k;
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s CURVE_NAME\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
const char *name = argv[1];
|
||||
const curve_info *info = get_curve_by_name(name);
|
||||
const ecdsa_curve *curve = info->params;
|
||||
if (curve == 0) {
|
||||
printf("Unknown curve '%s'\n", name);
|
||||
return 1;
|
||||
}
|
||||
int i, j, k;
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s CURVE_NAME\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
const char *name = argv[1];
|
||||
const curve_info *info = get_curve_by_name(name);
|
||||
const ecdsa_curve *curve = info->params;
|
||||
if (curve == 0) {
|
||||
printf("Unknown curve '%s'\n", name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
curve_point ng = curve->G;
|
||||
curve_point pow2ig = curve->G;
|
||||
for (i = 0; i < 64; i++) {
|
||||
// invariants:
|
||||
// pow2ig = 16^i * G
|
||||
// ng = pow2ig
|
||||
printf("\t{\n");
|
||||
for (j = 0; j < 8; j++) {
|
||||
// invariants:
|
||||
// pow2ig = 16^i * G
|
||||
// ng = (2*j+1) * 16^i * G
|
||||
curve_point ng = curve->G;
|
||||
curve_point pow2ig = curve->G;
|
||||
for (i = 0; i < 64; i++) {
|
||||
// invariants:
|
||||
// pow2ig = 16^i * G
|
||||
// ng = pow2ig
|
||||
printf("\t{\n");
|
||||
for (j = 0; j < 8; j++) {
|
||||
// invariants:
|
||||
// pow2ig = 16^i * G
|
||||
// ng = (2*j+1) * 16^i * G
|
||||
#ifndef NDEBUG
|
||||
curve_point checkresult;
|
||||
bignum256 a;
|
||||
bn_zero(&a);
|
||||
a.val[(4*i) / 30] = ((uint32_t) 2*j+1) << ((4*i) % 30);
|
||||
bn_normalize(&a);
|
||||
point_multiply(curve, &a, &curve->G, &checkresult);
|
||||
assert(point_is_equal(&checkresult, &ng));
|
||||
curve_point checkresult;
|
||||
bignum256 a;
|
||||
bn_zero(&a);
|
||||
a.val[(4 * i) / 30] = ((uint32_t)2 * j + 1) << ((4 * i) % 30);
|
||||
bn_normalize(&a);
|
||||
point_multiply(curve, &a, &curve->G, &checkresult);
|
||||
assert(point_is_equal(&checkresult, &ng));
|
||||
#endif
|
||||
printf("\t\t/* %2d*16^%d*G: */\n\t\t{{{", 2*j + 1, i);
|
||||
// print x coordinate
|
||||
for (k = 0; k < 9; k++) {
|
||||
printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.x.val[k]);
|
||||
}
|
||||
printf("}},\n\t\t {{");
|
||||
// print y coordinate
|
||||
for (k = 0; k < 9; k++) {
|
||||
printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.y.val[k]);
|
||||
}
|
||||
if (j == 7) {
|
||||
printf("}}}\n\t},\n");
|
||||
} else {
|
||||
printf("}}},\n");
|
||||
point_add(curve, &pow2ig, &ng);
|
||||
}
|
||||
point_add(curve, &pow2ig, &ng);
|
||||
}
|
||||
pow2ig = ng;
|
||||
}
|
||||
return 0;
|
||||
printf("\t\t/* %2d*16^%d*G: */\n\t\t{{{", 2 * j + 1, i);
|
||||
// print x coordinate
|
||||
for (k = 0; k < 9; k++) {
|
||||
printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.x.val[k]);
|
||||
}
|
||||
printf("}},\n\t\t {{");
|
||||
// print y coordinate
|
||||
for (k = 0; k < 9; k++) {
|
||||
printf((k < 8 ? "0x%08x, " : "0x%04x"), ng.y.val[k]);
|
||||
}
|
||||
if (j == 7) {
|
||||
printf("}}}\n\t},\n");
|
||||
} else {
|
||||
printf("}}},\n");
|
||||
point_add(curve, &pow2ig, &ng);
|
||||
}
|
||||
point_add(curve, &pow2ig, &ng);
|
||||
}
|
||||
pow2ig = ng;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,47 +1,49 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include "bip32.h"
|
||||
#include "curves.h"
|
||||
#include "ecdsa.h"
|
||||
|
||||
#define VERSION_PUBLIC 0x0488b21e
|
||||
#define VERSION_PUBLIC 0x0488b21e
|
||||
#define VERSION_PRIVATE 0x0488ade4
|
||||
|
||||
void process_job(uint32_t jobid, const char *xpub, uint32_t change, uint32_t from, uint32_t to)
|
||||
{
|
||||
HDNode node, child;
|
||||
if (change > 1 || to <= from || hdnode_deserialize(xpub, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME, &node, NULL) != 0) {
|
||||
printf("%d error\n", jobid);
|
||||
return;
|
||||
}
|
||||
hdnode_public_ckd(&node, change);
|
||||
uint32_t i;
|
||||
char address[36];
|
||||
for (i = from; i < to; i++) {
|
||||
memcpy(&child, &node, sizeof(HDNode));
|
||||
hdnode_public_ckd(&child, i);
|
||||
ecdsa_get_address(child.public_key, 0, HASHER_SHA2, HASHER_SHA2D, address, sizeof(address));
|
||||
printf("%d %d %s\n", jobid, i, address);
|
||||
}
|
||||
void process_job(uint32_t jobid, const char *xpub, uint32_t change,
|
||||
uint32_t from, uint32_t to) {
|
||||
HDNode node, child;
|
||||
if (change > 1 || to <= from ||
|
||||
hdnode_deserialize(xpub, VERSION_PUBLIC, VERSION_PRIVATE, SECP256K1_NAME,
|
||||
&node, NULL) != 0) {
|
||||
printf("%d error\n", jobid);
|
||||
return;
|
||||
}
|
||||
hdnode_public_ckd(&node, change);
|
||||
uint32_t i;
|
||||
char address[36];
|
||||
for (i = from; i < to; i++) {
|
||||
memcpy(&child, &node, sizeof(HDNode));
|
||||
hdnode_public_ckd(&child, i);
|
||||
ecdsa_get_address(child.public_key, 0, HASHER_SHA2, HASHER_SHA2D, address,
|
||||
sizeof(address));
|
||||
printf("%d %d %s\n", jobid, i, address);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char line[1024], xpub[1024];
|
||||
uint32_t jobid, change, from, to;
|
||||
int r;
|
||||
for (;;) {
|
||||
if (!fgets(line, sizeof(line), stdin)) break;
|
||||
r = sscanf(line, "%u %s %u %u %u\n", &jobid, xpub, &change, &from, &to);
|
||||
if (r < 1) {
|
||||
printf("error\n");
|
||||
} else if (r != 5) {
|
||||
printf("%d error\n", jobid);
|
||||
} else {
|
||||
process_job(jobid, xpub, change, from, to);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
int main(void) {
|
||||
char line[1024], xpub[1024];
|
||||
uint32_t jobid, change, from, to;
|
||||
int r;
|
||||
for (;;) {
|
||||
if (!fgets(line, sizeof(line), stdin)) break;
|
||||
r = sscanf(line, "%u %s %u %u %u\n", &jobid, xpub, &change, &from, &to);
|
||||
if (r < 1) {
|
||||
printf("error\n");
|
||||
} else if (r != 5) {
|
||||
printf("%d error\n", jobid);
|
||||
} else {
|
||||
process_job(jobid, xpub, change, from, to);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user