K-256#

ECDSA over the secp256k1 curve.

Available Implementations#

#include "Hacl_K256_ECDSA.h"

API Reference#

Example

// Note: HACL Packages will provide these in a later version.
#define HACL_SIGNATURE_ECDSA_K256_SECRETKEY_LEN 32

#define HACL_SIGNATURE_ECDSA_K256_PUBLICKEY_LEN 64
#define HACL_SIGNATURE_ECDSA_K256_PUBLICKEY_COMPRESSED_LEN 33
#define HACL_SIGNATURE_ECDSA_K256_PUBLICKEY_UNCOMPRESSED_LEN 65

#define HACL_SIGNATURE_ECDSA_K256_NONCE_LEN 32

#define HACL_SIGNATURE_ECDSA_K256_SIGNATURE_LEN 64
// We want to sign and verify a message.

// Message
const char* message = "Hello, World!";
uint32_t message_size = strlen(message);

// Keys
uint8_t sk[HACL_SIGNATURE_ECDSA_K256_SECRETKEY_LEN];
uint8_t pk[HACL_SIGNATURE_ECDSA_K256_PUBLICKEY_LEN];

// Note: This function is not in HACL*.
//       You need to bring your own keys.
generate_k256_keypair(sk, pk);

// Nonce
uint8_t nonce[HACL_SIGNATURE_ECDSA_K256_NONCE_LEN];

// Signature
uint8_t signature[HACL_SIGNATURE_ECDSA_K256_SIGNATURE_LEN];

// Sign
bool res_sign = Hacl_K256_ECDSA_ecdsa_sign_sha256(
  signature, message_size, (uint8_t*)message, sk, nonce);

if (!res_sign) {
  // Error
}

// Verify
bool res_verify = Hacl_K256_ECDSA_ecdsa_verify_sha256(
  message_size, (uint8_t*)message, pk, signature);

if (!res_verify) {
  // Error
}

Load and Store Keys#

void Hacl_K256_ECDSA_public_key_compressed_from_raw(uint8_t *pk, uint8_t *pk_raw)#

Convert a public key from raw to its compressed form.

The outparam pk points to 33 bytes of valid memory, i.e., uint8_t[33]. The argument pk_raw points to 64 bytes of valid memory, i.e., uint8_t[64].

The function DOESN’T check whether (x, y) is valid point.

bool Hacl_K256_ECDSA_public_key_compressed_to_raw(uint8_t *pk_raw, uint8_t *pk)#

Convert a public key from compressed to its raw form.

The function returns true for successful conversion of a public key and false otherwise.

The outparam pk_raw points to 64 bytes of valid memory, i.e., uint8_t[64]. The argument pk points to 33 bytes of valid memory, i.e., uint8_t[33].

The function also checks whether (x, y) is valid point.

void Hacl_K256_ECDSA_public_key_uncompressed_from_raw(uint8_t *pk, uint8_t *pk_raw)#

Convert a public key from raw to its uncompressed form.

The outparam pk points to 65 bytes of valid memory, i.e., uint8_t[65]. The argument pk_raw points to 64 bytes of valid memory, i.e., uint8_t[64].

The function DOESN’T check whether (x, y) is valid point.

bool Hacl_K256_ECDSA_public_key_uncompressed_to_raw(uint8_t *pk_raw, uint8_t *pk)#

Convert a public key from uncompressed to its raw form.

The function returns true for successful conversion of a public key and false otherwise.

The outparam pk_raw points to 64 bytes of valid memory, i.e., uint8_t[64]. The argument pk points to 65 bytes of valid memory, i.e., uint8_t[65].

The function DOESN’T check whether (x, y) is valid point.

Sign#

bool Hacl_K256_ECDSA_ecdsa_sign_sha256(uint8_t *signature, uint32_t msg_len, uint8_t *msg, uint8_t *private_key, uint8_t *nonce)#

Create an ECDSA signature using SHA2-256.

The function returns true for successful creation of an ECDSA signature and false otherwise.

The outparam signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64]. The argument msg points to msg_len bytes of valid memory, i.e., uint8_t[msg_len]. The arguments private_key and nonce point to 32 bytes of valid memory, i.e., uint8_t[32].

The function first hashes a message msg with SHA2-256 and then calls ecdsa_sign_hashed_msg.

The function DOESN’T perform low-S normalization, see secp256k1_ecdsa_sign_sha256 if needed.

bool Hacl_K256_ECDSA_ecdsa_sign_hashed_msg(uint8_t *signature, uint8_t *msgHash, uint8_t *private_key, uint8_t *nonce)#

Create an ECDSA signature.

The function returns true for successful creation of an ECDSA signature and false otherwise.

The outparam signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64]. The arguments msgHash, private_key, and nonce point to 32 bytes of valid memory, i.e., uint8_t[32].

