Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
cc84744
Transferred existed code and fixed all errors during build and test
Macrosrider Aug 19, 2020
7666510
Added proper structures in order to build transaction more easily
Macrosrider Sep 1, 2020
909a2c9
Added proper structures to work with BTC transactions
Macrosrider Oct 15, 2020
c640961
Added proper functions and constants to work with BTC transactions
Macrosrider Oct 15, 2020
d87ff92
Added functions for BTC signing and implemented correct BTC signing algo
Macrosrider Oct 15, 2020
e7d2e22
Fixed issue with wrong format of currency amount, added SIGHASH_ALL flag
Macrosrider Oct 20, 2020
0a4ffde
Added some constants, changed some files structure
Macrosrider Oct 28, 2020
e5b5870
Fixed issue with missed PUSH_DATA optocode in locking script
Macrosrider Oct 28, 2020
85709dc
Added code for unlocking script compilation
Macrosrider Oct 28, 2020
a112e4e
Fixed BTC signing
Macrosrider Oct 28, 2020
34cb8d6
Fixed issue with wrong size of unlocking script
Macrosrider Nov 12, 2020
359ff8c
Fixed issue with SHA256 double hashing of transaction
Macrosrider Nov 12, 2020
10df4e5
Fixed issue with signature length in responce
Macrosrider Nov 16, 2020
cd7978c
Fixed issue with failing signing tests
Macrosrider Dec 8, 2020
50c7528
Added some standard regressive tests for BTC transaction signing
Macrosrider Dec 18, 2020
1d097fc
Added deterministic signature derivation for test purposes
Macrosrider Dec 30, 2020
645f703
Rewritten BTC transaction signing state machine
Macrosrider Dec 30, 2020
ec4b93f
Removed unnecessary code
Macrosrider Dec 30, 2020
8671a23
Making changes in tests after BTC transaction signing state mashine upd
Macrosrider Dec 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions skycoin-api/bitcoin_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,13 @@
#define BITCOIN_ADDRESS_CHECKSUM_LENGTH 4
#define BITCOIN_PUBKEY_LEN 33
#define BITCOIN_SECKEY_LEN 32
#define BITCOIN_RS_SIG_LEN 65
#define BITCOIN_DER_SIG_LEN (7+33+33)

#define BITCOIN_SCRIPT_OP_DUP 0x76
#define BITCOIN_SCRIPT_OP_HASH160 0xa9
#define BITCOIN_PUSH_DATA 0x14
#define BITCOIN_SCRIPT_OP_EQUALVERIFY 0x88
#define BITCOIN_SCRIPT_OP_CHECKSIG 0xac

#endif
31 changes: 31 additions & 0 deletions skycoin-api/bitcoin_crypto.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "skycoin_crypto.h"
#include "bitcoin_crypto.h"

#include <stdio.h> //sprintf
#include <string.h>
Expand Down Expand Up @@ -39,3 +40,33 @@ int bitcoin_address_from_pubkey(const uint8_t* pubkey, char* b58address, size_t*
}
return 0;
}

int bitcoin_ecdsa_sign_digest(const uint8_t* priv_key, const uint8_t* digest, uint8_t* sig)
{
int ret;
const curve_info* curve = get_curve_by_name(SECP256K1_NAME);
uint8_t recid = 0;
#if USE_RFC6979
ret = ecdsa_sign_deterministic_digest(curve->params, priv_key, digest, sig, &recid, NULL);
#else
ret = ecdsa_sign_digest(curve->params, priv_key, digest, sig, &recid, NULL);
#endif
if (recid >= 4) {
// This should never happen; we can abort() here, as a sanity check
return -3;
}
sig[64] = recid;
return ret;
}

int compile_script(uint8_t* pubkeyhash, uint8_t* script){

script[0] = BITCOIN_SCRIPT_OP_DUP;
script[1] = BITCOIN_SCRIPT_OP_HASH160;
script[2] = BITCOIN_PUSH_DATA;
script[23] = BITCOIN_SCRIPT_OP_EQUALVERIFY;
script[24] = BITCOIN_SCRIPT_OP_CHECKSIG;
memcpy(script + 3, pubkeyhash, 20);

return 0;
}
6 changes: 6 additions & 0 deletions skycoin-api/bitcoin_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
#define BITCOIN_CRYPTO_H

#include "tools/sha2.h"
#include "tools/hasher.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "skycoin_crypto.h"

