mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
replace cardano with v2 (#179)
This commit is contained in:
parent
cabc926b39
commit
d2bc03fb59
162
bip32.c
162
bip32.c
@ -49,6 +49,7 @@
|
||||
#include "ed25519-donna/modm-donna-32bit.h"
|
||||
#include "blake2b.h"
|
||||
#include "bip39.h"
|
||||
#include "pbkdf2.h"
|
||||
#endif
|
||||
#include "memzero.h"
|
||||
|
||||
@ -262,49 +263,56 @@ int hdnode_private_ckd(HDNode *inout, uint32_t i)
|
||||
}
|
||||
|
||||
#if USE_CARDANO
|
||||
/* sk1 is zl8 and contains only 29 bytes of active data,
|
||||
* so it's not going to overflow when adding to sk2 */
|
||||
void scalar_add_no_overflow(const uint8_t * sk1, const uint8_t * sk2, uint8_t * res)
|
||||
{
|
||||
uint16_t r = 0; int i;
|
||||
for (i = 0; i < 32; i++) {
|
||||
r = (uint16_t) sk1[i] + (uint16_t) sk2[i] + r;
|
||||
res[i] = (uint8_t) r;
|
||||
r >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void multiply8(uint8_t *dst, uint8_t *src, int bytes)
|
||||
{
|
||||
int i;
|
||||
uint8_t prev_acc = 0;
|
||||
for (int i = 0; i < bytes; i++) {
|
||||
dst[i] = (src[i] << 3) + (prev_acc & 0x8);
|
||||
for (i = 0; i < bytes; i++) {
|
||||
dst[i] = (src[i] << 3) + (prev_acc & 0x7);
|
||||
prev_acc = src[i] >> 5;
|
||||
}
|
||||
dst[bytes] = src[bytes-1] >> 5;
|
||||
}
|
||||
|
||||
static void add_256bits(uint8_t *dst, uint8_t *src1, uint8_t *src2)
|
||||
{
|
||||
for (int i = 0; i < 32; i++) {
|
||||
int i; uint8_t carry = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
uint8_t a = src1[i];
|
||||
uint8_t b = src2[i];
|
||||
uint16_t r = a + b;
|
||||
uint16_t r = (uint16_t) a + (uint16_t) b + (uint16_t) carry;
|
||||
dst[i] = r & 0xff;
|
||||
carry = (r >= 0x100) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ed25519_scalar_add(const uint8_t *sk1, const uint8_t *sk2, uint8_t *res)
|
||||
{
|
||||
bignum256modm s1, s2;
|
||||
expand256_modm(s1, sk1, 32);
|
||||
expand256_modm(s2, sk2, 32);
|
||||
add256_modm(s1, s1, s2);
|
||||
contract256_modm(res, s1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i)
|
||||
int hdnode_private_ckd_cardano(HDNode *inout, uint32_t index)
|
||||
{
|
||||
// checks for hardened/non-hardened derivation, keysize 32 means we are dealing with public key and thus non-h, keysize 64 is for private key
|
||||
int keysize = 32;
|
||||
if (i & 0x80000000) {
|
||||
if (index & 0x80000000) {
|
||||
keysize = 64;
|
||||
}
|
||||
|
||||
static CONFIDENTIAL uint8_t data[1 + 64 + 4];
|
||||
static CONFIDENTIAL uint8_t I[32 + 32];
|
||||
static CONFIDENTIAL bignum256 a, b;
|
||||
static CONFIDENTIAL uint8_t z[32 + 32];
|
||||
static CONFIDENTIAL uint8_t priv_key[64];
|
||||
static CONFIDENTIAL uint8_t res_key[64];
|
||||
|
||||
write_le(data + keysize + 1, index);
|
||||
|
||||
memcpy(priv_key, inout->private_key, 32);
|
||||
memcpy(priv_key + 32, inout->private_key_extension, 32);
|
||||
|
||||
@ -317,19 +325,23 @@ int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i)
|
||||
data[0] = 2;
|
||||
memcpy(data + 1, inout->public_key + 1, 32);
|
||||
}
|
||||
write_be(data + keysize + 1, i);
|
||||
|
||||
bn_read_be(priv_key, &a);
|
||||
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, 1 + keysize + 4);
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
hmac_sha512_Final(&ctx, z);
|
||||
|
||||
static CONFIDENTIAL uint8_t zl8[32];
|
||||
multiply8(zl8,I,32);
|
||||
ed25519_scalar_add(zl8,priv_key,res_key);
|
||||
add_256bits(res_key+32,I+32,priv_key+32);
|
||||
memset(zl8, 0, 32);
|
||||
|
||||
/* get 8 * Zl */
|
||||
multiply8(zl8, z, 28);
|
||||
/* Kl = 8*Zl + parent(K)l */
|
||||
scalar_add_no_overflow(zl8, priv_key, res_key);
|
||||
|
||||
/* Kr = Zr + parent(K)r */
|
||||
add_256bits(res_key + 32, z+32, priv_key+32);
|
||||
|
||||
memcpy(inout->private_key, res_key, 32);
|
||||
memcpy(inout->private_key_extension, res_key + 32, 32);
|
||||
|
||||
@ -340,112 +352,42 @@ int hdnode_private_ckd_cardano(HDNode *inout, uint32_t i)
|
||||
}
|
||||
hmac_sha512_Init(&ctx, inout->chain_code, 32);
|
||||
hmac_sha512_Update(&ctx, data, 1 + keysize + 4);
|
||||
hmac_sha512_Final(&ctx, I);
|
||||
hmac_sha512_Final(&ctx, z);
|
||||
|
||||
memcpy(inout->chain_code, I + 32, 32);
|
||||
memcpy(inout->chain_code, z + 32, 32);
|
||||
inout->depth++;
|
||||
inout->child_num = i;
|
||||
inout->child_num = index;
|
||||
memzero(inout->public_key, sizeof(inout->public_key));
|
||||
|
||||
// making sure to wipe our memory
|
||||
memzero(&a, sizeof(a));
|
||||
memzero(&b, sizeof(b));
|
||||
memzero(I, sizeof(I));
|
||||
memzero(z, sizeof(z));
|
||||
memzero(data, sizeof(data));
|
||||
memzero(priv_key, sizeof(priv_key));
|
||||
memzero(res_key, sizeof(res_key));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hdnode_from_seed_cardano(uint8_t *seed, int seed_len, HDNode *out) {
|
||||
uint8_t hash[32];
|
||||
uint8_t cbor[32+2];
|
||||
int hdnode_from_seed_cardano(uint8_t *pass, int pass_len, uint8_t *seed, int seed_len, HDNode *out) {
|
||||
uint8_t secret[96];
|
||||
pbkdf2_hmac_sha512(pass, pass_len, seed, seed_len, 4096, secret, 96);
|
||||
|
||||
secret[0] &= 248;
|
||||
secret[31] &= 31;
|
||||
secret[31] |= 64;
|
||||
|
||||
if (seed_len < 24) {
|
||||
// cbor encodes length directly into first byte if its smaller than 24
|
||||
seed[1] = 64 | seed_len;
|
||||
blake2b(seed + 1, seed_len + 1, hash, 32);
|
||||
} else {
|
||||
seed[0] = 88;
|
||||
seed[1] = seed_len;
|
||||
blake2b(seed, seed_len + 2, hash, 32);
|
||||
}
|
||||
|
||||
cbor[0] = 88; // 64 means its byte array, 24 means its length has 8 bits
|
||||
cbor[1] = 32; // length of the byte array
|
||||
memcpy(cbor + 2, hash, 32);
|
||||
uint8_t salt[21];
|
||||
memcpy(salt, "Root Seed Chain ", 16);
|
||||
uint8_t hmac[64];
|
||||
uint8_t secret[64];
|
||||
uint8_t public[32];
|
||||
uint8_t chain_code[32];
|
||||
int failed = 1;
|
||||
memset(out, 0, sizeof(HDNode));
|
||||
out->depth = 0;
|
||||
out->child_num = 0;
|
||||
out->curve = get_curve_by_name(ED25519_CARDANO_NAME);
|
||||
|
||||
int saltlen;
|
||||
static CONFIDENTIAL HMAC_SHA512_CTX ctx;
|
||||
for (int i = 1; i <= 1000; i++){
|
||||
hmac_sha512_Init(&ctx, cbor, 34);
|
||||
if (i < 10) {
|
||||
salt[16] = '0' + (i);
|
||||
saltlen = 16 + 1;
|
||||
} else if (i < 100) {
|
||||
salt[16] = '0' + (i / 10);
|
||||
salt[17] = '0' + (i % 10);
|
||||
saltlen = 16 + 2;
|
||||
} else if (i < 1000) {
|
||||
salt[16] = '0' + (i / 100);
|
||||
salt[17] = '0' + ((i / 10) % 10);
|
||||
salt[18] = '0' + (i % 10);
|
||||
saltlen = 16 + 3;
|
||||
} else {
|
||||
salt[16] = '0' + (i / 1000);
|
||||
salt[17] = '0' + ((i / 100) % 10);
|
||||
salt[18] = '0' + ((i / 10) % 10);
|
||||
salt[19] = '0' + (i % 10);
|
||||
saltlen = 16 + 4;
|
||||
}
|
||||
hmac_sha512_Update(&ctx, salt, saltlen);
|
||||
hmac_sha512_Final(&ctx, hmac);
|
||||
ed25519_publickey(hmac, public);
|
||||
sha512_Raw(hmac, 32, secret);
|
||||
secret[0] &= 248;
|
||||
secret[31] &= 127;
|
||||
secret[31] |= 64;
|
||||
if (secret[31] & 0x20) {
|
||||
continue;
|
||||
}
|
||||
memcpy(chain_code, hmac + 32, 32);
|
||||
failed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
memzero(hash, sizeof(hash));
|
||||
memzero(cbor, sizeof(cbor));
|
||||
memzero(salt, sizeof(salt));
|
||||
|
||||
if (failed) {
|
||||
memzero(seed, sizeof(seed));
|
||||
memzero(secret, sizeof(secret));
|
||||
memzero(chain_code, sizeof(chain_code));
|
||||
memzero(hmac, sizeof(hmac));
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(out->private_key, secret, 32);
|
||||
memcpy(out->private_key_extension, secret + 32, 32);
|
||||
|
||||
memcpy(out->chain_code, chain_code, 32);
|
||||
out->public_key[0] = 1;
|
||||
memcpy(out->public_key + 1, public, 32);
|
||||
memzero(seed, sizeof(seed));
|
||||
out->public_key[0] = 0;
|
||||
hdnode_fill_public_key(out);
|
||||
|
||||
memcpy(out->chain_code, secret + 64, 32);
|
||||
memzero(secret, sizeof(secret));
|
||||
memzero(chain_code, sizeof(chain_code));
|
||||
memzero(hmac, sizeof(hmac));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
2
bip32.h
2
bip32.h
@ -63,7 +63,7 @@ int hdnode_from_seed(const uint8_t *seed, int seed_len, const char *curve, HDNod
|
||||
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(uint8_t *seed, int seed_len, HDNode *out);
|
||||
int hdnode_from_seed_cardano(uint8_t *pass, int pass_len, 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);
|
||||
|
2
bip39.c
2
bip39.c
@ -243,7 +243,7 @@ void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed
|
||||
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, strlen(mnemonic), salt, passphraselen + 8);
|
||||
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, strlen(mnemonic), salt, passphraselen + 8, 1);
|
||||
if (progress_callback) {
|
||||
progress_callback(0, BIP39_PBKDF2_ROUNDS);
|
||||
}
|
||||
|
61
pbkdf2.c
61
pbkdf2.c
@ -27,10 +27,11 @@
|
||||
#include "sha2.h"
|
||||
#include "memzero.h"
|
||||
|
||||
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen)
|
||||
#define CEILING_POS(X) ((X-(uint32_t)(X)) > 0 ? (uint32_t)(X+1) : (uint32_t)(X))
|
||||
|
||||
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;
|
||||
uint32_t blocknr = 1;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
@ -78,18 +79,34 @@ void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key)
|
||||
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)
|
||||
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)
|
||||
{
|
||||
PBKDF2_HMAC_SHA256_CTX pctx;
|
||||
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen);
|
||||
pbkdf2_hmac_sha256_Update(&pctx, iterations);
|
||||
pbkdf2_hmac_sha256_Final(&pctx, key);
|
||||
uint32_t blocks_count = (uint32_t) CEILING_POS((float) keylen / SHA256_DIGEST_LENGTH);
|
||||
|
||||
int unfinished_key_size = keylen;
|
||||
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);
|
||||
|
||||
unsigned int key_offset = (blocknr - 1) * SHA256_DIGEST_LENGTH;
|
||||
uint8_t diggest[SHA256_DIGEST_LENGTH];
|
||||
|
||||
pbkdf2_hmac_sha256_Final(&pctx, diggest);
|
||||
|
||||
if (unfinished_key_size > SHA256_DIGEST_LENGTH) {
|
||||
memcpy(key + key_offset, diggest, SHA256_DIGEST_LENGTH);
|
||||
unfinished_key_size -= SHA256_DIGEST_LENGTH;
|
||||
} else {
|
||||
memcpy(key + key_offset, diggest, unfinished_key_size);
|
||||
unfinished_key_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen)
|
||||
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;
|
||||
uint32_t blocknr = 1;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
REVERSE32(blocknr, blocknr);
|
||||
#endif
|
||||
@ -138,10 +155,26 @@ void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)
|
||||
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)
|
||||
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen)
|
||||
{
|
||||
PBKDF2_HMAC_SHA512_CTX pctx;
|
||||
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen);
|
||||
pbkdf2_hmac_sha512_Update(&pctx, iterations);
|
||||
pbkdf2_hmac_sha512_Final(&pctx, key);
|
||||
uint32_t blocks_count = (uint32_t) CEILING_POS((float) keylen / SHA512_DIGEST_LENGTH);
|
||||
|
||||
int unfinished_key_size = keylen;
|
||||
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);
|
||||
|
||||
unsigned int key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
|
||||
uint8_t diggest[SHA512_DIGEST_LENGTH];
|
||||
pbkdf2_hmac_sha512_Final(&pctx, diggest);
|
||||
|
||||
if (unfinished_key_size > SHA512_DIGEST_LENGTH) {
|
||||
memcpy(key + key_offset, diggest, SHA512_DIGEST_LENGTH);
|
||||
unfinished_key_size -= SHA512_DIGEST_LENGTH;
|
||||
} else {
|
||||
memcpy(key + key_offset, diggest, unfinished_key_size);
|
||||
unfinished_key_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
pbkdf2.h
8
pbkdf2.h
@ -43,14 +43,14 @@ typedef struct _PBKDF2_HMAC_SHA512_CTX {
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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
|
||||
|
@ -2586,19 +2586,19 @@ START_TEST(test_pbkdf2_hmac_sha256)
|
||||
uint8_t k[40], s[40];
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 1, k);
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 1, k, 32);
|
||||
ck_assert_mem_eq(k, fromhex("120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"), 32);
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 2, k);
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 2, k, 32);
|
||||
ck_assert_mem_eq(k, fromhex("ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"), 32);
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 4096, k);
|
||||
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 4096, k, 32);
|
||||
ck_assert_mem_eq(k, fromhex("c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"), 32);
|
||||
|
||||
strcpy((char *)s, "saltSALTsaltSALTsaltSALTsaltSALTsalt");
|
||||
pbkdf2_hmac_sha256((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k);
|
||||
pbkdf2_hmac_sha256((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 32);
|
||||
ck_assert_mem_eq(k, fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1"), 32);
|
||||
}
|
||||
END_TEST
|
||||
@ -2609,19 +2609,19 @@ START_TEST(test_pbkdf2_hmac_sha512)
|
||||
uint8_t k[64], s[40];
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 1, k);
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 1, k, 64);
|
||||
ck_assert_mem_eq(k, fromhex("867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"), 64);
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 2, k);
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 2, k, 64);
|
||||
ck_assert_mem_eq(k, fromhex("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"), 64);
|
||||
|
||||
strcpy((char *)s, "salt");
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 4096, k);
|
||||
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 4096, k, 64);
|
||||
ck_assert_mem_eq(k, fromhex("d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"), 64);
|
||||
|
||||
strcpy((char *)s, "saltSALTsaltSALTsaltSALTsaltSALTsalt");
|
||||
pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k);
|
||||
pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 64);
|
||||
ck_assert_mem_eq(k, fromhex("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"), 64);
|
||||
}
|
||||
END_TEST
|
||||
@ -5063,6 +5063,7 @@ Suite *test_suite(void)
|
||||
|
||||
#if USE_CARDANO
|
||||
tc = tcase_create("bip32-cardano");
|
||||
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_1);
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_2);
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_3);
|
||||
@ -5070,6 +5071,7 @@ Suite *test_suite(void)
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_5);
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_6);
|
||||
tcase_add_test(tc, test_bip32_cardano_hdnode_vector_7);
|
||||
|
||||
tcase_add_test(tc, test_ed25519_cardano_sign_vectors);
|
||||
suite_add_tcase(s,tc);
|
||||
#endif
|
||||
|
@ -1,145 +1,3 @@
|
||||
// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(seed, seed_len / 8, &node);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("739f4b3caca4c9ad4fcd4bdc2ef42c8601af8d6946999ef85ef6ae84f66e72eb"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea53"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8e"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("64b20fa082b3143d6b5eed42c6ef63f99599d0888afe060620abc1b319935fe1"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("6755cb82e892d6614c007a5efbceb21d95a5244e269d0e206b48b9a495390b03"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("e7d27516538403a53a8b041656a3f570909df641a0ab811fe7d87c9ba02a830c"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("794a2c54ad8b525b781773c87d38cbf4197636bc427a9d551368286fe4c294a4"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("95bb82ffd5707716bc65170ab4e8dafeed90fbe0ce9258713b7751e962d931df"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("47a242713bd18608231147c066b6083bfc1e9066fec9f621844c84fed6228a34"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("9b5a3d9a4c60bcd49bb64b72c082b164314d0f61d842f2575fd1d4fb30a28a0c"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("b093e376f41eb7bf80abcd0073a52455d25b5d21815bc758e5f6f81536aedebb"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("79fc8154554b97e4c56ef2f9dbb4c1421ff19509688931a1e964bda5dec0f19f"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(seed, seed_len / 8, &node);
|
||||
|
||||
hdnode_private_ckd_cardano(&node, 0x80000000);
|
||||
hdnode_private_ckd_cardano(&node, 0x80000001);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("d6798491b9fa4612370ae5ef3c623a0b6872f3ad8f26970885fa67c83bdc425e"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("52e0c98aa600cfdcd1ff28fcda5227ed87063f4a98547a78b771052cf102b40c"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("6c18d9f8075b1a6a1833540607479bd58b7beb8a83d2bb01ca7ae02452a25803"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("dc907c7c06e6314eedd9e18c9f6c6f9cc4e205fb1c70da608234c319f1f7b0d6"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(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("4169a2a32e3618a903e930bd1a713033a38f92389093408394e29ac37a1752ea"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("11fd6462a3a92b35c22703f6f1c124ddcf36b7c2b09cc2784f320e1cfa12ec04"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("c2785803c61c46aeca192a1bb1b7b20a8c4cc7fa01db57fc5d1d8a5473402352"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("839775a41876e328986aa26168958bba1176e67819b357eea84afceab8b1db78"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(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);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("3ae9c99a5925cba2dcf121baf3a0254f3dea23c129f9eb70a8a7e8897c5199ba"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("5b1e5cad02274ba461f4708d8598d3497faf8fe3e894a379573aa6ac3a03e505"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("ba179d2e3c67aabb486c48d16002b51ad32eab434c738a1550962313b07098cd"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("75eb8d197ec8627c85af88e66aa1e49065dd8ac98ed8991db52ece01635dfb76"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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 + 2);
|
||||
ck_assert_int_eq(seed_len, 132);
|
||||
hdnode_from_seed_cardano(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);
|
||||
|
||||
ck_assert_mem_eq(node.chain_code, fromhex("15c450b86dd7dd83b31951d9ee03eb1a7925161d817bd517c69cf09e3671f1ca"), 32);
|
||||
ck_assert_mem_eq(node.private_key, fromhex("624b47150f58dfa44284fbc63c9f99b9b79f808c4955a461f0e2be44eb0be50d"), 32);
|
||||
ck_assert_mem_eq(node.private_key_extension, fromhex("097aa006d694b165ef37cf23562e5967c96e49255d2f20faae478dee83aa5b02"), 32);
|
||||
hdnode_fill_public_key(&node);
|
||||
ck_assert_mem_eq(node.public_key + 1, fromhex("0588589cd9b51dfc028cf225674069cbe52e0e70deb02dc45b79b26ee3548b00"), 32);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
// https://github.com/input-output-hk/cardano-crypto/blob/master/tests/goldens/cardano/crypto/wallet/BIP39-128
|
||||
START_TEST(test_ed25519_cardano_sign_vectors)
|
||||
{
|
||||
@ -214,3 +72,144 @@ START_TEST(test_ed25519_cardano_sign_vectors)
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 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);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 0, seed, seed_len / 8, &node);
|
||||
|
||||
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);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 0, seed, seed_len / 8, &node);
|
||||
|
||||
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);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 0, seed, seed_len / 8, &node);
|
||||
|
||||
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);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 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);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
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(NULL, 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);
|
||||
|
||||
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;
|
||||
|
||||
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(NULL, 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);
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user