# c255b3: schnorr signatures using curve25519 and blake3.
This crate provides [Schnorr signatures][Schnorr] based on [Curve25519] and [Blake3].
[Schnorr]: https://en.wikipedia.org/wiki/Schnorr_signature
[Curve25519]: https://en.wikipedia.org/wiki/Curve25519
[Blake3]: https://github.com/BLAKE3-team/BLAKE3
Note: This is not [Ed25519], if you want Ed25519, please use the excellent [ed25519-dalek] crate.
[Ed25519]: https://en.wikipedia.org/wiki/Ed25519
[ed25519-dalek]: https://crates.io/crates/ed25519-dalek
Warning! This is an alpha version of a (slightly) novel cryptographic primitive.
It has not been audited and you may encounter breaking API and cryptographic changes until the first stable version!
Use at your own risk!
## Why?
The initial motivation was preparing for embedded versions of [converge].
We already use the Blake3 hash function for bulk data,
and adding SHA512 just for Ed25519 signatures just isn't necessary.
That said, there are other benefits:
- proper application-specific domain separation for signatures
- support for non-deterministic signatures with application-supplied nonces
- well specified secret and public keys
- a [*much* faster][Blake3] hash function
[converge]: https://adpt.dev/tools/converge
## How?
For the most part the parameterization is straight-forward.
However there are two minor deviations:
- The keyed version of Blake3 is used to provide domain separation.
- The nonce `k` is deterministic by default, a Blake3 hash of the private key and message keyed with the domain.
### Key Generation
c255b3 uses 255-bit (less 19 values) secret keys.
Contrary to Ed25519 it does not require [clamping][ed25519-clamping],
though to reuse the keys with X25519 the low three bits must be cleared.
The secret key `sk` may simply be generated as 256 random bits and reduced modulo the order of the base point (slightly more than 2²⁵²).
[ed25519-clamping]: https://www.jcraige.com/an-explainer-on-ed25519-clamping
### Signing
The first step is to generate the scalar nonce `k`.
This can be done with a random number generator,
or by taking the Blake3 hash (keyed with the domain) of the secret key concatinated with the message.
```
Now `k` multiplies the base point to get the point `r`, which we will recover later while verifying.
`r` is compressed, concatinated with the message, and fed to Blake2 to used to derive the scalar `e`.
```
r = k*B
Finally, we multiply `e` and the secret key, and subtract their product from `k`, yielding the scalar `s`.
This produces our signature, which is the tuple of `e` and `s`.
```
s = k - sk * e
sig = (e, s)
```

### Verifying
For verification we need the public key, this is found by multiplying the base point by the private key.
```
pk = sk*B
```
Then we take our signature and reconstruct `r`, calling it `rᵥ`:
```
rᵥ = s*B + e*pk = (k - sk*e)*B + (e*sk*B) = k*B - sk*e*B + e*sk*B = k*B
```
Now that we have `rᵥ`, we hash the message with Blake3 exactly as was done during signing.
This yields another copy of `e`, which we call `eᵥ`.
```
Finally we can compare `eᵥ` with the `e` from the signature, and if they match we have a valid signature.
## License
This project is dedicated to the public domain, see the [UNLICENSE](./UNLICENSE) for details.