int bitcoin_address_from_pubkey(const uint8_t* pubkey, char* b58address, size_t* size_b58address);

int bitcoin_ecdsa_sign_digest(const uint8_t* priv_key, const uint8_t* digest, uint8_t* sig);

int compile_script(uint8_t* pubkeyhash, uint8_t* script);

#endif
16 changes: 16 additions & 0 deletions skycoin-api/skycoin_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ void tohex(char* str, const uint8_t* buffer, int buffer_length)
}
}

const uint8_t* fromhex(const char* str)
{
static uint8_t buf[FROMHEX_MAXLEN];
size_t len = strlen(str) / 2;
if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN;
for (size_t i = 0; i < len; i++) {
uint8_t c = 0;
if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4;
if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F') c += (10 + (str[i * 2] & ~0x20) - 'A') << 4;
if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') c += (str[i * 2 + 1] - '0');
if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') c += (10 + (str[i * 2 + 1] & ~0x20) - 'A');
buf[i] = c;
}
return buf;
}

void tobuff(const char* str, uint8_t* buf, size_t buffer_length)
{
for (size_t i = 0; i < buffer_length; i++) {
Expand Down
8 changes: 8 additions & 0 deletions skycoin-api/skycoin_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
#define SKYCOIN_CRYPTO_H

#include "tools/sha2.h"
#include "tools/hasher.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

#define FROMHEX_MAXLEN 512

typedef struct TransactionOutput {
uint64_t coin;
uint64_t hour;
Expand All @@ -39,6 +42,9 @@ typedef enum {
InnerHashInputs,
InnerHashOutputs,
Signature,
BTC_Inputs,
BTC_Outputs,
BTC_Signature
} TxSignState;

typedef struct _TxSignContext {
Expand All @@ -56,6 +62,7 @@ typedef struct _TxSignContext {
uint8_t innerHash[32];
uint64_t requestIndex;
SHA256_CTX sha256_ctx;
Hasher hasher;
} TxSignContext;

void transaction_initZeroTransaction(Transaction* self);
Expand All @@ -74,6 +81,7 @@ void skycoin_pubkey_from_seckey(const uint8_t* seckey, uint8_t* pubkey);
int skycoin_address_from_pubkey(const uint8_t* pubkey, char* address, size_t* size_address);
int skycoin_ecdsa_sign_digest(const uint8_t* priv_key, const uint8_t* digest, uint8_t* sig);
void tohex(char* str, const uint8_t* buffer, int buffer_length);
const uint8_t* fromhex(const char* str);
void tobuff(const char* str, uint8_t* buf, size_t buffer_length);
void writebuf_fromhexstr(const char* str, uint8_t* buf);

Expand Down
18 changes: 0 additions & 18 deletions skycoin-api/test_skycoin_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,6 @@
#include "tools/sha2.h" //SHA256_DIGEST_LENGTH
#include "tools/sha3.h"

#define FROMHEX_MAXLEN 512

const uint8_t* fromhex(const char* str)
{
static uint8_t buf[FROMHEX_MAXLEN];
size_t len = strlen(str) / 2;
if (len > FROMHEX_MAXLEN) len = FROMHEX_MAXLEN;
for (size_t i = 0; i < len; i++) {
uint8_t c = 0;
if (str[i * 2] >= '0' && str[i * 2] <= '9') c += (str[i * 2] - '0') << 4;
if ((str[i * 2] & ~0x20) >= 'A' && (str[i * 2] & ~0x20) <= 'F') c += (10 + (str[i * 2] & ~0x20) - 'A') << 4;
if (str[i * 2 + 1] >= '0' && str[i * 2 + 1] <= '9') c += (str[i * 2 + 1] - '0');
if ((str[i * 2 + 1] & ~0x20) >= 'A' && (str[i * 2 + 1] & ~0x20) <= 'F') c += (10 + (str[i * 2 + 1] & ~0x20) - 'A');
buf[i] = c;
}
return buf;
}

START_TEST(test_base58_decode)
{
uint8_t addrhex[25] = {0};
Expand Down
88 changes: 87 additions & 1 deletion skycoin-api/tools/ecdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "ripemd160.h"
#include "secp256k1.h"
#include "sha2.h"
// #include "rfc6979.h"
#include "rfc6979.h"
#include "memzero.h"

// Set cp2 = cp1
Expand Down Expand Up @@ -737,6 +737,92 @@ int ecdsa_sign_digest(const ecdsa_curve* curve, const uint8_t* priv_key, const u
return -1;
}

int ecdsa_sign_deterministic_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])){

int i;
curve_point R;
bignum256 k, z, randk;
bignum256 *s = &R.y;
uint8_t by; // signature recovery byte

rfc6979_state rng;
init_rfc6979(priv_key, digest, &rng);

bn_read_be(digest, &z);

for (i = 0; i < 10000; i++) {

generate_k_rfc6979(&k, &rng);
// if k is too big or too small, we don't like it
if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) {
continue;
}

// compute k*G
scalar_multiply(curve, &k, &R);
by = R.y.val[0] & 1;
// r = (rx mod n)
if (!bn_is_less(&R.x, &curve->order)) {
bn_subtract(&R.x, &curve->order, &R.x);
by |= 2;
}
// if r is zero, we retry
if (bn_is_zero(&R.x)) {
continue;
}

// randomize operations to counter side-channel attacks
generate_k_random(&randk, &curve->order);
bn_multiply(&randk, &k, &curve->order); // k*rand
bn_inverse(&k, &curve->order); // (k*rand)^-1
bn_read_be(priv_key, s); // priv
bn_multiply(&R.x, s, &curve->order); // R.x*priv
bn_add(s, &z); // R.x*priv + z
bn_multiply(&k, s, &curve->order); // (k*rand)^-1 (R.x*priv + z)
bn_multiply(&randk, s, &curve->order); // k^-1 (R.x*priv + z)
bn_mod(s, &curve->order);
// if s is zero, we retry
if (bn_is_zero(s)) {
continue;
}

// if S > order/2 => S = -S
if (bn_is_less(&curve->order_half, s)) {
bn_subtract(&curve->order, s, s);
by ^= 1;
}
// we are done, R.x and s is the result signature
bn_write_be(&R.x, sig);
bn_write_be(s, sig + 32);

// check if the signature is acceptable or retry
if (is_canonical && !is_canonical(by, sig)) {
continue;
}

if (pby) {
*pby = by;
}

memzero(&k, sizeof(k));
memzero(&randk, sizeof(randk));

memzero(&rng, sizeof(rng));

return 0;
}

// Too many retries without a valid signature
// -> fail with an error
memzero(&k, sizeof(k));
memzero(&randk, sizeof(randk));
memzero(&rng, sizeof(rng));

return -1;
}

int ecdsa_sign_digest_inner(const ecdsa_curve* curve, const uint8_t* priv_key, bignum256* z, bignum256* k, uint8_t* sig, uint8_t* pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]))
{
bignum256 randk;
Expand Down
1 change: 1 addition & 0 deletions skycoin-api/tools/ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ int ecdsa_sign(const ecdsa_curve* curve, HasherType hasher_type, const uint8_t*
int ecdsa_sign_double(const ecdsa_curve* curve, HasherType hasher_type, 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]));
int ecdsa_sign_digest_inner(const ecdsa_curve* curve, const uint8_t* priv_key, bignum256* z, bignum256* k, uint8_t* sig, uint8_t* pby, int (*is_canonical)(uint8_t by, uint8_t sig[64]));
int ecdsa_sign_deterministic_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_type, uint8_t* pubkeyhash);
Expand Down
6 changes: 6 additions & 0 deletions skycoin-api/tools/hasher.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ void hasher_Init(Hasher* hasher, HasherType type)

switch (hasher->type) {
case HASHER_SHA2:
case HASHER_SHA2D:
sha256_Init(&hasher->ctx.sha2);
break;
case HASHER_BLAKE:
Expand All @@ -45,6 +46,7 @@ void hasher_Update(Hasher* hasher, const uint8_t* data, size_t length)
{
switch (hasher->type) {
case HASHER_SHA2:
case HASHER_SHA2D:
sha256_Update(&hasher->ctx.sha2, data, length);
break;
case HASHER_BLAKE:
Expand All @@ -59,6 +61,10 @@ void hasher_Final(Hasher* hasher, uint8_t hash[HASHER_DIGEST_LENGTH])
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_BLAKE:
blake256_Final(&hasher->ctx.blake, hash);
break;
Expand Down
1 change: 1 addition & 0 deletions skycoin-api/tools/hasher.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

typedef enum {
HASHER_SHA2,
HASHER_SHA2D,
HASHER_BLAKE,
} HasherType;

Expand Down
Loading