Merge pull request #59 from axic/feature/ethereum

Support Ethereum pubkeyhash
pull/25/head
Pavol Rusnak 8 years ago committed by GitHub
commit 16f477787d

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.6)
set(SOURCES aescrypt.c aeskey.c aes_modes.c aestab.c base58.c bignum.c bip32.c bip39.c ecdsa.c hmac.c nist256p1.c pbkdf2.c rand.c ripemd160.c secp256k1.c sha2.c ed25519-donna/ed25519.c)
set(SOURCES aescrypt.c aeskey.c aes_modes.c aestab.c base58.c bignum.c bip32.c bip39.c ecdsa.c hmac.c nist256p1.c pbkdf2.c rand.c ripemd160.c secp256k1.c sha2.c ed25519-donna/ed25519.c sha3.c)
include_directories(ed25519-donna)
# disable sequence point warnings where they are expected

@ -30,6 +30,7 @@ CFLAGS += -DED25519_CUSTOMHASH=1
CFLAGS += -DED25519_NO_INLINE_ASM
CFLAGS += -DED25519_FORCE_32BIT=1
CFLAGS += -Ied25519-donna -I.
CFLAGS += -DUSE_ETHEREUM=1
# disable certain optimizations and features when small footprint is required
ifdef SMALL

@ -36,6 +36,9 @@
#include "base58.h"
#include "macros.h"
#include "secp256k1.h"
#if USE_ETHEREUM
#include "sha3.h"
#endif
// Set cp2 = cp1
void point_copy(const curve_point *cp1, curve_point *cp2)
@ -815,6 +818,21 @@ void ecdsa_get_public_key65(const ecdsa_curve *curve, const uint8_t *priv_key, u
MEMSET_BZERO(&k, sizeof(k));
}
int ecdsa_uncompress_pubkey(const ecdsa_curve *curve, const uint8_t *pub_key, uint8_t *uncompressed)
{
curve_point pub;
if (!ecdsa_read_pubkey(curve, pub_key, &pub)) {
return 0;
}
uncompressed[0] = 4;
bn_write_be(&pub.x, uncompressed + 1);
bn_write_be(&pub.y, uncompressed + 33);
return 1;
}
void ecdsa_get_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash)
{
uint8_t h[32];
@ -829,6 +847,27 @@ void ecdsa_get_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash)
MEMSET_BZERO(h, sizeof(h));
}
#if USE_ETHEREUM
int ecdsa_get_ethereum_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash)
{
uint8_t h[65];
SHA3_CTX ctx;
if (!ecdsa_uncompress_pubkey(&secp256k1, pub_key, h)) {
return 0;
}
sha3_256_Init(&ctx);
sha3_Update(&ctx, h + 1, 64);
keccak_Final(&ctx, h);
// least significant 160 bits
memcpy(pubkeyhash, h + 12, 20);
return 1;
}
#endif
void ecdsa_get_address_raw(const uint8_t *pub_key, uint8_t version, uint8_t *addr_raw)
{
addr_raw[0] = version;

@ -58,6 +58,7 @@ 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);
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, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby);
int ecdsa_sign_double(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *msg, uint32_t msg_len, uint8_t *sig, uint8_t *pby);
@ -65,6 +66,7 @@ int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const u
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, uint8_t *pubkeyhash);
int ecdsa_get_ethereum_pubkeyhash(const uint8_t *pub_key, uint8_t *pubkeyhash);
void ecdsa_get_address_raw(const uint8_t *pub_key, uint8_t version, uint8_t *addr_raw);
void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr, int addrsize);
void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif, int wifsize);

@ -56,4 +56,14 @@
#define BIP39_CACHE_SIZE 4
#endif
// support Ethereum operations
#ifndef USE_ETHEREUM
#define USE_ETHEREUM 0
#endif
// support Keccak hashing
#ifndef USE_KECCAK
#define USE_KECCAK USE_ETHEREUM
#endif
#endif

