aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_cs.c')
-rw-r--r--src/util/crypto_cs.c344
1 files changed, 0 insertions, 344 deletions
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
deleted file mode 100644
index 8506c7fa6..000000000
--- a/src/util/crypto_cs.c
+++ /dev/null
@@ -1,344 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014,2016,2019 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/crypto_cs.c
23 * @brief Clause Blind Schnorr signatures using Curve25519
24 * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
25 * @author Gian Demarmels <gian@demarmels.org>
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <sodium.h>
31#include <gcrypt.h>
32
33/**
34 * IMPLEMENTATION NOTICE:
35 *
36 * This is an implementation of the Clause Blind Schnorr Signature Scheme using Curve25519.
37 * Further details about the Clause Blind Schnorr Signature Scheme can be found here:
38 * https://eprint.iacr.org/2019/877.pdf
39 *
40 * We use libsodium wherever possible.
41 */
42
43
44void
45GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
46{
47 crypto_core_ed25519_scalar_random (priv->scalar.d);
48}
49
50
51void
52GNUNET_CRYPTO_cs_private_key_get_public (
53 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
54 struct GNUNET_CRYPTO_CsPublicKey *pub)
55{
56 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
57 priv->scalar.d));
58}
59
60
61/**
62 * Maps 32 random bytes to a scalar. This is necessary because libsodium
63 * expects scalar to be in the prime order subgroup.
64 *
65 * @param[in,out] scalar containing 32 byte char array, is modified to be in prime order subgroup
66 */
67static void
68map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
69{
70 /* perform clamping as described in RFC7748 */
71 scalar->d[0] &= 248;
72 scalar->d[31] &= 127;
73 scalar->d[31] |= 64;
74}
75
76
77void
78GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
79 const char *seed,
80 const struct GNUNET_CRYPTO_CsPrivateKey *lts,
81 struct GNUNET_CRYPTO_CsRSecret r[2])
82{
83 GNUNET_assert (
84 GNUNET_YES ==
85 GNUNET_CRYPTO_kdf (
86 r, sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
87 seed, strlen (seed),
88 lts, sizeof (*lts),
89 nonce, sizeof (*nonce),
90 NULL, 0));
91 map_to_scalar_subgroup (&r[0].scalar);
92 map_to_scalar_subgroup (&r[1].scalar);
93}
94
95
96void
97GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
98 struct GNUNET_CRYPTO_CsRPublic *r_pub)
99{
100 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
101 r_priv->scalar.d));
102}
103
104
105void
106GNUNET_CRYPTO_cs_blinding_secrets_derive (
107 const struct GNUNET_CRYPTO_CsNonce *blind_seed,
108 struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
109{
110 GNUNET_assert (
111 GNUNET_YES ==
112 GNUNET_CRYPTO_hkdf (bs,
113 sizeof (struct GNUNET_CRYPTO_CsBlindingSecret) * 2,
114 GCRY_MD_SHA512,
115 GCRY_MD_SHA256,
116 "alphabeta",
117 strlen ("alphabeta"),
118 blind_seed,
119 sizeof(*blind_seed),
120 NULL,
121 0));
122 map_to_scalar_subgroup (&bs[0].alpha);
123 map_to_scalar_subgroup (&bs[0].beta);
124 map_to_scalar_subgroup (&bs[1].alpha);
125 map_to_scalar_subgroup (&bs[1].beta);
126}
127
128
129/*
130order of subgroup required for scalars by libsodium
1312^252 + 27742317777372353535851937790883648493
132copied from https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
133and converted to big endian
134*/
135static const unsigned char L_BIG_ENDIAN[32] = {
136 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
138 0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
139};
140
141
142/**
143 * Computes a Hash of (R', m) mapped to a Curve25519 scalar
144 *
145 * @param hash initial hash of the message to be signed
146 * @param pub denomination public key (used as salt)
147 * @param[out] c C containing scalar
148 */
149static void
150cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
151 const void *msg,
152 size_t msg_len,
153 const struct GNUNET_CRYPTO_CsPublicKey *pub,
154 struct GNUNET_CRYPTO_CsC *c)
155{
156 // SHA-512 hash of R' and message
157 size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
158 char r_m_concat[r_m_concat_len];
159 memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
160 memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
161 struct GNUNET_HashCode prehash;
162
163 GNUNET_CRYPTO_hash (r_m_concat,
164 r_m_concat_len,
165 &prehash);
166
167 // modulus converted to MPI representation
168 gcry_mpi_t l_mpi;
169 GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi,
170 L_BIG_ENDIAN,
171 sizeof(L_BIG_ENDIAN));
172
173 // calculate full domain hash
174 gcry_mpi_t c_mpi;
175 GNUNET_CRYPTO_kdf_mod_mpi (&c_mpi,
176 l_mpi,
177 pub,
178 sizeof(struct GNUNET_CRYPTO_CsPublicKey),
179 &prehash,
180 sizeof(struct GNUNET_HashCode),
181 "Curve25519FDH");
182 gcry_mpi_release (l_mpi);
183
184 // convert c from mpi
185 unsigned char c_big_endian[256 / 8];
186 GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian,
187 sizeof(c_big_endian),
188 c_mpi);
189 gcry_mpi_release (c_mpi);
190 for (size_t i = 0; i<32; i++)
191 c->scalar.d[i] = c_big_endian[31 - i];
192}
193
194
195/**
196 * calculate R'
197 *
198 * @param bs blinding secret
199 * @param r_pub R
200 * @param pub public key
201 * @param[out] blinded_r_pub R'
202 */
203static void
204calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
205 const struct GNUNET_CRYPTO_CsRPublic *r_pub,
206 const struct GNUNET_CRYPTO_CsPublicKey *pub,
207 struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
208{
209 // R'i = Ri + alpha i*G + beta i*pub
210 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
211 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
212 alpha_mul_base.y,
213 bs->alpha.d));
214 struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
215 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (beta_mul_pub.y,
216 bs->beta.d,
217 pub->point.y));
218 struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
219 GNUNET_assert (0 == crypto_core_ed25519_add (
220 alpha_mul_base_plus_beta_mul_pub.y,
221 alpha_mul_base.y,
222 beta_mul_pub.y));
223 GNUNET_assert (0 == crypto_core_ed25519_add (blinded_r_pub->point.y,
224 r_pub->point.y,
225 alpha_mul_base_plus_beta_mul_pub.
226 y));
227}
228
229
230void
231GNUNET_CRYPTO_cs_calc_blinded_c (
232 const struct GNUNET_CRYPTO_CsBlindingSecret bs[2],
233 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
234 const struct GNUNET_CRYPTO_CsPublicKey *pub,
235 const void *msg,
236 size_t msg_len,
237 struct GNUNET_CRYPTO_CsC blinded_c[2],
238 struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
239{
240 // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
241 calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
242 calc_r_dash (&bs[1], &r_pub[1], pub, &blinded_r_pub[1]);
243
244 // for i 0/1: c'i = H(R'i, msg)
245 struct GNUNET_CRYPTO_CsC c_dash_0;
246 struct GNUNET_CRYPTO_CsC c_dash_1;
247 cs_full_domain_hash (&blinded_r_pub[0], msg, msg_len, pub, &c_dash_0);
248 cs_full_domain_hash (&blinded_r_pub[1], msg, msg_len, pub, &c_dash_1);
249
250 // for i 0/1: ci = c'i + beta i mod p
251 crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
252 c_dash_0.scalar.d,
253 bs[0].beta.d);
254 crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
255 c_dash_1.scalar.d,
256 bs[1].beta.d);
257}
258
259
260unsigned int
261GNUNET_CRYPTO_cs_sign_derive (
262 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
263 const struct GNUNET_CRYPTO_CsRSecret r[2],
264 const struct GNUNET_CRYPTO_CsC c[2],
265 const struct GNUNET_CRYPTO_CsNonce *nonce,
266 struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar)
267{
268 uint32_t hkdf_out;
269
270 // derive clause session identifier b (random bit)
271 GNUNET_assert (GNUNET_YES ==
272 GNUNET_CRYPTO_hkdf (&hkdf_out,
273 sizeof (hkdf_out),
274 GCRY_MD_SHA512,
275 GCRY_MD_SHA256,
276 "b",
277 strlen ("b"),
278 priv,
279 sizeof (*priv),
280 nonce,
281 sizeof (*nonce),
282 NULL,
283 0));
284 unsigned int b = hkdf_out % 2;
285
286 // s = r_b + c_b priv
287 struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
288 crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
289 c[b].scalar.d,
290 priv->scalar.d);
291 crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
292 r[b].scalar.d,
293 c_b_mul_priv.d);
294
295 return b;
296}
297
298
299void
300GNUNET_CRYPTO_cs_unblind (
301 const struct GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
302 const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
303 struct GNUNET_CRYPTO_CsS *signature_scalar)
304{
305 crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
306 blinded_signature_scalar->scalar.d,
307 bs->alpha.d);
308}
309
310
311enum GNUNET_GenericReturnValue
312GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
313 const struct GNUNET_CRYPTO_CsPublicKey *pub,
314 const void *msg,
315 size_t msg_len)
316{
317 // calculate c' = H(R, m)
318 struct GNUNET_CRYPTO_CsC c_dash;
319
320 cs_full_domain_hash (&sig->r_point,
321 msg,
322 msg_len,
323 pub,
324 &c_dash);
325
326 // s'G ?= R' + c' pub
327 struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
328 GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
329 sig_scal_mul_base.y,
330 sig->s_scalar.scalar.d));
331 struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
332 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
333 c_dash.scalar.d,
334 pub->point.y));
335 struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
336 GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
337 sig->r_point.point.y,
338 c_dash_mul_pub.y));
339
340 return 0 == GNUNET_memcmp (&sig_scal_mul_base,
341 &R_add_c_dash_mul_pub)
342 ? GNUNET_OK
343 : GNUNET_SYSERR;
344}