Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions include/paseto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything in the header should be namespaced/prefixed so it doesn't potentially collide with other libraries or code. Enums aren't namespaced in C(++).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. We don't normally do C development and was hoping the CI pipeline would catch these bugs.

};

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.
*/
Expand All @@ -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.
Expand All @@ -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);

/**
Expand All @@ -66,38 +86,38 @@ 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);

/**
* Load a base64-url-encoded key (without padding).
* 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);

/**
* Load a hex-encoded key.
* 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);

/**
* Load a base64-url-encoded key (without padding).
* 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);

/**
Expand All @@ -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);

/**
Expand All @@ -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);


Expand Down
30 changes: 22 additions & 8 deletions src/paseto_v2_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand All @@ -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;

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
44 changes: 32 additions & 12 deletions src/paseto_v2_public.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no point in doing this, since tmp does not get initialized in C, you can just drop it. Also the &tmp is plain wrong, you can't the address of a variable on the stack and returns it; aside from the fact that this doesn't even compile. Please test your patches before you send them, the readme contains the few simple instructions necessary.

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;

Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down