tweetnacl 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # TweetNaCl for Ruby
2
+
3
+ # SUMMARY
4
+
5
+ TweetNaCl is a C-extension for Ruby built on top of the official TweetNacl
6
+ distribution. It exposes the basic functions using Ruby objects.
7
+
8
+ For a detailed explanation of TweetNaCl, [here's the research paper associated with it][paper]
9
+
10
+ # INSTALL
11
+
12
+ gem install tweetnacl
13
+
14
+ ## USAGE
15
+
16
+ input = "<text to cipher>"
17
+ nonce = "<a 24-char string>"
18
+
19
+ pk, sk = @t.crypto_box_keypair # This generates a pair of public and secret keys
20
+
21
+ cipher = @t.crypto_box(input, nonce, pk, sk) # Encrypt !
22
+
23
+ output = @t.crypto_box_open(cipher, nonce, pk, sk) # Decrypt!
24
+
25
+ assert_equal input, output # They're the same !
26
+
27
+ ## FUNCTIONS
28
+
29
+ ### crypto_box_keypair
30
+
31
+ Generate a pair of public and secret keys.
32
+
33
+ ### crypto_box(input, nonce, public_key, secret_key)
34
+
35
+ Encrypt and sign the input given the other parameters.
36
+
37
+ ### crypto_box_keypair(ciphered_message, nonce, public_key, secret_key)
38
+
39
+ Decrypt and verify the signature of the ciphered message given the other parameters.
40
+
41
+ ## TODO
42
+
43
+ * [x] crypto_box_keypair
44
+ * [x] crypto_box
45
+ * [x] crypto_box_open
46
+ * [ ] All the other functions !
47
+ * [ ] Use high-level objects
48
+
49
+ ## Is it PRODUCTION-READY?
50
+
51
+ No. And it never will.
52
+
53
+ ## Is it secure?
54
+
55
+ No. Until proven otherwise.
56
+
57
+ ## CONTRIBUTE
58
+
59
+ 1. Fork it ( https://github.com/franckverrot/tweetnacl/fork )
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create new Pull Request
64
+
65
+ ## LICENSE
66
+
67
+ Franck Verrot, Copyright 2014. See LICENSE.txt.
68
+
69
+
70
+ [paper] : http://tweetnacl.cr.yp.to/tweetnacl-20131229.pdf
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'rake/extensiontask'
2
+ spec = Gem::Specification.load('tweetnacl.gemspec')
3
+ Rake::ExtensionTask.new('tweetnacl', spec) do |ext|
4
+ ext.source_pattern = "*.{c,h}"
5
+ end
6
+
7
+ require 'rake/testtask'
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.pattern = "test/*_test.rb"
11
+ t.verbose = true
12
+ t.warning = true
13
+ end
14
+
15
+ task :default => :full
16
+
17
+ desc "Run the full spec suite"
18
+ task :full => ["clean", "compile", "test"]
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'tweetnacl'
@@ -0,0 +1,23 @@
1
+ #include "randombytes.h"
2
+
3
+ void randombytes(unsigned char * ptr,unsigned int length)
4
+ {
5
+ char failed = 0;
6
+ FILE* fh = fopen("/dev/urandom", "rb");
7
+ if (fh != NULL) {
8
+ if (fread(ptr, length, 1, fh) == 0) {
9
+ failed = 1;
10
+ }
11
+ fclose(fh);
12
+ } else {
13
+ failed = 1;
14
+ }
15
+ /*
16
+ * yes, this is horrible error handling but we don't have better
17
+ * options from here and I don't want to start changing the design
18
+ * of the library
19
+ */
20
+ if (failed) {
21
+ exit(1);
22
+ }
23
+ }
@@ -0,0 +1,4 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+
4
+ void randombytes(unsigned char * ptr,unsigned int length);
@@ -0,0 +1,92 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include "tweetnacl.h"
4
+ #define PADDING_LEN 32
5
+
6
+ typedef struct {
7
+ } TweetNaCl;
8
+
9
+ static void tweetnacl_free() {
10
+ }
11
+
12
+ static VALUE tweetnacl_alloc(VALUE klass) {
13
+ return Data_Wrap_Struct(klass, NULL, tweetnacl_free, ruby_xmalloc(sizeof(TweetNaCl)));
14
+ }
15
+
16
+ static VALUE tweetnacl_init(VALUE self) {
17
+ return Qnil;
18
+ }
19
+
20
+ void hexdump(char * data, int len)
21
+ {
22
+ int i;
23
+ for (i = 0; i < len; i++) {
24
+ printf("%02X", (unsigned char)data[i]);
25
+ }
26
+ printf("\n");
27
+ }
28
+
29
+ VALUE m_crypto_box_keypair(VALUE self) {
30
+ VALUE ary = rb_ary_new2(2);
31
+ char *pk = calloc(crypto_box_PUBLICKEYBYTES, sizeof(unsigned char));
32
+ char *sk = calloc(crypto_box_SECRETKEYBYTES, sizeof(unsigned char));
33
+ int res = crypto_box_keypair(pk, sk);
34
+ pk[crypto_box_PUBLICKEYBYTES] = 0;
35
+ sk[crypto_box_SECRETKEYBYTES] = 0;
36
+ rb_ary_store(ary, 0, rb_str_new(pk, crypto_box_PUBLICKEYBYTES));
37
+ rb_ary_store(ary, 1, rb_str_new(sk, crypto_box_SECRETKEYBYTES));
38
+ return ary;
39
+ }
40
+
41
+ VALUE m_crypto_box(VALUE self, VALUE _m, VALUE _n, VALUE _pk, VALUE _sk) {
42
+ if(_m == Qnil) { rb_raise(rb_eArgError, "A message should have been given"); }
43
+ if(_pk == Qnil) { rb_raise(rb_eArgError, "Public key should have been given"); }
44
+ if(_sk == Qnil) { rb_raise(rb_eArgError, "Secret key should have been given"); }
45
+ if (RSTRING_LEN(_n) != 24) { rb_raise(rb_eArgError, "nonce should be 24-byte long"); }
46
+ if (RSTRING_LEN(_pk) != 32) { rb_raise(rb_eArgError, "public key should be 24-byte long"); }
47
+ if (RSTRING_LEN(_sk) != 32) { rb_raise(rb_eArgError, "secret key should be 24-byte long"); }
48
+
49
+ char * message = RSTRING_PTR(_m);
50
+ char * nonce = RSTRING_PTR(_n);
51
+ char * pk = RSTRING_PTR(_pk);
52
+ char * sk = RSTRING_PTR(_sk);
53
+ int len = strlen(message);
54
+ char * padded_message = (char*)calloc(sizeof(char), len + PADDING_LEN);
55
+ memcpy(padded_message + PADDING_LEN, message, strlen(message));
56
+ char * c = malloc(strlen(message) + PADDING_LEN);
57
+ int res = crypto_box(c, padded_message, len + PADDING_LEN, nonce, pk, sk);
58
+ if (0 != res) { fprintf(stderr, "Something went wrong\n"); exit(res); }
59
+ VALUE ret = rb_str_new(c, len + PADDING_LEN);
60
+ return ret;
61
+ }
62
+
63
+ VALUE m_crypto_box_open(VALUE self, VALUE _c, VALUE _n, VALUE _pk, VALUE _sk) {
64
+ if(_c == Qnil) { rb_raise(rb_eArgError, "A cipher should have been given"); }
65
+ if(_pk == Qnil) { rb_raise(rb_eArgError, "Public key should have been given"); }
66
+ if(_sk == Qnil) { rb_raise(rb_eArgError, "Secret key should have been given"); }
67
+ if (RSTRING_LEN(_n) != 24) { rb_raise(rb_eArgError, "nonce should be 24-byte long"); }
68
+ if (RSTRING_LEN(_pk) != 32) { rb_raise(rb_eArgError, "public key should be 24-byte long"); }
69
+ if (RSTRING_LEN(_sk) != 32) { rb_raise(rb_eArgError, "secret key should be 24-byte long"); }
70
+
71
+ unsigned char * c = RSTRING_PTR(_c);
72
+ char * nonce = RSTRING_PTR(_n);
73
+ char * pk = RSTRING_PTR(_pk);
74
+ char * sk = RSTRING_PTR(_sk);
75
+ int padded_mlen = rb_str_strlen(_c);
76
+ char * message = calloc(padded_mlen, sizeof(char));
77
+
78
+ int res = crypto_box_open(message, c, padded_mlen, nonce, pk, sk);
79
+ if (0 != res) { rb_raise(rb_eRuntimeError, "la putain"); }
80
+
81
+ return rb_str_new2(message + PADDING_LEN);
82
+ }
83
+
84
+ void Init_tweetnacl() {
85
+ VALUE c = rb_define_class("TweetNaCl", rb_cObject);
86
+
87
+ rb_define_alloc_func(c, tweetnacl_alloc);
88
+ rb_define_private_method(c, "initialize", RUBY_METHOD_FUNC(tweetnacl_init), 0);
89
+ rb_define_method(c, "crypto_box_keypair", RUBY_METHOD_FUNC(m_crypto_box_keypair), 0);
90
+ rb_define_method(c, "crypto_box", RUBY_METHOD_FUNC(m_crypto_box), 4);
91
+ rb_define_method(c, "crypto_box_open", RUBY_METHOD_FUNC(m_crypto_box_open), 4);
92
+ }
@@ -0,0 +1,811 @@
1
+ #include "tweetnacl.h"
2
+ #define FOR(i,n) for (i = 0;i < n;++i)
3
+ #define sv static void
4
+
5
+ typedef unsigned char u8;
6
+ typedef unsigned long u32;
7
+ typedef unsigned long long u64;
8
+ typedef long long i64;
9
+ typedef i64 gf[16];
10
+ extern void randombytes(u8 *,u64);
11
+
12
+ static const u8
13
+ _0[16],
14
+ _9[32] = {9};
15
+ static const gf
16
+ gf0,
17
+ gf1 = {1},
18
+ _121665 = {0xDB41,1},
19
+ D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
20
+ D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
21
+ X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
22
+ Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
23
+ I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
24
+
25
+ static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
26
+
27
+ static u32 ld32(const u8 *x)
28
+ {
29
+ u32 u = x[3];
30
+ u = (u<<8)|x[2];
31
+ u = (u<<8)|x[1];
32
+ return (u<<8)|x[0];
33
+ }
34
+
35
+ static u64 dl64(const u8 *x)
36
+ {
37
+ u64 i,u=0;
38
+ FOR(i,8) u=(u<<8)|x[i];
39
+ return u;
40
+ }
41
+
42
+ sv st32(u8 *x,u32 u)
43
+ {
44
+ int i;
45
+ FOR(i,4) { x[i] = u; u >>= 8; }
46
+ }
47
+
48
+ sv ts64(u8 *x,u64 u)
49
+ {
50
+ int i;
51
+ for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
52
+ }
53
+
54
+ static int vn(const u8 *x,const u8 *y,int n)
55
+ {
56
+ u32 i,d = 0;
57
+ FOR(i,n) d |= x[i]^y[i];
58
+ return (1 & ((d - 1) >> 8)) - 1;
59
+ }
60
+
61
+ int crypto_verify_16(const u8 *x,const u8 *y)
62
+ {
63
+ return vn(x,y,16);
64
+ }
65
+
66
+ int crypto_verify_32(const u8 *x,const u8 *y)
67
+ {
68
+ return vn(x,y,32);
69
+ }
70
+
71
+ sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h)
72
+ {
73
+ u32 w[16],x[16],y[16],t[4];
74
+ int i,j,m;
75
+
76
+ FOR(i,4) {
77
+ x[5*i] = ld32(c+4*i);
78
+ x[1+i] = ld32(k+4*i);
79
+ x[6+i] = ld32(in+4*i);
80
+ x[11+i] = ld32(k+16+4*i);
81
+ }
82
+
83
+ FOR(i,16) y[i] = x[i];
84
+
85
+ FOR(i,20) {
86
+ FOR(j,4) {
87
+ FOR(m,4) t[m] = x[(5*j+4*m)%16];
88
+ t[1] ^= L32(t[0]+t[3], 7);
89
+ t[2] ^= L32(t[1]+t[0], 9);
90
+ t[3] ^= L32(t[2]+t[1],13);
91
+ t[0] ^= L32(t[3]+t[2],18);
92
+ FOR(m,4) w[4*j+(j+m)%4] = t[m];
93
+ }
94
+ FOR(m,16) x[m] = w[m];
95
+ }
96
+
97
+ if (h) {
98
+ FOR(i,16) x[i] += y[i];
99
+ FOR(i,4) {
100
+ x[5*i] -= ld32(c+4*i);
101
+ x[6+i] -= ld32(in+4*i);
102
+ }
103
+ FOR(i,4) {
104
+ st32(out+4*i,x[5*i]);
105
+ st32(out+16+4*i,x[6+i]);
106
+ }
107
+ } else
108
+ FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
109
+ }
110
+
111
+ int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
112
+ {
113
+ core(out,in,k,c,0);
114
+ return 0;
115
+ }
116
+
117
+ int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
118
+ {
119
+ core(out,in,k,c,1);
120
+ return 0;
121
+ }
122
+
123
+ static const u8 sigma[16] = "expand 32-byte k";
124
+
125
+ int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k)
126
+ {
127
+ u8 z[16],x[64];
128
+ u32 u,i;
129
+ if (!b) return 0;
130
+ FOR(i,16) z[i] = 0;
131
+ FOR(i,8) z[i] = n[i];
132
+ while (b >= 64) {
133
+ crypto_core_salsa20(x,z,k,sigma);
134
+ FOR(i,64) c[i] = (m?m[i]:0) ^ x[i];
135
+ u = 1;
136
+ for (i = 8;i < 16;++i) {
137
+ u += (u32) z[i];
138
+ z[i] = u;
139
+ u >>= 8;
140
+ }
141
+ b -= 64;
142
+ c += 64;
143
+ if (m) m += 64;
144
+ }
145
+ if (b) {
146
+ crypto_core_salsa20(x,z,k,sigma);
147
+ FOR(i,b) c[i] = (m?m[i]:0) ^ x[i];
148
+ }
149
+ return 0;
150
+ }
151
+
152
+ int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k)
153
+ {
154
+ return crypto_stream_salsa20_xor(c,0,d,n,k);
155
+ }
156
+
157
+ int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k)
158
+ {
159
+ u8 s[32];
160
+ crypto_core_hsalsa20(s,n,k,sigma);
161
+ return crypto_stream_salsa20(c,d,n+16,s);
162
+ }
163
+
164
+ int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
165
+ {
166
+ u8 s[32];
167
+ crypto_core_hsalsa20(s,n,k,sigma);
168
+ return crypto_stream_salsa20_xor(c,m,d,n+16,s);
169
+ }
170
+
171
+ sv add1305(u32 *h,const u32 *c)
172
+ {
173
+ u32 j,u = 0;
174
+ FOR(j,17) {
175
+ u += h[j] + c[j];
176
+ h[j] = u & 255;
177
+ u >>= 8;
178
+ }
179
+ }
180
+
181
+ static const u32 minusp[17] = {
182
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
183
+ } ;
184
+
185
+ int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k)
186
+ {
187
+ u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17];
188
+
189
+ FOR(j,17) r[j]=h[j]=0;
190
+ FOR(j,16) r[j]=k[j];
191
+ r[3]&=15;
192
+ r[4]&=252;
193
+ r[7]&=15;
194
+ r[8]&=252;
195
+ r[11]&=15;
196
+ r[12]&=252;
197
+ r[15]&=15;
198
+
199
+ while (n > 0) {
200
+ FOR(j,17) c[j] = 0;
201
+ for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j];
202
+ c[j] = 1;
203
+ m += j; n -= j;
204
+ add1305(h,c);
205
+ FOR(i,17) {
206
+ x[i] = 0;
207
+ FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]);
208
+ }
209
+ FOR(i,17) h[i] = x[i];
210
+ u = 0;
211
+ FOR(j,16) {
212
+ u += h[j];
213
+ h[j] = u & 255;
214
+ u >>= 8;
215
+ }
216
+ u += h[16]; h[16] = u & 3;
217
+ u = 5 * (u >> 2);
218
+ FOR(j,16) {
219
+ u += h[j];
220
+ h[j] = u & 255;
221
+ u >>= 8;
222
+ }
223
+ u += h[16]; h[16] = u;
224
+ }
225
+
226
+ FOR(j,17) g[j] = h[j];
227
+ add1305(h,minusp);
228
+ s = -(h[16] >> 7);
229
+ FOR(j,17) h[j] ^= s & (g[j] ^ h[j]);
230
+
231
+ FOR(j,16) c[j] = k[j + 16];
232
+ c[16] = 0;
233
+ add1305(h,c);
234
+ FOR(j,16) out[j] = h[j];
235
+ return 0;
236
+ }
237
+
238
+ #include <stdio.h>
239
+ extern void hexdump(char*,int);
240
+ int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k)
241
+ {
242
+ u8 x[16];
243
+ crypto_onetimeauth(x,m,n,k);
244
+ return crypto_verify_16(h,x);
245
+ }
246
+
247
+ int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
248
+ {
249
+ int i;
250
+ if (d < 32) return -1;
251
+ crypto_stream_xor(c,m,d,n,k);
252
+ crypto_onetimeauth(c + 16,c + 32,d - 32,c);
253
+ FOR(i,16) c[i] = 0;
254
+ return 0;
255
+ }
256
+
257
+ int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
258
+ {
259
+ int i;
260
+ u8 x[32];
261
+ if (d < 32) return -1;
262
+ crypto_stream(x,32,n,k);
263
+ if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1;
264
+ crypto_stream_xor(m,c,d,n,k);
265
+ FOR(i,32) m[i] = 0;
266
+ return 0;
267
+ }
268
+
269
+ sv set25519(gf r, const gf a)
270
+ {
271
+ int i;
272
+ FOR(i,16) r[i]=a[i];
273
+ }
274
+
275
+ sv car25519(gf o)
276
+ {
277
+ int i;
278
+ i64 c;
279
+ FOR(i,16) {
280
+ o[i]+=(1LL<<16);
281
+ c=o[i]>>16;
282
+ o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
283
+ o[i]-=c<<16;
284
+ }
285
+ }
286
+
287
+ sv sel25519(gf p,gf q,int b)
288
+ {
289
+ i64 t,i,c=~(b-1);
290
+ FOR(i,16) {
291
+ t= c&(p[i]^q[i]);
292
+ p[i]^=t;
293
+ q[i]^=t;
294
+ }
295
+ }
296
+
297
+ sv pack25519(u8 *o,const gf n)
298
+ {
299
+ int i,j,b;
300
+ gf m,t;
301
+ FOR(i,16) t[i]=n[i];
302
+ car25519(t);
303
+ car25519(t);
304
+ car25519(t);
305
+ FOR(j,2) {
306
+ m[0]=t[0]-0xffed;
307
+ for(i=1;i<15;i++) {
308
+ m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
309
+ m[i-1]&=0xffff;
310
+ }
311
+ m[15]=t[15]-0x7fff-((m[14]>>16)&1);
312
+ b=(m[15]>>16)&1;
313
+ m[14]&=0xffff;
314
+ sel25519(t,m,1-b);
315
+ }
316
+ FOR(i,16) {
317
+ o[2*i]=t[i]&0xff;
318
+ o[2*i+1]=t[i]>>8;
319
+ }
320
+ }
321
+
322
+ static int neq25519(const gf a, const gf b)
323
+ {
324
+ u8 c[32],d[32];
325
+ pack25519(c,a);
326
+ pack25519(d,b);
327
+ return crypto_verify_32(c,d);
328
+ }
329
+
330
+ static u8 par25519(const gf a)
331
+ {
332
+ u8 d[32];
333
+ pack25519(d,a);
334
+ return d[0]&1;
335
+ }
336
+
337
+ sv unpack25519(gf o, const u8 *n)
338
+ {
339
+ int i;
340
+ FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
341
+ o[15]&=0x7fff;
342
+ }
343
+
344
+ sv A(gf o,const gf a,const gf b)
345
+ {
346
+ int i;
347
+ FOR(i,16) o[i]=a[i]+b[i];
348
+ }
349
+
350
+ sv Z(gf o,const gf a,const gf b)
351
+ {
352
+ int i;
353
+ FOR(i,16) o[i]=a[i]-b[i];
354
+ }
355
+
356
+ sv M(gf o,const gf a,const gf b)
357
+ {
358
+ i64 i,j,t[31];
359
+ FOR(i,31) t[i]=0;
360
+ FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
361
+ FOR(i,15) t[i]+=38*t[i+16];
362
+ FOR(i,16) o[i]=t[i];
363
+ car25519(o);
364
+ car25519(o);
365
+ }
366
+
367
+ sv S(gf o,const gf a)
368
+ {
369
+ M(o,a,a);
370
+ }
371
+
372
+ sv inv25519(gf o,const gf i)
373
+ {
374
+ gf c;
375
+ int a;
376
+ FOR(a,16) c[a]=i[a];
377
+ for(a=253;a>=0;a--) {
378
+ S(c,c);
379
+ if(a!=2&&a!=4) M(c,c,i);
380
+ }
381
+ FOR(a,16) o[a]=c[a];
382
+ }
383
+
384
+ sv pow2523(gf o,const gf i)
385
+ {
386
+ gf c;
387
+ int a;
388
+ FOR(a,16) c[a]=i[a];
389
+ for(a=250;a>=0;a--) {
390
+ S(c,c);
391
+ if(a!=1) M(c,c,i);
392
+ }
393
+ FOR(a,16) o[a]=c[a];
394
+ }
395
+
396
+ int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
397
+ {
398
+ u8 z[32];
399
+ i64 x[80],r,i;
400
+ gf a,b,c,d,e,f;
401
+ FOR(i,31) z[i]=n[i];
402
+ z[31]=(n[31]&127)|64;
403
+ z[0]&=248;
404
+ unpack25519(x,p);
405
+ FOR(i,16) {
406
+ b[i]=x[i];
407
+ d[i]=a[i]=c[i]=0;
408
+ }
409
+ a[0]=d[0]=1;
410
+ for(i=254;i>=0;--i) {
411
+ r=(z[i>>3]>>(i&7))&1;
412
+ sel25519(a,b,r);
413
+ sel25519(c,d,r);
414
+ A(e,a,c);
415
+ Z(a,a,c);
416
+ A(c,b,d);
417
+ Z(b,b,d);
418
+ S(d,e);
419
+ S(f,a);
420
+ M(a,c,a);
421
+ M(c,b,e);
422
+ A(e,a,c);
423
+ Z(a,a,c);
424
+ S(b,a);
425
+ Z(c,d,f);
426
+ M(a,c,_121665);
427
+ A(a,a,d);
428
+ M(c,c,a);
429
+ M(a,d,f);
430
+ M(d,b,x);
431
+ S(b,e);
432
+ sel25519(a,b,r);
433
+ sel25519(c,d,r);
434
+ }
435
+ FOR(i,16) {
436
+ x[i+16]=a[i];
437
+ x[i+32]=c[i];
438
+ x[i+48]=b[i];
439
+ x[i+64]=d[i];
440
+ }
441
+ inv25519(x+32,x+32);
442
+ M(x+16,x+16,x+32);
443
+ pack25519(q,x+16);
444
+ return 0;
445
+ }
446
+
447
+ int crypto_scalarmult_base(u8 *q,const u8 *n)
448
+ {
449
+ return crypto_scalarmult(q,n,_9);
450
+ }
451
+
452
+ int crypto_box_keypair(u8 *y,u8 *x)
453
+ {
454
+ randombytes(x,32);
455
+ return crypto_scalarmult_base(y,x);
456
+ }
457
+
458
+ int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x)
459
+ {
460
+ u8 s[32];
461
+ crypto_scalarmult(s,x,y);
462
+ return crypto_core_hsalsa20(k,_0,s,sigma);
463
+ }
464
+
465
+ int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
466
+ {
467
+ return crypto_secretbox(c,m,d,n,k);
468
+ }
469
+
470
+ int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
471
+ {
472
+ return crypto_secretbox_open(m,c,d,n,k);
473
+ }
474
+
475
+ int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x)
476
+ {
477
+ u8 k[32];
478
+ crypto_box_beforenm(k,y,x);
479
+ return crypto_box_afternm(c,m,d,n,k);
480
+ }
481
+
482
+ int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x)
483
+ {
484
+ u8 k[32];
485
+ crypto_box_beforenm(k,y,x);
486
+ return crypto_box_open_afternm(m,c,d,n,k);
487
+ }
488
+
489
+ static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); }
490
+ static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); }
491
+ static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
492
+ static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); }
493
+ static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); }
494
+ static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
495
+ static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); }
496
+
497
+ static const u64 K[80] =
498
+ {
499
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
500
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
501
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
502
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
503
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
504
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
505
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
506
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
507
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
508
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
509
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
510
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
511
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
512
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
513
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
514
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
515
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
516
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
517
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
518
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
519
+ };
520
+
521
+ int crypto_hashblocks(u8 *x,const u8 *m,u64 n)
522
+ {
523
+ u64 z[8],b[8],a[8],w[16],t;
524
+ int i,j;
525
+
526
+ FOR(i,8) z[i] = a[i] = dl64(x + 8 * i);
527
+
528
+ while (n >= 128) {
529
+ FOR(i,16) w[i] = dl64(m + 8 * i);
530
+
531
+ FOR(i,80) {
532
+ FOR(j,8) b[j] = a[j];
533
+ t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16];
534
+ b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]);
535
+ b[3] += t;
536
+ FOR(j,8) a[(j+1)%8] = b[j];
537
+ if (i%16 == 15)
538
+ FOR(j,16)
539
+ w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]);
540
+ }
541
+
542
+ FOR(i,8) { a[i] += z[i]; z[i] = a[i]; }
543
+
544
+ m += 128;
545
+ n -= 128;
546
+ }
547
+
548
+ FOR(i,8) ts64(x+8*i,z[i]);
549
+
550
+ return n;
551
+ }
552
+
553
+ static const u8 iv[64] = {
554
+ 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
555
+ 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
556
+ 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
557
+ 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
558
+ 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
559
+ 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
560
+ 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
561
+ 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
562
+ } ;
563
+
564
+ int crypto_hash(u8 *out,const u8 *m,u64 n)
565
+ {
566
+ u8 h[64],x[256];
567
+ u64 i,b = n;
568
+
569
+ FOR(i,64) h[i] = iv[i];
570
+
571
+ crypto_hashblocks(h,m,n);
572
+ m += n;
573
+ n &= 127;
574
+ m -= n;
575
+
576
+ FOR(i,256) x[i] = 0;
577
+ FOR(i,n) x[i] = m[i];
578
+ x[n] = 128;
579
+
580
+ n = 256-128*(n<112);
581
+ x[n-9] = b >> 61;
582
+ ts64(x+n-8,b<<3);
583
+ crypto_hashblocks(h,x,n);
584
+
585
+ FOR(i,64) out[i] = h[i];
586
+
587
+ return 0;
588
+ }
589
+
590
+ sv add(gf p[4],gf q[4])
591
+ {
592
+ gf a,b,c,d,t,e,f,g,h;
593
+
594
+ Z(a, p[1], p[0]);
595
+ Z(t, q[1], q[0]);
596
+ M(a, a, t);
597
+ A(b, p[0], p[1]);
598
+ A(t, q[0], q[1]);
599
+ M(b, b, t);
600
+ M(c, p[3], q[3]);
601
+ M(c, c, D2);
602
+ M(d, p[2], q[2]);
603
+ A(d, d, d);
604
+ Z(e, b, a);
605
+ Z(f, d, c);
606
+ A(g, d, c);
607
+ A(h, b, a);
608
+
609
+ M(p[0], e, f);
610
+ M(p[1], h, g);
611
+ M(p[2], g, f);
612
+ M(p[3], e, h);
613
+ }
614
+
615
+ sv cswap(gf p[4],gf q[4],u8 b)
616
+ {
617
+ int i;
618
+ FOR(i,4)
619
+ sel25519(p[i],q[i],b);
620
+ }
621
+
622
+ sv pack(u8 *r,gf p[4])
623
+ {
624
+ gf tx, ty, zi;
625
+ inv25519(zi, p[2]);
626
+ M(tx, p[0], zi);
627
+ M(ty, p[1], zi);
628
+ pack25519(r, ty);
629
+ r[31] ^= par25519(tx) << 7;
630
+ }
631
+
632
+ sv scalarmult(gf p[4],gf q[4],const u8 *s)
633
+ {
634
+ int i;
635
+ set25519(p[0],gf0);
636
+ set25519(p[1],gf1);
637
+ set25519(p[2],gf1);
638
+ set25519(p[3],gf0);
639
+ for (i = 255;i >= 0;--i) {
640
+ u8 b = (s[i/8]>>(i&7))&1;
641
+ cswap(p,q,b);
642
+ add(q,p);
643
+ add(p,p);
644
+ cswap(p,q,b);
645
+ }
646
+ }
647
+
648
+ sv scalarbase(gf p[4],const u8 *s)
649
+ {
650
+ gf q[4];
651
+ set25519(q[0],X);
652
+ set25519(q[1],Y);
653
+ set25519(q[2],gf1);
654
+ M(q[3],X,Y);
655
+ scalarmult(p,q,s);
656
+ }
657
+
658
+ int crypto_sign_keypair(u8 *pk, u8 *sk)
659
+ {
660
+ u8 d[64];
661
+ gf p[4];
662
+ int i;
663
+
664
+ randombytes(sk, 32);
665
+ crypto_hash(d, sk, 32);
666
+ d[0] &= 248;
667
+ d[31] &= 127;
668
+ d[31] |= 64;
669
+
670
+ scalarbase(p,d);
671
+ pack(pk,p);
672
+
673
+ FOR(i,32) sk[32 + i] = pk[i];
674
+ return 0;
675
+ }
676
+
677
+ static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
678
+
679
+ sv modL(u8 *r,i64 x[64])
680
+ {
681
+ i64 carry,i,j;
682
+ for (i = 63;i >= 32;--i) {
683
+ carry = 0;
684
+ for (j = i - 32;j < i - 12;++j) {
685
+ x[j] += carry - 16 * x[i] * L[j - (i - 32)];
686
+ carry = (x[j] + 128) >> 8;
687
+ x[j] -= carry << 8;
688
+ }
689
+ x[j] += carry;
690
+ x[i] = 0;
691
+ }
692
+ carry = 0;
693
+ FOR(j,32) {
694
+ x[j] += carry - (x[31] >> 4) * L[j];
695
+ carry = x[j] >> 8;
696
+ x[j] &= 255;
697
+ }
698
+ FOR(j,32) x[j] -= carry * L[j];
699
+ FOR(i,32) {
700
+ x[i+1] += x[i] >> 8;
701
+ r[i] = x[i] & 255;
702
+ }
703
+ }
704
+
705
+ sv reduce(u8 *r)
706
+ {
707
+ i64 x[64],i;
708
+ FOR(i,64) x[i] = (u64) r[i];
709
+ FOR(i,64) r[i] = 0;
710
+ modL(r,x);
711
+ }
712
+
713
+ int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk)
714
+ {
715
+ u8 d[64],h[64],r[64];
716
+ i64 i,j,x[64];
717
+ gf p[4];
718
+
719
+ crypto_hash(d, sk, 32);
720
+ d[0] &= 248;
721
+ d[31] &= 127;
722
+ d[31] |= 64;
723
+
724
+ *smlen = n+64;
725
+ FOR(i,n) sm[64 + i] = m[i];
726
+ FOR(i,32) sm[32 + i] = d[32 + i];
727
+
728
+ crypto_hash(r, sm+32, n+32);
729
+ reduce(r);
730
+ scalarbase(p,r);
731
+ pack(sm,p);
732
+
733
+ FOR(i,32) sm[i+32] = sk[i+32];
734
+ crypto_hash(h,sm,n + 64);
735
+ reduce(h);
736
+
737
+ FOR(i,64) x[i] = 0;
738
+ FOR(i,32) x[i] = (u64) r[i];
739
+ FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
740
+ modL(sm + 32,x);
741
+
742
+ return 0;
743
+ }
744
+
745
+ static int unpackneg(gf r[4],const u8 p[32])
746
+ {
747
+ gf t, chk, num, den, den2, den4, den6;
748
+ set25519(r[2],gf1);
749
+ unpack25519(r[1],p);
750
+ S(num,r[1]);
751
+ M(den,num,D);
752
+ Z(num,num,r[2]);
753
+ A(den,r[2],den);
754
+
755
+ S(den2,den);
756
+ S(den4,den2);
757
+ M(den6,den4,den2);
758
+ M(t,den6,num);
759
+ M(t,t,den);
760
+
761
+ pow2523(t,t);
762
+ M(t,t,num);
763
+ M(t,t,den);
764
+ M(t,t,den);
765
+ M(r[0],t,den);
766
+
767
+ S(chk,r[0]);
768
+ M(chk,chk,den);
769
+ if (neq25519(chk, num)) M(r[0],r[0],I);
770
+
771
+ S(chk,r[0]);
772
+ M(chk,chk,den);
773
+ if (neq25519(chk, num)) return -1;
774
+
775
+ if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
776
+
777
+ M(r[3],r[0],r[1]);
778
+ return 0;
779
+ }
780
+
781
+ int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk)
782
+ {
783
+ int i;
784
+ u8 t[32],h[64];
785
+ gf p[4],q[4];
786
+
787
+ *mlen = -1;
788
+ if (n < 64) return -1;
789
+
790
+ if (unpackneg(q,pk)) return -1;
791
+
792
+ FOR(i,n) m[i] = sm[i];
793
+ FOR(i,32) m[i+32] = pk[i];
794
+ crypto_hash(h,m,n);
795
+ reduce(h);
796
+ scalarmult(p,q,h);
797
+
798
+ scalarbase(q,sm + 32);
799
+ add(p,q);
800
+ pack(t,p);
801
+
802
+ n -= 64;
803
+ if (crypto_verify_32(sm, t)) {
804
+ FOR(i,n) m[i] = 0;
805
+ return -1;
806
+ }
807
+
808
+ FOR(i,n) m[i] = sm[i + 64];
809
+ *mlen = n;
810
+ return 0;
811
+ }