diff --git a/include/paseto.h b/include/paseto.h index ba4368f..5e07e24 100644 --- a/include/paseto.h +++ b/include/paseto.h @@ -17,6 +17,26 @@ extern "C"{ #define paseto_v2_PUBLIC_PUBLICKEYBYTES 32U #define paseto_v2_PUBLIC_SECRETKEYBYTES 64U +enum paseto_key_header { + V2_LOCAL = 4, + V2_PUBLIC = 5 +}; + +struct paseto_v2_local_key { + paseto_key_header header; + uint8_t key_bytes[paseto_v2_LOCAL_KEYBYTES]; +}; + +struct paseto_v2_local_pk { + paseto_key_header header; + uint8_t key_bytes[paseto_v2_PUBLIC_PUBLICKEYBYTES]; +}; + +struct paseto_v2_local_sk { + paseto_key_header header; + uint8_t key_bytes[paseto_v2_PUBLIC_SECRETKEYBYTES]; +}; + /** * Initialize the library. Must be called before using any functionality. */ @@ -32,14 +52,14 @@ void paseto_free(void *p); * Returns false on error and sets errno. */ bool paseto_v2_local_load_key_hex( - uint8_t key[paseto_v2_LOCAL_KEYBYTES], const char *key_hex); + struct paseto_v2_local_key *key, const char *key_hex); /** * Load a base64-url-encoded key (without padding). * Returns false on error and sets errno. */ bool paseto_v2_local_load_key_base64( - uint8_t key[paseto_v2_LOCAL_KEYBYTES], const char *key_base64); + struct paseto_v2_local_key *key, const char *key_base64); /** * Encrypt and encode `message` using `key`, attaching `footer` if it is not NULL. @@ -49,7 +69,7 @@ bool paseto_v2_local_load_key_base64( */ char *paseto_v2_local_encrypt( const uint8_t *message, size_t message_len, - const uint8_t key[paseto_v2_LOCAL_KEYBYTES], + const struct paseto_v2_local_key *key, const uint8_t *footer, size_t footer_len); /** @@ -66,14 +86,14 @@ char *paseto_v2_local_encrypt( */ uint8_t *paseto_v2_local_decrypt( const char *encoded, size_t *message_len, - const uint8_t key[paseto_v2_LOCAL_KEYBYTES], + const struct paseto_v2_local_key *key, uint8_t **footer, size_t *footer_len); /** * Load a hex-encoded key. Returns false on error and sets errno. */ bool paseto_v2_public_load_public_key_hex( - uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + struct paseto_v2_public_pk *key, const char *key_hex); /** @@ -81,7 +101,7 @@ bool paseto_v2_public_load_public_key_hex( * Returns false on error and sets errno. */ bool paseto_v2_public_load_public_key_base64( - uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + struct paseto_v2_public_pk *key, const char *key_base64); /** @@ -89,7 +109,7 @@ bool paseto_v2_public_load_public_key_base64( * Returns false on error and sets errno. */ bool paseto_v2_public_load_secret_key_hex( - uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + struct paseto_v2_public_sk *key, const char *key_hex); /** @@ -97,7 +117,7 @@ bool paseto_v2_public_load_secret_key_hex( * Returns false on error and sets errno. */ bool paseto_v2_public_load_secret_key_base64( - uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + struct paseto_v2_public_sk *key, const char *key_base64); /** @@ -108,7 +128,7 @@ bool paseto_v2_public_load_secret_key_base64( */ char *paseto_v2_public_sign( const uint8_t *message, size_t message_len, - const uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + const struct paseto_v2_public_sk *key, const uint8_t *footer, size_t footer_len); /** @@ -123,7 +143,7 @@ char *paseto_v2_public_sign( */ uint8_t *paseto_v2_public_verify( const char *encoded, size_t *message_len, - const uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + const struct paseto_v2_public_pk *key, uint8_t **footer, size_t *footer_len); diff --git a/src/paseto_v2_local.c b/src/paseto_v2_local.c index b971e78..f490124 100644 --- a/src/paseto_v2_local.c +++ b/src/paseto_v2_local.c @@ -17,16 +17,22 @@ static const size_t mac_len = crypto_aead_xchacha20poly1305_ietf_ABYTES; bool paseto_v2_local_load_key_hex( - uint8_t key[paseto_v2_LOCAL_KEYBYTES], + struct paseto_v2_local_key *key, const char *key_hex) { - return key_load_hex(key, paseto_v2_LOCAL_KEYBYTES, key_hex); + struct paseto_v2_local_key tmp; + *key = &tmp; + key->header = V2_LOCAL; + return key_load_hex(key->key_bytes, paseto_v2_LOCAL_KEYBYTES, key_hex); } bool paseto_v2_local_load_key_base64( - uint8_t key[paseto_v2_LOCAL_KEYBYTES], + struct paseto_v2_local_key *key, const char *key_base64) { - return key_load_base64(key, paseto_v2_LOCAL_KEYBYTES, key_base64); + struct paseto_v2_local_key tmp; + *key = &tmp; + key->header = V2_LOCAL; + return key_load_base64(key->key_bytes, paseto_v2_LOCAL_KEYBYTES, key_base64); } @@ -52,12 +58,16 @@ generate_nonce_fn generate_nonce = default_generate_nonce; char *paseto_v2_local_encrypt( const uint8_t *message, size_t message_len, - const uint8_t key[paseto_v2_LOCAL_KEYBYTES], + const struct paseto_v2_local_key *key, const uint8_t *footer, size_t footer_len) { if (!message || !key) { errno = EINVAL; return NULL; } + if (key->header != V2_LOCAL) { + errno = EINVAL; + return NULL; + } if (!footer) footer_len = 0; if (!footer_len) footer = NULL; @@ -89,7 +99,7 @@ char *paseto_v2_local_encrypt( ct, NULL, message, message_len, pa.base, pre_auth_len, - NULL, nonce, key); + NULL, nonce, key->key_bytes); free(pa.base); @@ -134,12 +144,16 @@ char *paseto_v2_local_encrypt( uint8_t *paseto_v2_local_decrypt( const char *encoded, size_t *message_len, - const uint8_t key[paseto_v2_LOCAL_KEYBYTES], + const struct paseto_v2_local_key *key, uint8_t **footer, size_t *footer_len) { if (!encoded || !message_len || !key) { errno = EINVAL; return NULL; } + if (key->header != V2_LOCAL) { + errno = EINVAL; + return NULL; + } if (strlen(encoded) < header_len + sodium_base64_ENCODED_LEN( paseto_v2_LOCAL_NONCEBYTES + mac_len, @@ -233,7 +247,7 @@ uint8_t *paseto_v2_local_decrypt( NULL, ct, ct_len, pa.base, pre_auth_len, - nonce, key) != 0) { + nonce, key->key_bytes) != 0) { free(decoded); free(pa.base); free(message); diff --git a/src/paseto_v2_public.c b/src/paseto_v2_public.c index d29d202..6668555 100644 --- a/src/paseto_v2_public.c +++ b/src/paseto_v2_public.c @@ -21,41 +21,57 @@ static const size_t signature_len = crypto_sign_BYTES; bool paseto_v2_public_load_public_key_hex( - uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + struct paseto_v2_public_pk *key, const char *key_hex) { - return key_load_hex(key, paseto_v2_PUBLIC_PUBLICKEYBYTES, key_hex); + struct paseto_v2_public_pk tmp; + *key = &tmp; + key->header = V2_PUBLIC; + return key_load_hex(key->key_bytes, paseto_v2_PUBLIC_PUBLICKEYBYTES, key_hex); } bool paseto_v2_public_load_public_key_base64( - uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + struct paseto_v2_public_pk *key, const char *key_base64) { - return key_load_base64(key, paseto_v2_PUBLIC_PUBLICKEYBYTES, key_base64); + struct paseto_v2_public_pk tmp; + *key = &tmp; + key->header = V2_PUBLIC; + return key_load_base64(key->key_bytes, paseto_v2_PUBLIC_PUBLICKEYBYTES, key_base64); } bool paseto_v2_public_load_secret_key_hex( - uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + struct paseto_v2_public_sk key, const char *key_hex) { - return key_load_hex(key, paseto_v2_PUBLIC_SECRETKEYBYTES, key_hex); + struct paseto_v2_public_sk tmp; + *key = &tmp; + key->header = V2_PUBLIC; + return key_load_hex(key->key_bytes, paseto_v2_PUBLIC_SECRETKEYBYTES, key_hex); } bool paseto_v2_public_load_secret_key_base64( - uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + v2_public_sk key, const char *key_base64) { - return key_load_base64(key, paseto_v2_PUBLIC_SECRETKEYBYTES, key_base64); + struct paseto_v2_public_sk tmp; + *key = &tmp; + key->header = V2_PUBLIC; + return key_load_base64(key->key_bytes, paseto_v2_PUBLIC_SECRETKEYBYTES, key_base64); } char *paseto_v2_public_sign( const uint8_t *message, size_t message_len, - const uint8_t key[paseto_v2_PUBLIC_SECRETKEYBYTES], + struct paseto_v2_public_sk *key, const uint8_t *footer, size_t footer_len) { if (!message || !key) { errno = EINVAL; return NULL; } + if (key->header != V2_PUBLIC) { + errno = EINVAL; + return NULL; + } if (!footer) footer_len = 0; if (!footer_len) footer = NULL; @@ -79,7 +95,7 @@ char *paseto_v2_public_sign( size_t pre_auth_len = pa.current - pa.base; uint8_t *ct = to_encode + message_len; - crypto_sign_detached(ct, NULL, pa.base, pre_auth_len, key); + crypto_sign_detached(ct, NULL, pa.base, pre_auth_len, key->key_bytes); free(pa.base); @@ -124,12 +140,16 @@ char *paseto_v2_public_sign( uint8_t *paseto_v2_public_verify( const char *encoded, size_t *message_len, - const uint8_t key[paseto_v2_PUBLIC_PUBLICKEYBYTES], + const struct paseto_v2_public_pk *key, uint8_t **footer, size_t *footer_len) { if (!encoded || !message_len || !key) { errno = EINVAL; return NULL; } + if (key->header != V2_PUBLIC) { + errno = EINVAL; + return NULL; + } if (strlen(encoded) < header_len + sodium_base64_ENCODED_LEN( signature_len, sodium_base64_VARIANT_URLSAFE_NO_PADDING) - 1 @@ -215,7 +235,7 @@ uint8_t *paseto_v2_public_verify( return NULL; } if (crypto_sign_verify_detached( - signature, pa.base, pre_auth_len, key) != 0) { + signature, pa.base, pre_auth_len, key->key_bytes) != 0) { free(decoded); free(decoded_footer); free(pa.base);