Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jedisct1/libsodium-signcryption
Signcryption using libsodium.
https://github.com/jedisct1/libsodium-signcryption
encryption libsodium ristretto255 signature signcryption
Last synced: 2 months ago
JSON representation
Signcryption using libsodium.
- Host: GitHub
- URL: https://github.com/jedisct1/libsodium-signcryption
- Owner: jedisct1
- License: mit
- Created: 2020-05-11T23:22:45.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2024-02-16T17:09:11.000Z (10 months ago)
- Last Synced: 2024-10-05T04:35:45.655Z (3 months ago)
- Topics: encryption, libsodium, ristretto255, signature, signcryption
- Language: C
- Homepage:
- Size: 40 KB
- Stars: 58
- Watchers: 5
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# signcryption using libsodium
An implementation of the Toorani-Beheshti signcryption scheme, instantiated over the Ristretto255 group.
## Why
Traditional authenticated encryption with a shared key allows two or more parties to decrypt a ciphertext and verify that it was created by a member of the group knowing that secret key.
However, it doesn't allow verification of who in a group originally created a message.
In order to do so, authenticated encryption has to be combined with signatures.
The Toorani-Beheshti signcryption scheme achieves this using a single key pair per device, with forward security and public verifiability.
## Parameter definitions
- `sender_id`: an identifier for a sender. It may be the sender's public key but it doesn't have to. It can also be an account number, or anything that can uniquely identify a user. It doesn't need to be secret, nor have high entropy. A user can send messages from multiple devices, each with their own key pair, with `sender_id` remaining the same.
- `recipient_id`: an identifier for the recipient of a message. It can represent a specific party, or, for a message sent to a group, a group identifier.
- `info`: this describes the context in which a message was sent. Signature verification will fail if the context expected by the verifier doesn't match the one the signature was originally created for.
- `shared_key`: a shared secret key, used for encryption. The scheme only generates shared secrets; applications are free to use them with the encryption system of their choice.## Algorithm summary
```
(a, A) = sender_sk, sender_pk
(b, B) = recipent_sk, recipient_pkr = H("nonce", sender_sk, recipient_pk, noise, plaintext)
R = rG
K = (Ra + r)B
x = H("shared_key", K, sender_id, recipient_id, info)
y = H("sign_key", R, sender_id, recipient_id, info, ciphertext)
R = rG
s = ya - rsignature = (R, s) = (rG, ya - r)
K = b(RA + R)
S = (sG + R)Aalternatively:
S = A^2 + R
```## Source code
- The `src/tbsbr` directory contains the main source code, with the scheme implemented using the BLAKE2b hash function and the Ristretto255 group. This is the recommended version.
- As an alternative, the `src/tbsbe` directory contains a version using the standard edwards25519 encoding.The API decription below assumes that the `tbsbr` version is being used, but both versions have the exact same API with a different prefix.
## Key pair creation
```c
void crypto_signcrypt_tbsbr_keygen(unsigned char pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
unsigned char sk[crypto_signcrypt_tbsbr_SECRETKEYBYTES]);
```Create a new key pair, putting the public key into `pk` and the secret into `sk`.
```c
void crypto_signcrypt_tbsbr_seed_keygen(unsigned char pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
unsigned char sk[crypto_signcrypt_tbsbr_SECRETKEYBYTES],
const unsigned char seed[crypto_signcrypt_tbsbr_SEEDBYTES]);
```Create a deterministic key pair from the seed `seed`.
## Signcryption
These functions are called by the sender.
```c
int crypto_signcrypt_tbsbr_sign_before(
unsigned char st[crypto_signcrypt_tbsbr_STATEBYTES],
unsigned char shared_key[crypto_signcrypt_tbsbr_SHAREDBYTES],
const unsigned char *sender_id, size_t sender_id_len,
const unsigned char *recipient_id, size_t recipient_id_len,
const unsigned char *info, size_t info_len,
const unsigned char sender_sk[crypto_signcrypt_tbsbr_SECRETKEYBYTES],
const unsigned char recipient_pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
const unsigned char *m, size_t m_len);
```This function computes a shared key `shared_key` that can later be used to encrypt a message from `sender_id` to `recipient_id` in the `info` context.
`m` is the message to be encrypted, and `m_len` its size in bytes. On a system with a reliable secure random number generator, this is optional and `m` can be set to `NULL`, with `m_len` set to `0`.
`shared_key` can then be used to encrypt the message with any authenticated encryption system.
`st` will contain the state, required for the `sign_after` step.
The function returns `-1` or error, `0` on success.
```c
int crypto_signcrypt_tbsbr_sign_after(
unsigned char st[crypto_signcrypt_tbsbr_STATEBYTES],
unsigned char sig[crypto_signcrypt_tbsbr_SIGNBYTES],
const unsigned char sender_sk[crypto_signcrypt_tbsbr_SECRETKEYBYTES],
const unsigned char *c, size_t c_len);
```Once the message has been encrypted, it must be signed with this function. `c` is the ciphertext, and `c_len` its length.
The signature is stored into `sig`.
The function returns `-1` or error, `0` on success.
A typical signcryption sequence is thus:
1. `crypto_signcrypt_tbsbr_sign_before()`
2. encrypt with `shared_key`
3. `crypto_signcrypt_tbsbr_sign_after()`## Unsigncryption
The functions are called by the recipient.
```c
int crypto_signcrypt_tbsbr_verify_before(
unsigned char st[crypto_signcrypt_tbsbr_STATEBYTES],
unsigned char shared_key[crypto_signcrypt_tbsbr_SHAREDBYTES],
const unsigned char sig[crypto_signcrypt_tbsbr_SIGNBYTES],
const unsigned char *sender_id, size_t sender_id_len,
const unsigned char *recipient_id, size_t recipient_id_len,
const unsigned char *info, size_t info_len,
const unsigned char sender_pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
const unsigned char recipient_sk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES]);
```This function creates a state `st` and recovers the encryption shared key `shared_key` from the signature `sig`, the message sender identifier `sender_id`, the recipient `recipient_len`, the context `info`, the sender's public key `sender_pk` and the recipent's secret key `recipient_sk`.
The shared key can then be used to decrypt the ciphertext.
The function returns `-1` or error, `0` on success.
```c
int crypto_signcrypt_tbsbr_verify_after(
unsigned char st[crypto_signcrypt_tbsbr_STATEBYTES],
const unsigned char sig[crypto_signcrypt_tbsbr_SIGNBYTES],
const unsigned char sender_pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
const unsigned char *c, size_t c_len);
```This function verifies that the signature `sig` is valid for the ciphertext `c` of length `c_len` bytes, the sender's public key `sender_pk` and the previously computed state `st`.
It returns `-1` is the verification failed, and `0` if it succeeded.
A typical unsigncryption sequence is thus:
1. `crypto_signcrypt_tbsbr_verify_before()`
2. decrypt with `shared_key`
3. `crypto_signcrypt_tbsbr_verify_after()` - The return of that function *must* be checked.## Public verification
The fact that a message was sent by a specific sender to a specific recipient in a specific context can also be publicly verified, without giving the ability to decrypt the ciphertext.
```c
int crypto_signcrypt_tbsbr_verify_public(
const unsigned char sig[crypto_signcrypt_tbsbr_SIGNBYTES],
const unsigned char *sender_id, size_t sender_id_len,
const unsigned char *recipient_id, size_t recipient_id_len,
const unsigned char *info, size_t info_len,
const unsigned char sender_pk[crypto_signcrypt_tbsbr_PUBLICKEYBYTES],
const unsigned char *c, size_t c_len);
```This function verifies that `sig` is a valid signature for the ciphertext `c` of length `c_len` bytes, the sender identifier `sender_id`, the recipient `recipient_id`, the context `info`, and the sender's public key `sender_pk`.
## Constants
- `crypto_signcrypt_tbsbr_SECRETKEYBYTES` = 32
- `crypto_signcrypt_tbsbr_PUBLICKEYBYTES` = 32
- `crypto_signcrypt_tbsbr_SHAREDBYTES` = 32
- `crypto_signcrypt_tbsbr_SEEDBYTES` = 64
- `crypto_signcrypt_tbsbr_SIGNBYTES` = 64
- `crypto_signcrypt_tbsbr_STATEBYTES` = 512## Other implementations
- [signcryption](https://crates.io/crates/signcryption) is a port to the Rust programming language.
## References
- _A Directly Public Verifiable Signcryption Scheme based on Elliptic Curves_ [[PDF]](https://arxiv.org/ftp/arxiv/papers/1002/1002.3316.pdf) (M. Toorani, A. Beheshti).