279 lines
9.2 KiB
TeX
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} |