mirror of
https://github.com/kmackay/micro-ecc.git
synced 2026-09-17 14:40:04 +00:00
Add uECC_valid_public_key() function to check if a given public key is valid. (#29)
This commit is contained in:
@@ -1852,24 +1852,28 @@ void uECC_compress(const uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_compressed
|
|||||||
p_compressed[0] = 2 + (p_publicKey[uECC_BYTES * 2 - 1] & 0x01);
|
p_compressed[0] = 2 + (p_publicKey[uECC_BYTES * 2 - 1] & 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Computes p_result = x^3 + ax + b. p_result must not overlap x. */
|
||||||
|
static void curve_x_side(uECC_word_t * RESTRICT p_result, uECC_word_t * RESTRICT x)
|
||||||
|
{
|
||||||
|
#if (uECC_CURVE == uECC_secp256k1)
|
||||||
|
vli_modSquare_fast(p_result, x); /* r = x^2 */
|
||||||
|
vli_modMult_fast(p_result, p_result, x); /* r = x^3 */
|
||||||
|
vli_modAdd(p_result, p_result, curve_b, curve_p); /* r = x^3 + b */
|
||||||
|
#else
|
||||||
|
uECC_word_t _3[uECC_WORDS] = {3}; /* -a = 3 */
|
||||||
|
|
||||||
|
vli_modSquare_fast(p_result, x); /* r = x^2 */
|
||||||
|
vli_modSub_fast(p_result, p_result, _3); /* r = x^2 - 3 */
|
||||||
|
vli_modMult_fast(p_result, p_result, x); /* r = x^3 - 3x */
|
||||||
|
vli_modAdd(p_result, p_result, curve_b, curve_p); /* r = x^3 - 3x + b */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void uECC_decompress(const uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicKey[uECC_BYTES*2])
|
void uECC_decompress(const uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicKey[uECC_BYTES*2])
|
||||||
{
|
{
|
||||||
EccPoint l_point;
|
EccPoint l_point;
|
||||||
vli_bytesToNative(l_point.x, p_compressed + 1);
|
vli_bytesToNative(l_point.x, p_compressed + 1);
|
||||||
|
curve_x_side(l_point.y, l_point.x);
|
||||||
#if (uECC_CURVE == uECC_secp256k1)
|
|
||||||
vli_modSquare_fast(l_point.y, l_point.x); /* r = x^2 */
|
|
||||||
vli_modMult_fast(l_point.y, l_point.y, l_point.x); /* r = x^3 */
|
|
||||||
vli_modAdd(l_point.y, l_point.y, curve_b, curve_p); /* r = x^3 + b */
|
|
||||||
#else
|
|
||||||
uECC_word_t _3[uECC_WORDS] = {3}; /* -a = 3 */
|
|
||||||
|
|
||||||
vli_modSquare_fast(l_point.y, l_point.x); /* y = x^2 */
|
|
||||||
vli_modSub_fast(l_point.y, l_point.y, _3); /* y = x^2 - 3 */
|
|
||||||
vli_modMult_fast(l_point.y, l_point.y, l_point.x); /* y = x^3 - 3x */
|
|
||||||
vli_modAdd(l_point.y, l_point.y, curve_b, curve_p); /* y = x^3 - 3x + b */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mod_sqrt(l_point.y);
|
mod_sqrt(l_point.y);
|
||||||
|
|
||||||
if((l_point.y[0] & 0x01) != (p_compressed[0] & 0x01))
|
if((l_point.y[0] & 0x01) != (p_compressed[0] & 0x01))
|
||||||
@@ -1881,6 +1885,34 @@ void uECC_decompress(const uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicK
|
|||||||
vli_nativeToBytes(p_publicKey + uECC_BYTES, l_point.y);
|
vli_nativeToBytes(p_publicKey + uECC_BYTES, l_point.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uECC_valid_public_key(const uint8_t p_publicKey[uECC_BYTES*2])
|
||||||
|
{
|
||||||
|
uECC_word_t l_tmp1[uECC_WORDS];
|
||||||
|
uECC_word_t l_tmp2[uECC_WORDS];
|
||||||
|
EccPoint l_public;
|
||||||
|
vli_bytesToNative(l_public.x, p_publicKey);
|
||||||
|
vli_bytesToNative(l_public.y, p_publicKey + uECC_BYTES);
|
||||||
|
|
||||||
|
// The point at infinity is invalid.
|
||||||
|
if(EccPoint_isZero(&l_public))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x and y must be smaller than p.
|
||||||
|
if(vli_cmp(curve_p, l_public.x) != 1 || vli_cmp(curve_p, l_public.y) != 1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vli_modSquare_fast(l_tmp1, l_public.y); /* tmp1 = y^2 */
|
||||||
|
|
||||||
|
curve_x_side(l_tmp2, l_public.x); /* tmp2 = x^3 + ax + b */
|
||||||
|
|
||||||
|
/* Make sure that y^2 == x^3 + ax + b */
|
||||||
|
return (vli_cmp(l_tmp1, l_tmp2) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------- ECDSA code -------- */
|
/* -------- ECDSA code -------- */
|
||||||
|
|
||||||
#if (uECC_CURVE == uECC_secp160r1)
|
#if (uECC_CURVE == uECC_secp160r1)
|
||||||
|
|||||||
@@ -110,28 +110,6 @@ Returns 1 if the shared secret was generated successfully, 0 if an error occurre
|
|||||||
*/
|
*/
|
||||||
int uECC_shared_secret(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_privateKey[uECC_BYTES], uint8_t p_secret[uECC_BYTES]);
|
int uECC_shared_secret(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_privateKey[uECC_BYTES], uint8_t p_secret[uECC_BYTES]);
|
||||||
|
|
||||||
/* uECC_compress() function.
|
|
||||||
Compress a public key.
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
p_publicKey - The public key to compress.
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
p_compressed - Will be filled in with the compressed public key.
|
|
||||||
*/
|
|
||||||
void uECC_compress(const uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_compressed[uECC_BYTES+1]);
|
|
||||||
|
|
||||||
/* uECC_decompress() function.
|
|
||||||
Decompress a compressed public key.
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
p_compressed - The compressed public key.
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
p_publicKey - Will be filled in with the decompressed public key.
|
|
||||||
*/
|
|
||||||
void uECC_decompress(const uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicKey[uECC_BYTES*2]);
|
|
||||||
|
|
||||||
/* uECC_sign() function.
|
/* uECC_sign() function.
|
||||||
Generate an ECDSA signature for a given hash value.
|
Generate an ECDSA signature for a given hash value.
|
||||||
|
|
||||||
@@ -164,6 +142,42 @@ Returns 1 if the signature is valid, 0 if it is invalid.
|
|||||||
*/
|
*/
|
||||||
int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uECC_BYTES], const uint8_t p_signature[uECC_BYTES*2]);
|
int uECC_verify(const uint8_t p_publicKey[uECC_BYTES*2], const uint8_t p_hash[uECC_BYTES], const uint8_t p_signature[uECC_BYTES*2]);
|
||||||
|
|
||||||
|
/* uECC_compress() function.
|
||||||
|
Compress a public key.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
p_publicKey - The public key to compress.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
p_compressed - Will be filled in with the compressed public key.
|
||||||
|
*/
|
||||||
|
void uECC_compress(const uint8_t p_publicKey[uECC_BYTES*2], uint8_t p_compressed[uECC_BYTES+1]);
|
||||||
|
|
||||||
|
/* uECC_decompress() function.
|
||||||
|
Decompress a compressed public key.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
p_compressed - The compressed public key.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
p_publicKey - Will be filled in with the decompressed public key.
|
||||||
|
*/
|
||||||
|
void uECC_decompress(const uint8_t p_compressed[uECC_BYTES+1], uint8_t p_publicKey[uECC_BYTES*2]);
|
||||||
|
|
||||||
|
/* uECC_valid_public_key() function.
|
||||||
|
Check to see if a public key is valid.
|
||||||
|
|
||||||
|
Note that you are not required to check for a valid public key before using any other uECC
|
||||||
|
functions. However, you may wish to avoid spending CPU time computing a shared secret or
|
||||||
|
verifying a signature using an invalid public key.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
p_publicKey - The public key to check.
|
||||||
|
|
||||||
|
Returns 1 if the public key is valid, 0 if it is invalid.
|
||||||
|
*/
|
||||||
|
int uECC_valid_public_key(const uint8_t p_publicKey[uECC_BYTES*2]);
|
||||||
|
|
||||||
/* uECC_bytes() function.
|
/* uECC_bytes() function.
|
||||||
Return the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages.
|
Return the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user