-
Notifications
You must be signed in to change notification settings - Fork 114
Public key signatures
#define CONTEXT "Example"
#define MESSAGE "Test"
#define MESSAGE_LEN 4
hydro_sign_keypair key_pair;
hydro_sign_keygen(&key_pair);
uint8_t signature[hydro_sign_BYTES];
/* Sign the message using the secret key */
hydro_sign_create(signature, MESSAGE, MESSAGE_LEN, CONTEXT, key_pair.sk);
/* Verify the signature using the public key */
if (hydro_sign_verify(signature, MESSAGE, MESSAGE_LEN, CONTEXT, key_pair.pk) != 0) {
/* forged */
}#define CONTEXT "Example"
#define MESSAGE_PART1 "first chunk"
#define MESSAGE_PART2 "second chunk"
#define MESSAGE_PART1_LEN 11
#define MESSAGE_PART2_LEN 12
hydro_sign_keypair key_pair;
hydro_sign_keygen(&key_pair);
uint8_t signature[hydro_sign_BYTES];
hydro_sign_state st;
/* Sign the message using the secret key */
hydro_sign_init(&st, CONTEXT);
hydro_sign_update(&st, MESSAGE_PART1, MESSAGE_PART1_LEN);
hydro_sign_update(&st, MESSAGE_PART2, MESSAGE_PART2_LEN);
hydro_sign_final_create(&st, signature, key_pair.sk);
/* Verify the signature using the public key */
hydro_sign_init(&st, CONTEXT);
hydro_sign_update(&st, MESSAGE_PART1, MESSAGE_PART1_LEN);
hydro_sign_update(&st, MESSAGE_PART2, MESSAGE_PART2_LEN);
if (hydro_sign_final_verify(&st, signature, key_pair.pk) != 0) {
/* forged */
}In this system, a signer generates a key pair:
- a secret key, that will be used to sign any number of messages
- a public key, that anybody can use to verify that the signature for a message was actually issued by the creator of the public key.
Verifiers need to already know and ultimately trust a public key before messages signed using it can be verified.
void hydro_sign_keygen(hydro_sign_keypair *kp);The hydro_sign_keygen() function generates a secret key and a corresponding public key. The public key is put into kp->pk (hydro_sign_PUBLICKEYBYTES bytes) and the secret key into kp->sk (hydro_sign_SECRETKEYBYTES bytes).
void hydro_sign_keygen_deterministic(
hydro_sign_keypair *kp, const uint8_t seed[hydro_sign_SEEDBYTES]);Using hydro_sign_keygen_deterministic(), the key pair can be deterministically derived from a single key seed (hydro_sign_SEEDBYTES bytes).
int hydro_sign_create(uint8_t csig[hydro_sign_BYTES], const void *m_,
size_t mlen, const char ctx[hydro_sign_CONTEXTBYTES],
const uint8_t sk[hydro_sign_SECRETKEYBYTES]);The hydro_sign_create() function computes a signature for a message m_ whose length is mlen bytes, using the secret key sk and a context ctx.
The signature is put into csig, and is hydro_sign_BYTES bytes long.
int hydro_sign_verify(const uint8_t csig[hydro_sign_BYTES], const void *m_,
size_t mlen, const char ctx[hydro_sign_CONTEXTBYTES],
const uint8_t pk[hydro_sign_PUBLICKEYBYTES]);The hydro_sign_verify() function checks that the signed message m_ whose length is smlen bytes has a valid signature for the public key pk and the context ctx.
If the signature is doesn't appear to be valid, the function returns -1.
On success, it returns 0.
If the whole message doesn't fit in memory, it can be provided as a sequence of arbitrarily-sized chunks.
The multi-part API is almost the same for signing and for verification.
int hydro_sign_init(
hydro_sign_state *state, const char ctx[hydro_sign_CONTEXTBYTES]);
int hydro_sign_update(hydro_sign_state *state, const void *m_, size_t mlen);
int hydro_sign_final_create(hydro_sign_state *state,
uint8_t csig[hydro_sign_BYTES],
const uint8_t sk[hydro_sign_SECRETKEYBYTES]);
int hydro_sign_final_verify(hydro_sign_state *state,
const uint8_t csig[hydro_sign_BYTES],
const uint8_t pk[hydro_sign_PUBLICKEYBYTES]);The hydro_sign_init() function initializes a state state using the context ctx.
Individual chunks composing the entire message can then be hashed using hydro_sign_update().
In this function m_ is the address of a chunk, and mlen its own length.
Finally:
-
hydro_sign_final_create()can be used to compute a signature using the secret keysk. - or
hydro_sign_final_verify()can be used to verify a signature using the public keypk.
hydro_sign_final_verify() returns -1 if the signature doesn't appear to be valid for the given message, context and public key, or 0 if it could be successfully verified.
#define hydro_sign_BYTES 64
#define hydro_sign_CONTEXTBYTES 8
#define hydro_sign_PUBLICKEYBYTES 32
#define hydro_sign_SECRETKEYBYTES 64
#define hydro_sign_SEEDBYTES 32typedef struct hydro_sign_state {
hydro_hash_state hash_st;
} hydro_sign_state;
typedef struct hydro_sign_keypair {
uint8_t pk[hydro_sign_PUBLICKEYBYTES];
uint8_t sk[hydro_sign_SECRETKEYBYTES];
} hydro_sign_keypair;The nonces are non-deterministic. They are computed using the output of the CSPRNG as well as a hash of the message to be signed. As a result, signing the same message multiple times can produce different, all valid signatures. However, only the owner of the secret key can compute a valid signature.