mirror of
https://github.com/kmackay/micro-ecc.git
synced 2026-10-23 07:58:14 +00:00
Convert hash to int in sign/verify (#53)
Previously, callers would need to manually convert the hash value appropriately if it was not the same length as curve_n. Now, callers just pass in the full hash value and the length; uECC will convert the hash as appropriate.
This commit is contained in:
+2
-2
@@ -31,12 +31,12 @@ int main() {
|
|||||||
}
|
}
|
||||||
memcpy(hash, public, sizeof(hash));
|
memcpy(hash, public, sizeof(hash));
|
||||||
|
|
||||||
if (!uECC_sign(private, hash, sig, curves[c])) {
|
if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) {
|
||||||
printf("uECC_sign() failed\n");
|
printf("uECC_sign() failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uECC_verify(public, hash, sig, curves[c])) {
|
if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) {
|
||||||
printf("uECC_verify() failed\n");
|
printf("uECC_verify() failed\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1014,8 +1014,33 @@ int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uEC
|
|||||||
|
|
||||||
/* -------- ECDSA code -------- */
|
/* -------- ECDSA code -------- */
|
||||||
|
|
||||||
|
static void bits2int(uECC_word_t *native,
|
||||||
|
const uint8_t *bits,
|
||||||
|
unsigned bits_size,
|
||||||
|
uECC_Curve curve) {
|
||||||
|
unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
|
||||||
|
unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||||
|
if (bits_size > num_n_bytes) {
|
||||||
|
bits_size = num_n_bytes;
|
||||||
|
}
|
||||||
|
uECC_vli_bytesToNative(native, bits, bits_size, curve);
|
||||||
|
if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int shift = bits_size * 8 - curve->num_n_bits;
|
||||||
|
uECC_word_t carry = 0;
|
||||||
|
uECC_word_t *end = native;
|
||||||
|
native += num_n_words;
|
||||||
|
while (native-- > end) {
|
||||||
|
uECC_word_t temp = *native;
|
||||||
|
*native = (temp >> shift) | carry;
|
||||||
|
carry = temp << (uECC_WORD_BITS - shift);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int uECC_sign_with_k(const uint8_t *private_key,
|
static int uECC_sign_with_k(const uint8_t *private_key,
|
||||||
const uint8_t *message_hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
uECC_word_t *k,
|
uECC_word_t *k,
|
||||||
uint8_t *signature,
|
uint8_t *signature,
|
||||||
uECC_Curve curve) {
|
uECC_Curve curve) {
|
||||||
@@ -1071,7 +1096,7 @@ got_random:
|
|||||||
uECC_vli_set(s, p, num_words);
|
uECC_vli_set(s, p, num_words);
|
||||||
uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
|
uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
|
||||||
|
|
||||||
uECC_vli_bytesToNative(tmp, message_hash, curve->num_bytes, curve);
|
bits2int(tmp, message_hash, hash_size, curve);
|
||||||
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
|
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
|
||||||
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
|
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
|
||||||
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
|
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
|
||||||
@@ -1083,6 +1108,7 @@ got_random:
|
|||||||
|
|
||||||
int uECC_sign(const uint8_t *private_key,
|
int uECC_sign(const uint8_t *private_key,
|
||||||
const uint8_t *message_hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
uint8_t *signature,
|
uint8_t *signature,
|
||||||
uECC_Curve curve) {
|
uECC_Curve curve) {
|
||||||
uECC_word_t k[uECC_MAX_WORDS];
|
uECC_word_t k[uECC_MAX_WORDS];
|
||||||
@@ -1095,7 +1121,7 @@ int uECC_sign(const uint8_t *private_key,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uECC_sign_with_k(private_key, message_hash, k, signature, curve)) {
|
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1146,13 +1172,14 @@ static void update_V(uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Deterministic signing, similar to RFC 6979. Differences are:
|
/* Deterministic signing, similar to RFC 6979. Differences are:
|
||||||
* We just use (truncated) H(m) directly rather than bits2octets(H(m))
|
* We just use H(m) directly rather than bits2octets(H(m))
|
||||||
(it is not reduced modulo curve_n).
|
(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> */
|
Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) / <HMAC pad> */
|
||||||
int uECC_sign_deterministic(const uint8_t *private_key,
|
int uECC_sign_deterministic(const uint8_t *private_key,
|
||||||
const uint8_t *message_hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
uECC_HashContext *hash_context,
|
uECC_HashContext *hash_context,
|
||||||
uint8_t *signature,
|
uint8_t *signature,
|
||||||
uECC_Curve curve) {
|
uECC_Curve curve) {
|
||||||
@@ -1173,7 +1200,7 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
|||||||
V[hash_context->result_size] = 0x00;
|
V[hash_context->result_size] = 0x00;
|
||||||
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
||||||
HMAC_update(hash_context, private_key, num_bytes);
|
HMAC_update(hash_context, private_key, num_bytes);
|
||||||
HMAC_update(hash_context, message_hash, num_bytes);
|
HMAC_update(hash_context, message_hash, hash_size);
|
||||||
HMAC_finish(hash_context, K, K);
|
HMAC_finish(hash_context, K, K);
|
||||||
|
|
||||||
update_V(hash_context, K, V);
|
update_V(hash_context, K, V);
|
||||||
@@ -1183,7 +1210,7 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
|||||||
V[hash_context->result_size] = 0x01;
|
V[hash_context->result_size] = 0x01;
|
||||||
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
HMAC_update(hash_context, V, hash_context->result_size + 1);
|
||||||
HMAC_update(hash_context, private_key, num_bytes);
|
HMAC_update(hash_context, private_key, num_bytes);
|
||||||
HMAC_update(hash_context, message_hash, num_bytes);
|
HMAC_update(hash_context, message_hash, hash_size);
|
||||||
HMAC_finish(hash_context, K, K);
|
HMAC_finish(hash_context, K, K);
|
||||||
|
|
||||||
update_V(hash_context, K, V);
|
update_V(hash_context, K, V);
|
||||||
@@ -1208,7 +1235,7 @@ int uECC_sign_deterministic(const uint8_t *private_key,
|
|||||||
mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
|
mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uECC_sign_with_k(private_key, message_hash, T, signature, curve)) {
|
if (uECC_sign_with_k(private_key, message_hash, hash_size, T, signature, curve)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1228,7 +1255,8 @@ static bitcount_t smax(bitcount_t a, bitcount_t b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int uECC_verify(const uint8_t *public_key,
|
int uECC_verify(const uint8_t *public_key,
|
||||||
const uint8_t *hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
const uint8_t *signature,
|
const uint8_t *signature,
|
||||||
uECC_Curve curve) {
|
uECC_Curve curve) {
|
||||||
uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
|
uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
|
||||||
@@ -1272,7 +1300,7 @@ int uECC_verify(const uint8_t *public_key,
|
|||||||
/* Calculate u1 and u2. */
|
/* Calculate u1 and u2. */
|
||||||
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
||||||
u1[num_n_words - 1] = 0;
|
u1[num_n_words - 1] = 0;
|
||||||
uECC_vli_bytesToNative(u1, hash, curve->num_bytes, curve);
|
bits2int(u1, message_hash, hash_size, curve);
|
||||||
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
||||||
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ this function along with your private key.
|
|||||||
Inputs:
|
Inputs:
|
||||||
private_key - Your private key.
|
private_key - Your private key.
|
||||||
message_hash - The hash of the message to sign.
|
message_hash - The hash of the message to sign.
|
||||||
|
hash_size - The size of message_hash in bytes.
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
|
signature - Will be filled in with the signature value. Must be at least 2 * curve size long.
|
||||||
@@ -218,6 +219,7 @@ Returns 1 if the signature generated successfully, 0 if an error occurred.
|
|||||||
*/
|
*/
|
||||||
int uECC_sign(const uint8_t *private_key,
|
int uECC_sign(const uint8_t *private_key,
|
||||||
const uint8_t *message_hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
uint8_t *signature,
|
uint8_t *signature,
|
||||||
uECC_Curve curve);
|
uECC_Curve curve);
|
||||||
|
|
||||||
@@ -277,11 +279,13 @@ this function; however, if the RNG is defined it will improve resistance to side
|
|||||||
attacks.
|
attacks.
|
||||||
|
|
||||||
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to
|
||||||
this function along with your private key and a hash context.
|
this function along with your private key and a hash context. Note that the message_hash
|
||||||
|
does not need to be computed with the same hash function used by hash_context.
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
private_key - Your private key.
|
private_key - Your private key.
|
||||||
message_hash - The hash of the message to sign.
|
message_hash - The hash of the message to sign.
|
||||||
|
hash_size - The size of message_hash in bytes.
|
||||||
hash_context - A hash context to use.
|
hash_context - A hash context to use.
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
@@ -291,6 +295,7 @@ Returns 1 if the signature generated successfully, 0 if an error occurred.
|
|||||||
*/
|
*/
|
||||||
int uECC_sign_deterministic(const uint8_t *private_key,
|
int uECC_sign_deterministic(const uint8_t *private_key,
|
||||||
const uint8_t *message_hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
uECC_HashContext *hash_context,
|
uECC_HashContext *hash_context,
|
||||||
uint8_t *signature,
|
uint8_t *signature,
|
||||||
uECC_Curve curve);
|
uECC_Curve curve);
|
||||||
@@ -302,14 +307,16 @@ Usage: Compute the hash of the signed data using the same hash as the signer and
|
|||||||
pass it to this function along with the signer's public key and the signature values (r and s).
|
pass it to this function along with the signer's public key and the signature values (r and s).
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
public_key - The signer's public key
|
public_key - The signer's public key.
|
||||||
hash - The hash of the signed data.
|
message_hash - The hash of the signed data.
|
||||||
signature - The signature value.
|
hash_size - The size of message_hash in bytes.
|
||||||
|
signature - The signature value.
|
||||||
|
|
||||||
Returns 1 if the signature is valid, 0 if it is invalid.
|
Returns 1 if the signature is valid, 0 if it is invalid.
|
||||||
*/
|
*/
|
||||||
int uECC_verify(const uint8_t *private_key,
|
int uECC_verify(const uint8_t *private_key,
|
||||||
const uint8_t *hash,
|
const uint8_t *message_hash,
|
||||||
|
unsigned hash_size,
|
||||||
const uint8_t *signature,
|
const uint8_t *signature,
|
||||||
uECC_Curve curve);
|
uECC_Curve curve);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user