The function DOESN’T perform low-S normalization, see secp256k1_ecdsa_sign_hashed_msg if needed.

The function also checks whether private_key and nonce are valid: • 0 < private_key < the order of the curve • 0 < nonce < the order of the curve

bool Hacl_K256_ECDSA_secp256k1_ecdsa_sign_sha256(uint8_t *signature, uint32_t msg_len, uint8_t *msg, uint8_t *private_key, uint8_t *nonce)#

Create an ECDSA signature using SHA2-256.

The function returns true for successful creation of an ECDSA signature and false otherwise.

The outparam signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64]. The argument msg points to msg_len bytes of valid memory, i.e., uint8_t[msg_len]. The arguments private_key and nonce point to 32 bytes of valid memory, i.e., uint8_t[32].

The function first hashes a message msg with SHA2-256 and then calls secp256k1_ecdsa_sign_hashed_msg.

The function ALWAYS performs low-S normalization, see ecdsa_sign_hashed_msg if needed.

bool Hacl_K256_ECDSA_secp256k1_ecdsa_sign_hashed_msg(uint8_t *signature, uint8_t *msgHash, uint8_t *private_key, uint8_t *nonce)#

Create an ECDSA signature.

The function returns true for successful creation of an ECDSA signature and false otherwise.

The outparam signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64]. The arguments msgHash, private_key, and nonce point to 32 bytes of valid memory, i.e., uint8_t[32].

The function ALWAYS performs low-S normalization, see ecdsa_sign_hashed_msg if needed.

The function also checks whether private_key and nonce are valid: • 0 < private_key < the order of the curve • 0 < nonce < the order of the curve

Verify#

bool Hacl_K256_ECDSA_ecdsa_verify_sha256(uint32_t msg_len, uint8_t *msg, uint8_t *public_key, uint8_t *signature)#

Verify an ECDSA signature using SHA2-256.

The function returns true if the signature is valid and false otherwise.

The argument msg points to msg_len bytes of valid memory, i.e., uint8_t[msg_len]. The arguments public_key (x || y) and signature (R || S) point to 64 bytes of valid memory, i.e., uint8_t[64].

The function first hashes a message msg with SHA2-256 and then calls ecdsa_verify_hashed_msg.

The function ACCEPTS non low-S normalized signatures, see secp256k1_ecdsa_verify_sha256 if needed.

bool Hacl_K256_ECDSA_ecdsa_verify_hashed_msg(uint8_t *m, uint8_t *public_key, uint8_t *signature)#

Verify an ECDSA signature.

The function returns true if the signature is valid and false otherwise.

The argument msgHash points to 32 bytes of valid memory, i.e., uint8_t[32]. The arguments public_key (x || y) and signature (R || S) point to 64 bytes of valid memory, i.e., uint8_t[64].

The function ACCEPTS non low-S normalized signatures, see secp256k1_ecdsa_verify_hashed_msg if needed.

The function also checks whether public key is valid.

bool Hacl_K256_ECDSA_secp256k1_ecdsa_verify_sha256(uint32_t msg_len, uint8_t *msg, uint8_t *public_key, uint8_t *signature)#

Verify an ECDSA signature using SHA2-256.

The function returns true if the signature is valid and false otherwise.

The argument msg points to msg_len bytes of valid memory, i.e., uint8_t[msg_len]. The arguments public_key (x || y) and signature (R || S) point to 64 bytes of valid memory, i.e., uint8_t[64].

The function first hashes a message msg with SHA2-256 and then calls secp256k1_ecdsa_verify_hashed_msg.

The function DOESN’T accept non low-S normalized signatures, see ecdsa_verify_sha256 if needed.

bool Hacl_K256_ECDSA_secp256k1_ecdsa_verify_hashed_msg(uint8_t *msgHash, uint8_t *public_key, uint8_t *signature)#

Verify an ECDSA signature.

The function returns true if the signature is valid and false otherwise.

The argument msgHash points to 32 bytes of valid memory, i.e., uint8_t[32]. The arguments public_key (x || y) and signature (R || S) point to 64 bytes of valid memory, i.e., uint8_t[64].

The function DOESN’T accept non low-S normalized signatures, see ecdsa_verify_hashed_msg if needed.

The function also checks whether public_key is valid

Normalization#

bool Hacl_K256_ECDSA_secp256k1_ecdsa_is_signature_normalized(uint8_t *signature)#

Check whether signature (R || S) is in canonical form.

The function returns true if S is low-S normalized and false otherwise.

The argument signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64].

bool Hacl_K256_ECDSA_secp256k1_ecdsa_signature_normalize(uint8_t *signature)#

Compute canonical lowest S value for signature (R || S).

The function returns true for successful normalization of S and false otherwise.

The argument signature (R || S) points to 64 bytes of valid memory, i.e., uint8_t[64].