aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2022-03-27 17:12:52 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2022-03-27 17:12:52 +0200
commitce38d1f6c9bd7857a1c3bc2094a0ee9752b86c32 (patch)
tree984ac3c3018e218acd74c5866a3df2169bfd0557 /src/include
parent1e4d6256731d69f1309ff8439569c65d2e1384a0 (diff)
downloadgnunet-ce38d1f6c9bd7857a1c3bc2094a0ee9752b86c32.tar.gz
gnunet-ce38d1f6c9bd7857a1c3bc2094a0ee9752b86c32.zip
Edx25519 implemented
Edx25519 is a variant of EdDSA on curve25519 which allows for repeated derivation of private and public keys, independently. The private keys in Edx25519 initially correspond to the data after expansion and clamping in EdDSA. However, this correspondence is lost after deriving further keys from existing ones. The public keys and signature verification are compatible with EdDSA. The ability to repeatedly derive key material is used for example in the context of age restriction in GNU Taler. The scheme that has been implemented is as follows: /* Private keys in Edx25519 are pairs (a, b) of 32 byte each. * Initially they correspond to the result of the expansion * and clamping in EdDSA. */ Edx25519_generate_private(seed) { /* EdDSA expand and clamp */ dh := SHA-512(seed) a := dh[0..31] b := dh[32..64] a[0] &= 0b11111000 a[31] &= 0b01111111 a[31] |= 0b01000000 return (a, b) } Edx25519_public_from_private(private) { /* Public keys are the same as in EdDSA */ (a, _) := private return [a] * G } Edx25519_blinding_factor(P, seed) { /* This is a helper function used in the derivation of * private/public keys from existing ones. */ h1 := HKDF_32(P, seed) /* Ensure that h == h % L */ h := h1 % L /* Optionally: Make sure that we don't create weak keys. */ P' := [h] * P if !( (h!=1) && (h!=0) && (P'!=E) ) { return Edx25519_blinding_factor(P, seed+1) } return h } Edx25519_derive_private(private, seed) { /* This is based on the definition in * GNUNET_CRYPTO_eddsa_private_key_derive. But it accepts * and returns a private pair (a, b) and allows for iteration. */ (a, b) := private P := Edx25519_public_key_from_private(private) h := Edx25519_blinding_factor(P, seed) /* Carefully calculate the new value for a */ a1 := a / 8; a2 := (h * a1) % L a' := (a2 * 8) % L /* Update b as well, binding it to h. This is an additional step compared to GNS. */ b' := SHA256(b ∥ h) return (a', b') } Edx25519_derive_public(P, seed) { h := Edx25519_blinding_factor(P, seed) return [h]*P } Edx25519_sign(private, message) { /* As in Ed25519, except for the origin of b */ (d, b) := private P := Edx25519_public_from_private(private) r := SHA-512(b ∥ message) R := [r] * G s := r + SHA-512(R ∥ P ∥ message) * d % L return (R,s) } Edx25519_verify(P, message, signature) { /* Identical to Ed25519 */ (R, s) := signature return [s] * G == R + [SHA-512(R ∥ P ∥ message)] * P }
Diffstat (limited to 'src/include')
-rw-r--r--src/include/gnunet_crypto_lib.h235
1 files changed, 233 insertions, 2 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 77abab45d..582a58861 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -287,6 +287,59 @@ struct GNUNET_CRYPTO_EddsaPrivateScalar
287 unsigned char s[512 / 8]; 287 unsigned char s[512 / 8];
288}; 288};
289 289
290/**
291 * Private ECC key material encoded for transmission. To be used only for
292 * Edx25519 signatures. An inital key corresponds to data from the key
293 * expansion and clamping in the EdDSA key generation.
294 */
295struct GNUNET_CRYPTO_Edx25519PrivateKey
296{
297 /**
298 * a is a value mod n, where n has at most 256 bits. It is the first half of
299 * the seed-expansion of EdDSA and will be clamped.
300 */
301 unsigned char a[256 / 8];
302
303 /**
304 * b consists of 32 bytes which where originally the lower 32bytes of the key
305 * expansion. Subsequent calls to derive_private will change this value, too.
306 */
307 unsigned char b[256 / 8];
308};
309
310
311/**
312 * Public ECC key (always for curve Ed25519) encoded in a format suitable for
313 * network transmission and Edx25519 (same as EdDSA) signatures. Refer to
314 * section 5.1.3 of rfc8032, for a thorough explanation of how this value maps
315 * to the x- and y-coordinates.
316 */
317struct GNUNET_CRYPTO_Edx25519PublicKey
318{
319 /**
320 * Point Q consists of a y-value mod p (256 bits); the x-value is
321 * always positive. The point is stored in Ed25519 standard
322 * compact format.
323 */
324 unsigned char q_y[256 / 8];
325};
326
327/**
328 * @brief an ECC signature using Edx25519 (same as in EdDSA).
329 */
330struct GNUNET_CRYPTO_Edx25519Signature
331{
332 /**
333 * R value.
334 */
335 unsigned char r[256 / 8];
336
337 /**
338 * S value.
339 */
340 unsigned char s[256 / 8];
341};
342
290 343
291/** 344/**
292 * @brief type for session keys 345 * @brief type for session keys
@@ -1279,6 +1332,17 @@ GNUNET_CRYPTO_eddsa_key_get_public (
1279 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, 1332 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1280 struct GNUNET_CRYPTO_EddsaPublicKey *pub); 1333 struct GNUNET_CRYPTO_EddsaPublicKey *pub);
1281 1334
1335/**
1336 * @ingroup crypto
1337 * Extract the public key for the given private key.
1338 *
1339 * @param priv the private key
1340 * @param pub where to write the public key
1341 */
1342void
1343GNUNET_CRYPTO_edx25519_key_get_public (
1344 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
1345 struct GNUNET_CRYPTO_Edx25519PublicKey *pub);
1282 1346
1283/** 1347/**
1284 * @ingroup crypto 1348 * @ingroup crypto
@@ -1465,6 +1529,30 @@ GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
1465 1529
1466/** 1530/**
1467 * @ingroup crypto 1531 * @ingroup crypto
1532 * Create a new private key.
1533 *
1534 * @param[out] pk private key to initialize
1535 */
1536void
1537GNUNET_CRYPTO_edx25519_key_create (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1538
1539/**
1540 * @ingroup crypto
1541 * Create a new private key for Edx25519 from a given seed. After expanding
1542 * the seed, the first half of the key will be clamped according to EdDSA.
1543 *
1544 * @param seed seed input
1545 * @param seedsize size of the seed in bytes
1546 * @param[out] pk private key to initialize
1547 */
1548void
1549GNUNET_CRYPTO_edx25519_key_create_from_seed (
1550 const void *seed,
1551 size_t seedsize,
1552 struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1553
1554/**
1555 * @ingroup crypto
1468 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear(). 1556 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
1469 * 1557 *
1470 * @param[out] pk set to fresh private key; 1558 * @param[out] pk set to fresh private key;
@@ -1492,6 +1580,14 @@ GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
1492void 1580void
1493GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk); 1581GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk);
1494 1582
1583/**
1584 * @ingroup crypto
1585 * Clear memory that was used to store a private key.
1586 *
1587 * @param pk location of the key
1588 */
1589void
1590GNUNET_CRYPTO_edx25519_key_clear (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk);
1495 1591
1496/** 1592/**
1497 * @ingroup crypto 1593 * @ingroup crypto
@@ -1874,6 +1970,53 @@ GNUNET_CRYPTO_ecdsa_sign_ (
1874 sig)); \ 1970 sig)); \
1875} while (0) 1971} while (0)
1876 1972
1973/**
1974 * @ingroup crypto
1975 * @brief Edx25519 sign a given block.
1976 *
1977 * The @a purpose data is the beginning of the data of which the signature is
1978 * to be created. The `size` field in @a purpose must correctly indicate the
1979 * number of bytes of the data structure, including its header. If possible,
1980 * use #GNUNET_CRYPTO_edx25519_sign() instead of this function (only if @a
1981 * validate is not fixed-size, you must use this function directly).
1982 *
1983 * @param priv private key to use for the signing
1984 * @param purpose what to sign (size, purpose)
1985 * @param[out] sig where to write the signature
1986 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1987 */
1988enum GNUNET_GenericReturnValue
1989GNUNET_CRYPTO_edx25519_sign_ (
1990 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
1991 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1992 struct GNUNET_CRYPTO_Edx25519Signature *sig);
1993
1994
1995/**
1996 * @ingroup crypto
1997 * @brief Edx25519 sign a given block. The resulting signature is compatible
1998 * with EdDSA.
1999 *
2000 * The @a ps data must be a fixed-size struct for which the signature is to be
2001 * created. The `size` field in @a ps->purpose must correctly indicate the
2002 * number of bytes of the data structure, including its header.
2003 *
2004 * @param priv private key to use for the signing
2005 * @param ps packed struct with what to sign, MUST begin with a purpose
2006 * @param[out] sig where to write the signature
2007 */
2008#define GNUNET_CRYPTO_edx25519_sign(priv,ps,sig) do { \
2009 /* check size is set correctly */ \
2010 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
2011 /* check 'ps' begins with the purpose */ \
2012 GNUNET_static_assert (((void*) (ps)) == \
2013 ((void*) &(ps)->purpose)); \
2014 GNUNET_assert (GNUNET_OK == \
2015 GNUNET_CRYPTO_edx25519_sign_ (priv, \
2016 &(ps)->purpose, \
2017 sig)); \
2018} while (0)
2019
1877 2020
1878/** 2021/**
1879 * @ingroup crypto 2022 * @ingroup crypto
@@ -1917,7 +2060,7 @@ GNUNET_CRYPTO_eddsa_verify_ (
1917 */ 2060 */
1918#define GNUNET_CRYPTO_eddsa_verify(purp,ps,sig,pub) ({ \ 2061#define GNUNET_CRYPTO_eddsa_verify(purp,ps,sig,pub) ({ \
1919 /* check size is set correctly */ \ 2062 /* check size is set correctly */ \
1920 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \ 2063 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
1921 /* check 'ps' begins with the purpose */ \ 2064 /* check 'ps' begins with the purpose */ \
1922 GNUNET_static_assert (((void*) (ps)) == \ 2065 GNUNET_static_assert (((void*) (ps)) == \
1923 ((void*) &(ps)->purpose)); \ 2066 ((void*) &(ps)->purpose)); \
@@ -1927,7 +2070,6 @@ GNUNET_CRYPTO_eddsa_verify_ (
1927 pub); \ 2070 pub); \
1928 }) 2071 })
1929 2072
1930
1931/** 2073/**
1932 * @ingroup crypto 2074 * @ingroup crypto
1933 * @brief Verify ECDSA signature. 2075 * @brief Verify ECDSA signature.
@@ -1982,6 +2124,58 @@ GNUNET_CRYPTO_ecdsa_verify_ (
1982 2124
1983/** 2125/**
1984 * @ingroup crypto 2126 * @ingroup crypto
2127 * @brief Verify Edx25519 signature.
2128 *
2129 * The @a validate data is the beginning of the data of which the signature
2130 * is to be verified. The `size` field in @a validate must correctly indicate
2131 * the number of bytes of the data structure, including its header. If @a
2132 * purpose does not match the purpose given in @a validate (the latter must be
2133 * in big endian), signature verification fails. If possible, use
2134 * #GNUNET_CRYPTO_edx25519_verify() instead of this function (only if @a
2135 * validate is not fixed-size, you must use this function directly).
2136 *
2137 * @param purpose what is the purpose that the signature should have?
2138 * @param validate block to validate (size, purpose, data)
2139 * @param sig signature that is being validated
2140 * @param pub public key of the signer
2141 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
2142 */
2143enum GNUNET_GenericReturnValue
2144GNUNET_CRYPTO_edx25519_verify_ (
2145 uint32_t purpose,
2146 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
2147 const struct GNUNET_CRYPTO_Edx25519Signature *sig,
2148 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub);
2149
2150
2151/**
2152 * @ingroup crypto
2153 * @brief Verify Edx25519 signature.
2154 *
2155 * The @a ps data must be a fixed-size struct for which the signature is to be
2156 * created. The `size` field in @a ps->purpose must correctly indicate the
2157 * number of bytes of the data structure, including its header.
2158 *
2159 * @param purp purpose of the signature, must match 'ps->purpose.purpose'
2160 * (except in host byte order)
2161 * @param priv private key to use for the signing
2162 * @param ps packed struct with what to sign, MUST begin with a purpose
2163 * @param sig where to write the signature
2164 */
2165#define GNUNET_CRYPTO_edx25519_verify(purp,ps,sig,pub) ({ \
2166 /* check size is set correctly */ \
2167 GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*(ps))); \
2168 /* check 'ps' begins with the purpose */ \
2169 GNUNET_static_assert (((void*) (ps)) == \
2170 ((void*) &(ps)->purpose)); \
2171 GNUNET_CRYPTO_edx25519_verify_ (purp, \
2172 &(ps)->purpose, \
2173 sig, \
2174 pub); \
2175 })
2176
2177/**
2178 * @ingroup crypto
1985 * Derive a private key from a given private key and a label. 2179 * Derive a private key from a given private key and a label.
1986 * Essentially calculates a private key 'h = H(l,P) * d mod n' 2180 * Essentially calculates a private key 'h = H(l,P) * d mod n'
1987 * where n is the size of the ECC group and P is the public 2181 * where n is the size of the ECC group and P is the public
@@ -2115,6 +2309,43 @@ GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (
2115 const struct GNUNET_CRYPTO_EddsaPrivateScalar *s, 2309 const struct GNUNET_CRYPTO_EddsaPrivateScalar *s,
2116 struct GNUNET_CRYPTO_EddsaPublicKey *pkey); 2310 struct GNUNET_CRYPTO_EddsaPublicKey *pkey);
2117 2311
2312/**
2313 * @ingroup crypto
2314 * Derive a private scalar from a given private key and a label.
2315 * Essentially calculates a private key 'h = H(l,P) * d mod n'
2316 * where n is the size of the ECC group and P is the public
2317 * key associated with the private key 'd'.
2318 *
2319 * @param priv original private key
2320 * @param seed input seed
2321 * @param seedsize size of the seed
2322 * @param result derived private key
2323 */
2324void
2325GNUNET_CRYPTO_edx25519_private_key_derive (
2326 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
2327 const void *seed,
2328 size_t seedsize,
2329 struct GNUNET_CRYPTO_Edx25519PrivateKey *result);
2330
2331
2332/**
2333 * @ingroup crypto
2334 * Derive a public key from a given public key and a label.
2335 * Essentially calculates a public key 'V = H(l,P) * P'.
2336 *
2337 * @param pub original public key
2338 * @param seed input seed
2339 * @param seedsize size of the seed
2340 * @param result where to write the derived public key
2341 */
2342void
2343GNUNET_CRYPTO_edx25519_public_key_derive (
2344 const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
2345 const void *seed,
2346 size_t seedsize,
2347 struct GNUNET_CRYPTO_Edx25519PublicKey *result);
2348
2118 2349
2119/** 2350/**
2120 * Output the given MPI value to the given buffer in network 2351 * Output the given MPI value to the given buffer in network