Modified uECC_sign_deterministic() to not depend on #defined constants.

This commit is contained in:
Ken MacKay
2015-06-15 22:02:35 -07:00
parent 67d0733f51
commit fed2afb663
3 changed files with 43 additions and 43 deletions
+12 -4
View File
@@ -44,19 +44,19 @@ typedef struct SHA256_HashContext {
SHA256_CTX ctx;
} SHA256_HashContext;
static void SHA256_init(uECC_HashContext *base) {
static void init_SHA256(uECC_HashContext *base) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Init(&context->ctx);
}
static void SHA256_update(uECC_HashContext *base,
static void update_SHA256(uECC_HashContext *base,
const uint8_t *message,
unsigned message_size) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Update(&context->ctx, message, message_size);
}
static void SHA256_finish(uECC_HashContext *base, uint8_t *hash_result) {
static void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Final(hash_result, &context->ctx);
}
@@ -73,7 +73,15 @@ int main() {
uint8_t private[uECC_BYTES];
uint8_t hash[uECC_BYTES];
uint8_t sig[uECC_BYTES * 2];
SHA256_HashContext ctx = {{&SHA256_init, &SHA256_update, &SHA256_finish}};
uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_BLOCK_LENGTH];
SHA256_HashContext ctx = {{
&init_SHA256,
&update_SHA256,
&finish_SHA256,
SHA256_BLOCK_LENGTH,
SHA256_DIGEST_LENGTH,
tmp
}};
int i;
printf("Testing 256 signatures\n");
+23 -25
View File
@@ -2228,20 +2228,18 @@ int uECC_sign(const uint8_t private_key[uECC_BYTES],
return 0;
}
#if defined(uECC_HASH_BLOCK_SIZE) && defined(uECC_HASH_RESULT_SIZE)
/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
the same size as the hash result size. */
static void HMAC_init(uECC_HashContext *hash_context, const uint8_t *K) {
uint8_t pad[uECC_HASH_BLOCK_SIZE];
uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
unsigned i;
for (i = 0; i < uECC_HASH_RESULT_SIZE; ++i)
for (i = 0; i < hash_context->result_size; ++i)
pad[i] = K[i] ^ 0x36;
for (i = uECC_HASH_RESULT_SIZE; i < uECC_HASH_BLOCK_SIZE; ++i)
for (; i < hash_context->block_size; ++i)
pad[i] = 0x36;
hash_context->init_hash(hash_context);
hash_context->update_hash(hash_context, pad, uECC_HASH_BLOCK_SIZE);
hash_context->update_hash(hash_context, pad, hash_context->block_size);
}
static void HMAC_update(uECC_HashContext *hash_context,
@@ -2251,49 +2249,51 @@ static void HMAC_update(uECC_HashContext *hash_context,
}
static void HMAC_finish(uECC_HashContext *hash_context, const uint8_t *K, uint8_t *result) {
uint8_t pad[uECC_HASH_BLOCK_SIZE];
uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
unsigned i;
for (i = 0; i < uECC_HASH_RESULT_SIZE; ++i)
for (i = 0; i < hash_context->result_size; ++i)
pad[i] = K[i] ^ 0x5c;
for (i = uECC_HASH_RESULT_SIZE; i < uECC_HASH_BLOCK_SIZE; ++i)
for (; i < hash_context->block_size; ++i)
pad[i] = 0x5c;
hash_context->finish_hash(hash_context, result);
hash_context->init_hash(hash_context);
hash_context->update_hash(hash_context, pad, uECC_HASH_BLOCK_SIZE);
hash_context->update_hash(hash_context, result, uECC_HASH_RESULT_SIZE);
hash_context->update_hash(hash_context, pad, hash_context->block_size);
hash_context->update_hash(hash_context, result, hash_context->result_size);
hash_context->finish_hash(hash_context, result);
}
/* V = HMAC_K(V) */
static void update_V(uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) {
HMAC_init(hash_context, K);
HMAC_update(hash_context, V, uECC_HASH_RESULT_SIZE);
HMAC_update(hash_context, V, hash_context->result_size);
HMAC_finish(hash_context, K, V);
}
/* Deterministic signing, similar to RFC 6979. Differences are:
* We just use (truncated) H(m) directly rather than bits2octets(H(m))
(it is not reduced modulo curve_n).
* We generate a value for k (aka T) directly rather than converting endianness. */
* We generate a value for k (aka T) directly rather than converting endianness.
Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) / <HMAC pad> */
int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
const uint8_t message_hash[uECC_BYTES],
uECC_HashContext *hash_context,
uint8_t signature[uECC_BYTES*2]) {
uint8_t V[uECC_HASH_RESULT_SIZE + 1];
uint8_t K[uECC_HASH_RESULT_SIZE];
uint8_t *K = hash_context->tmp;
uint8_t *V = K + hash_context->result_size;
uECC_word_t tries;
unsigned i;
for (i = 0; i < uECC_HASH_RESULT_SIZE; ++i) {
for (i = 0; i < hash_context->result_size; ++i) {
V[i] = 0x01;
K[i] = 0;
}
// K = HMAC_K(V || 0x00 || int2octets(x) || h(m))
V[uECC_HASH_RESULT_SIZE] = 0x00;
HMAC_init(hash_context, K);
HMAC_update(hash_context, V, uECC_HASH_RESULT_SIZE + 1);
V[hash_context->result_size] = 0x00;
HMAC_update(hash_context, V, hash_context->result_size + 1);
HMAC_update(hash_context, private_key, uECC_BYTES);
HMAC_update(hash_context, message_hash, uECC_BYTES);
HMAC_finish(hash_context, K, K);
@@ -2301,9 +2301,9 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
update_V(hash_context, K, V);
// K = HMAC_K(V || 0x01 || int2octets(x) || h(m))
V[uECC_HASH_RESULT_SIZE] = 0x01;
HMAC_init(hash_context, K);
HMAC_update(hash_context, V, uECC_HASH_RESULT_SIZE + 1);
V[hash_context->result_size] = 0x01;
HMAC_update(hash_context, V, hash_context->result_size + 1);
HMAC_update(hash_context, private_key, uECC_BYTES);
HMAC_update(hash_context, message_hash, uECC_BYTES);
HMAC_finish(hash_context, K, K);
@@ -2316,7 +2316,7 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
unsigned T_bytes = 0;
while (T_bytes < sizeof(T)) {
update_V(hash_context, K, V);
for (i = 0; i < uECC_HASH_RESULT_SIZE && T_bytes < sizeof(T); ++i, ++T_bytes) {
for (i = 0; i < hash_context->result_size && T_bytes < sizeof(T); ++i, ++T_bytes) {
T_ptr[T_bytes] = V[i];
}
}
@@ -2329,9 +2329,9 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
}
// K = HMAC_K(V || 0x00)
V[uECC_HASH_RESULT_SIZE] = 0x00;
HMAC_init(hash_context, K);
HMAC_update(hash_context, V, uECC_HASH_RESULT_SIZE + 1);
V[hash_context->result_size] = 0x00;
HMAC_update(hash_context, V, hash_context->result_size + 1);
HMAC_finish(hash_context, K, K);
update_V(hash_context, K, V);
@@ -2339,8 +2339,6 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
return 0;
}
#endif /* defined(uECC_HASH_BLOCK_SIZE) && defined(uECC_HASH_RESULT_SIZE) */
static bitcount_t smax(bitcount_t a, bitcount_t b) {
return (a > b ? a : b);
}
+8 -14
View File
@@ -141,14 +141,6 @@ int uECC_sign(const uint8_t private_key[uECC_BYTES],
const uint8_t message_hash[uECC_BYTES],
uint8_t signature[uECC_BYTES*2]);
/* Define uECC_HASH_BLOCK_SIZE to the block size in bytes of your hash algorithm
(eg 64 for SHA-256) */
/* #define uECC_HASH_BLOCK_SIZE 64 */
/* Define uECC_HASH_RESULT_SIZE to the output size in bytes of your hash algorithm
(eg 32 for SHA-256) */
/* #define uECC_HASH_RESULT_SIZE 32 */
#if defined(uECC_HASH_BLOCK_SIZE) && defined(uECC_HASH_RESULT_SIZE)
/* uECC_HashContext structure.
This is used to pass in an arbitrary hash function to uECC_sign_deterministic().
The structure will be used for multiple hash computations; each time a new hash
@@ -163,26 +155,27 @@ typedef struct SHA256_HashContext {
SHA256_CTX ctx;
} SHA256_HashContext;
void SHA256_init(uECC_HashContext *base) {
void init_SHA256(uECC_HashContext *base) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Init(&context->ctx);
}
void SHA256_update(uECC_HashContext *base,
void update_SHA256(uECC_HashContext *base,
const uint8_t *message,
unsigned message_size) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Update(&context->ctx, message, message_size);
}
void SHA256_finish(uECC_HashContext *base, uint8_t *hash_result) {
void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) {
SHA256_HashContext *context = (SHA256_HashContext *)base;
SHA256_Final(hash_result, &context->ctx);
}
... when signing ...
{
SHA256_HashContext ctx = {{&SHA256_init, &SHA256_update, &SHA256_finish}};
uint8_t tmp[32 + 32 + 64];
SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}};
uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature);
}
*/
@@ -192,6 +185,9 @@ typedef struct uECC_HashContext {
const uint8_t *message,
unsigned message_size);
void (*finish_hash)(struct uECC_HashContext *context, uint8_t *hash_result);
unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */
unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */
uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */
} uECC_HashContext;
/* uECC_sign_deterministic() function.
@@ -218,8 +214,6 @@ int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES],
uECC_HashContext *hash_context,
uint8_t signature[uECC_BYTES*2]);
#endif /* defined(uECC_HASH_BLOCK_SIZE) && defined(uECC_HASH_RESULT_SIZE) */
/* uECC_verify() function.
Verify an ECDSA signature.