@ -331,7 +331,7 @@ void sha3_Final(SHA3_CTX *ctx, unsigned char* result)
if (result) me64_to_le_str(result, ctx->hash, digest_length);
}
#ifdef USE_KECCAK
#if USE_KECCAK
/**
* Store calculated hash into the given array.
*

@ -21,6 +21,7 @@
#define __SHA3_H__
#include <stdint.h>
#include "options.h"
#ifdef __cplusplus
extern "C" {
@ -57,7 +58,7 @@ void sha3_512_Init(SHA3_CTX *ctx);
void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size);
void sha3_Final(SHA3_CTX *ctx, unsigned char* result);
#ifdef USE_KECCAK
#if USE_KECCAK
#define keccak_224_Init sha3_224_Init
#define keccak_256_Init sha3_256_Init
#define keccak_384_Init sha3_384_Init

@ -1507,6 +1507,34 @@ START_TEST(test_pubkey_validity)
}
END_TEST
START_TEST(test_pubkey_uncompress)
{
uint8_t pub_key[65];
uint8_t uncompressed[65];
int res;
const ecdsa_curve *curve = &secp256k1;
memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33);
res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(uncompressed, fromhex("0426659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37b3cfbad6b39a8ce8cb3a675f53b7b57e120fe067b8035d771fd99e3eba7cf4de"), 65);
memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33);
res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(uncompressed, fromhex("04433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7feeb4c25bcb840f720a16e8857a011e6b91e0ab2d03dbb5f9762844bb21a7b8ca7"), 65);
memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65);
res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(uncompressed, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65);
memcpy(pub_key, fromhex("00"), 1);
res = ecdsa_uncompress_pubkey(curve, pub_key, uncompressed);
ck_assert_int_eq(res, 0);
}
END_TEST
START_TEST(test_wif)
{
uint8_t priv_key[32];
@ -1895,6 +1923,53 @@ START_TEST(test_output_script) {
}
END_TEST
START_TEST(test_ethereum_pubkeyhash)
{
uint8_t pubkeyhash[20];
uint8_t pub_key[65];
int res;
memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("dfec07843c46f3fb5e5ef8b70b845231a97ed2c8"), 20);
memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("aa2685dbc0a1820fc4bb03c3154d1cc0b26411ee"), 20);
memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("86193afd976244f39f0e9d42a1d2c090080754f1"), 20);
memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("330b7636bff2c8ea728170042ab6af0b826cbdc0"), 20);
memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("10027a9bef3e98be693f8fb4c02f4a7421cdf384"), 20);
memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("6d9baaf3db174b9ea498081707289c228108aa9e"), 20);
memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 1);
ck_assert_mem_eq(pubkeyhash, fromhex("addcb46a5ae157c837682689fcd4f80a76bb7740"), 20);
memcpy(pub_key, fromhex("00"), 1);
res = ecdsa_get_ethereum_pubkeyhash(pub_key, pubkeyhash);
ck_assert_int_eq(res, 0);
}
END_TEST
// define test suite and cases
Suite *test_suite(void)
@ -1974,6 +2049,10 @@ Suite *test_suite(void)
tcase_add_test(tc, test_pubkey_validity);
suite_add_tcase(s, tc);
tc = tcase_create("pubkey_uncompress");
tcase_add_test(tc, test_pubkey_uncompress);
suite_add_tcase(s, tc);
tc = tcase_create("codepoints");
tcase_add_test(tc, test_codepoints);
suite_add_tcase(s, tc);
@ -2002,6 +2081,10 @@ Suite *test_suite(void)
tcase_add_test(tc, test_output_script);
suite_add_tcase(s, tc);
tc = tcase_create("ethereum_pubkeyhash");
tcase_add_test(tc, test_ethereum_pubkeyhash);
suite_add_tcase(s, tc);
return s;
}

Loading…
Cancel
Save