exchange/doc/cs/content/appendix/crypto_implementation.tex
Gian Demarmels 9e69499468
CS thesis
2022-02-14 00:03:06 +01:00

279 lines
9.2 KiB
TeX

\begin{lstlisting}[style=bfh-c,language=C,, caption={Crypto Implementation API}, label={lst:cryptoapi}]
#include <sodium.h>
/**
* IMPLEMENTATION NOTICE:
*
* This is an implementation of the Schnorr, Blind Schnorr and
* Clause Blind Schnorr Signature Scheme using Curve25519.
* We use libsodium wherever possible.
*
* Blind Schnorr: The Blind Schnorr Signature Scheme is BROKEN!
* Use the Clause Blind Schnorr Signature Scheme instead.
*
* Clause Blind Schnorr Signature Scheme:
* This is a variation of the Blind Schnorr Signature Scheme where all operations
* before the signature creation are performed twice.
* The signer randomly chooses one of the two sessions and only creates the signature for this session.
* Note that the Clause part needs to be implemented by whoever uses this API.
* Further details about the Clause Blind Schnorr Signature Scheme can be found here:
* https://eprint.iacr.org/2019/877.pdf
*/
/**
* Curve25519 Scalar
*/
struct GNUNET_CRYPTO_Cs25519Scalar
{
/**
* 32 byte scalar
*/
unsigned char d[crypto_core_ed25519_SCALARBYTES];
};
/**
* Curve25519 point
*/
struct GNUNET_CRYPTO_Cs25519Point
{
/**
* This is a point on the Curve25519.
* The x coordinate can be restored using the y coordinate
*/
unsigned char y[crypto_core_ed25519_BYTES];
};
/**
* The private information of an Schnorr key pair.
*/
struct GNUNET_CRYPTO_CsPrivateKey
{
struct GNUNET_CRYPTO_Cs25519Scalar scalar;
};
/**
* The public information of an Schnorr key pair.
*/
struct GNUNET_CRYPTO_CsPublicKey
{
struct GNUNET_CRYPTO_Cs25519Point point;
};
/**
* Secret used for blinding (alpha and beta).
*/
struct GNUNET_CRYPTO_CsBlindingSecret
{
struct GNUNET_CRYPTO_Cs25519Scalar alpha;
struct GNUNET_CRYPTO_Cs25519Scalar beta;
};
/**
* the private r used in the signature
*/
struct GNUNET_CRYPTO_CsRSecret
{
struct GNUNET_CRYPTO_Cs25519Scalar scalar;
};
/**
* the public R (derived from r) used in c
*/
struct GNUNET_CRYPTO_CsRPublic
{
struct GNUNET_CRYPTO_Cs25519Point point;
};
/**
* Schnorr c to be signed
*/
struct GNUNET_CRYPTO_CsC
{
struct GNUNET_CRYPTO_Cs25519Scalar scalar;
};
/**
* s in the signature
*/
struct GNUNET_CRYPTO_CsS
{
struct GNUNET_CRYPTO_Cs25519Scalar scalar;
};
/**
* blinded s in the signature
*/
struct GNUNET_CRYPTO_CsBlindS
{
struct GNUNET_CRYPTO_Cs25519Scalar scalar;
};
/**
* CS Signtature containing scalar s and point R
*/
struct GNUNET_CRYPTO_CsSignature
{
/**
* Schnorr signatures are composed of a scalar s and a curve point
*/
struct GNUNET_CRYPTO_CsS s_scalar;
struct GNUNET_CRYPTO_Cs25519Point r_point;
};
/**
* Nonce
*/
struct GNUNET_CRYPTO_CsNonce
{
/*a nonce*/
unsigned char nonce[256 / 8];
};
/**
* Create a new random private key.
*
* @param[out] priv where to write the fresh private key
*/
void
GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv);
/**
* Extract the public key of the given private key.
*
* @param priv the private key
* @param[out] pub where to write the public key
*/
void
GNUNET_CRYPTO_cs_private_key_get_public (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
struct GNUNET_CRYPTO_CsPublicKey *pub);
/**
* Derive a new secret r pair r0 and r1.
* In original papers r is generated randomly
* To provide abort-idempotency, r needs to be derived but still needs to be UNPREDICTABLE
* To ensure unpredictability a new nonce should be used when a new r needs to be derived.
* Uses HKDF internally.
* Comment: Can be done in one HKDF shot and split output.
*
* @param nonce is a random nonce
* @param lts is a long-term-secret in form of a private key
* @param[out] r array containing derived secrets r0 and r1
*/
void
GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
const struct GNUNET_CRYPTO_CsPrivateKey *lts,
struct GNUNET_CRYPTO_CsRSecret r[2]);
/**
* Extract the public R of the given secret r.
*
* @param r_priv the private key
* @param[out] r_pub where to write the public key
*/
void
GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
struct GNUNET_CRYPTO_CsRPublic *r_pub);
/**
* Derives new random blinding factors.
* In original papers blinding factors are generated randomly
* To provide abort-idempotency, blinding factors need to be derived but still need to be UNPREDICTABLE
* To ensure unpredictability a new nonce has to be used.
* Uses HKDF internally
*
* @param secret is secret to derive blinding factors
* @param secret_len secret length
* @param[out] bs array containing the two derivedGNUNET_CRYPTO_CsBlindingSecret
*/
void
GNUNET_CRYPTO_cs_blinding_secrets_derive (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
struct GNUNET_CRYPTO_CsBlindingSecret bs[2]);
/**
* Calculate two blinded c's
* Comment: One would be insecure due to Wagner's algorithm solving ROS
*
* @param bs array of the two blinding factor structs each containing alpha and beta
* @param r_pub array of the two signer's nonce R
* @param pub the public key of the signer
* @param msg the message to blind in preparation for signing
* @param msg_len length of message msg
* @param[out] blinded_c array of the two blinded c's
*/
void
GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
const struct GNUNET_CRYPTO_CsPublicKey *pub,
const void *msg,
size_t msg_len,
struct GNUNET_CRYPTO_CsC blinded_c[2]);
/**
* Sign a blinded c
* This function derives b from a nonce and a longterm secret
* In original papers b is generated randomly
* To provide abort-idempotency, b needs to be derived but still need to be UNPREDICTABLE.
* To ensure unpredictability a new nonce has to be used for every signature
* HKDF is used internally for derivation
* r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
*
* @param priv private key to use for the signing and as LTS in HKDF
* @param r array of the two secret nonce from the signer
* @param c array of the two blinded c to sign c_b
* @param nonce is a random nonce
* @param[out] blinded_signature_scalar where to write the signature
* @return 0 or 1 for b (see Clause Blind Signature Scheme)
*/
int
GNUNET_CRYPTO_cs_sign_derive(const struct GNUNET_CRYPTO_CsPrivateKey *priv,
const struct GNUNET_CRYPTO_CsRSecret r[2],
const struct GNUNET_CRYPTO_CsC c[2],
const struct GNUNET_CRYPTO_CsNonce *nonce,
struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar
);
/**
* Unblind a blind-signed signature using a c that was blinded
*
* @param blinded_signature_scalar the signature made on the blinded c
* @param bs the blinding factors used in the blinding
* @param[out] signature_scalar where to write the unblinded signature
*/
void
GNUNET_CRYPTO_cs_unblind (const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
struct GNUNET_CRYPTO_CsS *signature_scalar);
/**
* Verify whether the given message corresponds to the given signature and the
* signature is valid with respect to the given public key.
*
* @param sig signature that is being validated
* @param pub public key of the signer
* @param msg is the message that should be signed by @a sig (message is used to calculate c)
* @param msg_len is the message length
* @returns #GNUNET_YES on success, #GNUNET_SYSERR if key parameter(s) invalid #GNUNET_NO if signature invalid
*/
enum GNUNET_GenericReturnValue
GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
const struct GNUNET_CRYPTO_CsPublicKey *pub,
const void *msg,
size_t msg_len);
\end{lstlisting}