red25519 1.0.0

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/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ lib/red25519_engine.*
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --backtrace
4
+ --default_path spec
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.3
4
+ - ruby-head
5
+ - rbx-18mode
6
+ - rbx-19mode
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: ruby-head
13
+ - rvm: jruby-18mode
14
+ - rvm: jruby-19mode
data/CHANGES.md ADDED
@@ -0,0 +1,3 @@
1
+ 1.0.0
2
+ -----
3
+ * Initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in red25519.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tony Arcieri
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ Red25519
2
+ ========
3
+ [![Build Status](https://secure.travis-ci.org/tarcieri/red25519.png?branch=master)](http://travis-ci.org/tarcieri/red25519)
4
+
5
+ Red25519 provides a Ruby binding to the Ed25519 public-key signature system
6
+ based on elliptic curves and created by Dan Bernstein et al. An implementation
7
+ in C is taken from the SUPERCOP benchmark suite. Ed25519 provides a 128-bit
8
+ security level, that is to say, all known attacks take at least 2^128
9
+ operations, providing the same security level as AES-128, NIST P-256, and
10
+ RSA-3072.
11
+
12
+ Ed25519 has a number of unique properties that make it one of the best-in-class
13
+ digital signature algorithms:
14
+
15
+ * ***Small keys***: Ed25519 keys are only 256-bits (32 bytes), making them
16
+ small enough to easily copy around. Ed25519 also allows the public key
17
+ to be derived from the private key, meaning that it doesn't need to be
18
+ included in a serialized private key in cases you want both.
19
+ * ***Small signatures***: Ed25519 signatures are only 512-bits (64 bytes),
20
+ one of the smallest signature sizes available.
21
+ * ***Deterministic***: Unlike (EC)DSA, Ed25519 does not rely on an entropy
22
+ source when signing messages. This can be a potential attack vector if
23
+ the entropy source is not generating good random numbers. Ed25519 avoids
24
+ this problem entirely and will always generate the same signature for the
25
+ same data.
26
+ * ***Collision Resistant***: Hash-function collisions do not break this
27
+ system. This adds a layer of defense against the possibility of weakness
28
+ in the selected hash function.
29
+
30
+ You can read more on [Dan Bernstein's Ed25519 site](http://ed25519.cr.yp.to/).
31
+
32
+ Installation
33
+ ------------
34
+
35
+ Add this line to your application's Gemfile:
36
+
37
+ gem 'red25519'
38
+
39
+ And then execute:
40
+
41
+ $ bundle
42
+
43
+ Or install it yourself as:
44
+
45
+ $ gem install red25519
46
+
47
+ Usage
48
+ -----
49
+
50
+ Require red25519 in your Ruby program:
51
+
52
+ ```ruby
53
+ require 'red25519'
54
+ ```
55
+
56
+ Generate a new random signing key:
57
+
58
+ ```ruby
59
+ signing_key = Ed25519::SigningKey.generate
60
+ ```
61
+
62
+ Sign a message with the signing key:
63
+
64
+ ```ruby
65
+ signature = signing_key.sign(message)
66
+ ```
67
+
68
+ Obtain the verify key for a given signing key:
69
+
70
+ ```ruby
71
+ verify_key = signing_key.verify_key
72
+ ```
73
+
74
+ Check the validity of a signature:
75
+
76
+ ```ruby
77
+ verify_key.verify(signature, message)
78
+ ```
79
+
80
+ The verify method will return `true` or `false` depending on if the signature matches.
81
+
82
+ ### Serializing Keys
83
+
84
+ Keys can be serialized as 32-byte binary strings as follows:
85
+
86
+ ```ruby
87
+ signature_key_bytes = signing_key.to_bytes
88
+ verify_key_bytes = verify_key.to_bytes
89
+ ```
90
+
91
+ The binary serialization can be passed directly into the constructor for a given key type:
92
+
93
+ ```ruby
94
+ signing_key = Ed25519::SigningKey.new(signature_key_bytes)
95
+ verify_key = Ed25519::VerifyKey.new(verify_key_bytes)
96
+ ```
97
+
98
+ You can also serialize keys to a hex string instead of a binary string:
99
+
100
+ ```ruby
101
+ signing_key_hex = signing_key.to_hex
102
+ ```
103
+
104
+ The hex representation can also be passed into the constructor:
105
+
106
+ ```ruby
107
+ signing_key = Ed25519::SigningKey.new(signing_key_hex)
108
+ ```
109
+
110
+ Contributing
111
+ ------------
112
+
113
+ * Fork this repository on github
114
+ * Make your changes and send me a pull request
115
+ * If I like them I'll merge them
116
+ * If I've accepted a patch, feel free to ask for commit access
117
+
118
+ License
119
+ -------
120
+
121
+ Copyright (c) 2012 Tony Arcieri. Distributed under the MIT License. See
122
+ LICENSE for further details.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/clean"
4
+
5
+ Dir[File.expand_path("../tasks/**/*.rake", __FILE__)].each { |task| load task }
6
+
7
+ task :default => %w(compile spec)
8
+
9
+ CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "**/*.jar", "pkg", "tmp"
@@ -0,0 +1,4 @@
1
+ #define CRYPTO_SECRETKEYBYTES 64
2
+ #define CRYPTO_PUBLICKEYBYTES 32
3
+ #define CRYPTO_BYTES 64
4
+
@@ -0,0 +1,6 @@
1
+ #ifndef crypto_int32_h
2
+ #define crypto_int32_h
3
+
4
+ typedef int crypto_int32;
5
+
6
+ #endif
@@ -0,0 +1,13 @@
1
+ #ifndef crypto_sign_edwards25519sha512batch_H
2
+ #define crypto_sign_edwards25519sha512batch_H
3
+
4
+ #define SECRETKEYBYTES 64
5
+ #define PUBLICKEYBYTES 32
6
+ #define SIGNATUREBYTES 64
7
+
8
+ extern int crypto_sign(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
9
+ extern int crypto_sign_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
10
+ extern int crypto_sign_keypair(unsigned char *,unsigned char *);
11
+ extern int crypto_sign_publickey(unsigned char *pk, unsigned char *sk, unsigned char *seed);
12
+
13
+ #endif
@@ -0,0 +1,6 @@
1
+ #ifndef crypto_uint32_h
2
+ #define crypto_uint32_h
3
+
4
+ typedef unsigned int crypto_uint32;
5
+
6
+ #endif
@@ -0,0 +1,7 @@
1
+ #ifndef crypto_verify_32_H
2
+ #define crypto_verify_32_H
3
+
4
+ #define crypto_verify_32_ref_BYTES 32
5
+ extern int crypto_verify_32(const unsigned char *,const unsigned char *);
6
+
7
+ #endif
@@ -0,0 +1,136 @@
1
+ #include "crypto_sign.h"
2
+
3
+ #include "crypto_verify_32.h"
4
+ #include "sha512.h"
5
+
6
+ #include "ge25519.h"
7
+
8
+ static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen)
9
+ {
10
+ unsigned long long i;
11
+
12
+ for (i = 0;i < 32;++i) playground[i] = sm[i];
13
+ for (i = 32;i < 64;++i) playground[i] = pk[i-32];
14
+ for (i = 64;i < smlen;++i) playground[i] = sm[i];
15
+
16
+ crypto_hash_sha512(hram,playground,smlen);
17
+ }
18
+
19
+
20
+ int crypto_sign_publickey(
21
+ unsigned char *pk, // write 32 bytes into this
22
+ unsigned char *sk, // write 64 bytes into this (seed+pubkey)
23
+ unsigned char *seed // 32 bytes
24
+ )
25
+ {
26
+ sc25519 scsk;
27
+ ge25519 gepk;
28
+ int i;
29
+
30
+ crypto_hash_sha512(sk, seed, 32);
31
+ sk[0] &= 248;
32
+ sk[31] &= 127;
33
+ sk[31] |= 64;
34
+
35
+ sc25519_from32bytes(&scsk,sk);
36
+
37
+ ge25519_scalarmult_base(&gepk, &scsk);
38
+ ge25519_pack(pk, &gepk);
39
+ for(i=0;i<32;i++)
40
+ sk[32 + i] = pk[i];
41
+ for(i=0;i<32;i++)
42
+ sk[i] = seed[i];
43
+ return 0;
44
+ }
45
+
46
+ int crypto_sign(
47
+ unsigned char *sm,unsigned long long *smlen,
48
+ const unsigned char *m,unsigned long long mlen,
49
+ const unsigned char *sk
50
+ )
51
+ {
52
+ sc25519 sck, scs, scsk;
53
+ ge25519 ger;
54
+ unsigned char r[32];
55
+ unsigned char s[32];
56
+ unsigned char extsk[64];
57
+ unsigned long long i;
58
+ unsigned char hmg[crypto_hash_sha512_BYTES];
59
+ unsigned char hram[crypto_hash_sha512_BYTES];
60
+
61
+ crypto_hash_sha512(extsk, sk, 32);
62
+ extsk[0] &= 248;
63
+ extsk[31] &= 127;
64
+ extsk[31] |= 64;
65
+
66
+ *smlen = mlen+64;
67
+ for(i=0;i<mlen;i++)
68
+ sm[64 + i] = m[i];
69
+ for(i=0;i<32;i++)
70
+ sm[32 + i] = extsk[32+i];
71
+
72
+ crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */
73
+
74
+ /* Computation of R */
75
+ sc25519_from64bytes(&sck, hmg);
76
+ ge25519_scalarmult_base(&ger, &sck);
77
+ ge25519_pack(r, &ger);
78
+
79
+ /* Computation of s */
80
+ for(i=0;i<32;i++)
81
+ sm[i] = r[i];
82
+
83
+ get_hram(hram, sm, sk+32, sm, mlen+64);
84
+
85
+ sc25519_from64bytes(&scs, hram);
86
+ sc25519_from32bytes(&scsk, extsk);
87
+ sc25519_mul(&scs, &scs, &scsk);
88
+
89
+ sc25519_add(&scs, &scs, &sck);
90
+
91
+ sc25519_to32bytes(s,&scs); /* cat s */
92
+ for(i=0;i<32;i++)
93
+ sm[32 + i] = s[i];
94
+
95
+ return 0;
96
+ }
97
+
98
+ int crypto_sign_open(
99
+ unsigned char *m,unsigned long long *mlen,
100
+ const unsigned char *sm,unsigned long long smlen,
101
+ const unsigned char *pk
102
+ )
103
+ {
104
+ int i, ret;
105
+ unsigned char t2[32];
106
+ ge25519 get1, get2;
107
+ sc25519 schram, scs;
108
+ unsigned char hram[crypto_hash_sha512_BYTES];
109
+
110
+ if (ge25519_unpackneg_vartime(&get1, pk)) return -1;
111
+
112
+ get_hram(hram,sm,pk,m,smlen);
113
+
114
+ sc25519_from64bytes(&schram, hram);
115
+
116
+ sc25519_from32bytes(&scs, sm+32);
117
+
118
+ ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs);
119
+ ge25519_pack(t2, &get2);
120
+
121
+ ret = crypto_verify_32(sm, t2);
122
+
123
+ if (!ret)
124
+ {
125
+ for(i=0;i<smlen-64;i++)
126
+ m[i] = sm[i + 64];
127
+ *mlen = smlen-64;
128
+ }
129
+ else
130
+ {
131
+ for(i=0;i<smlen-64;i++)
132
+ m[i] = 0;
133
+ *mlen = (unsigned long long) -1;
134
+ }
135
+ return ret;
136
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+
3
+ dir_config 'red25519_engine'
4
+ create_makefile 'red25519_engine'
@@ -0,0 +1,326 @@
1
+ #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
2
+ #define WINDOWMASK ((1<<WINDOWSIZE)-1)
3
+
4
+ #include "fe25519.h"
5
+
6
+ static crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
7
+ {
8
+ crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
9
+ x -= 1; /* 4294967295: yes; 0..65534: no */
10
+ x >>= 31; /* 1: yes; 0: no */
11
+ return x;
12
+ }
13
+
14
+ static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
15
+ {
16
+ unsigned int x = a;
17
+ x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
18
+ x >>= 31; /* 0: yes; 1: no */
19
+ x ^= 1; /* 1: yes; 0: no */
20
+ return x;
21
+ }
22
+
23
+ static crypto_uint32 times19(crypto_uint32 a)
24
+ {
25
+ return (a << 4) + (a << 1) + a;
26
+ }
27
+
28
+ static crypto_uint32 times38(crypto_uint32 a)
29
+ {
30
+ return (a << 5) + (a << 2) + (a << 1);
31
+ }
32
+
33
+ static void reduce_add_sub(fe25519 *r)
34
+ {
35
+ crypto_uint32 t;
36
+ int i,rep;
37
+
38
+ for(rep=0;rep<4;rep++)
39
+ {
40
+ t = r->v[31] >> 7;
41
+ r->v[31] &= 127;
42
+ t = times19(t);
43
+ r->v[0] += t;
44
+ for(i=0;i<31;i++)
45
+ {
46
+ t = r->v[i] >> 8;
47
+ r->v[i+1] += t;
48
+ r->v[i] &= 255;
49
+ }
50
+ }
51
+ }
52
+
53
+ static void reduce_mul(fe25519 *r)
54
+ {
55
+ crypto_uint32 t;
56
+ int i,rep;
57
+
58
+ for(rep=0;rep<2;rep++)
59
+ {
60
+ t = r->v[31] >> 7;
61
+ r->v[31] &= 127;
62
+ t = times19(t);
63
+ r->v[0] += t;
64
+ for(i=0;i<31;i++)
65
+ {
66
+ t = r->v[i] >> 8;
67
+ r->v[i+1] += t;
68
+ r->v[i] &= 255;
69
+ }
70
+ }
71
+ }
72
+
73
+ /* reduction modulo 2^255-19 */
74
+ void fe25519_freeze(fe25519 *r)
75
+ {
76
+ int i;
77
+ crypto_uint32 m = equal(r->v[31],127);
78
+ for(i=30;i>0;i--)
79
+ m &= equal(r->v[i],255);
80
+ m &= ge(r->v[0],237);
81
+
82
+ m = -m;
83
+
84
+ r->v[31] -= m&127;
85
+ for(i=30;i>0;i--)
86
+ r->v[i] -= m&255;
87
+ r->v[0] -= m&237;
88
+ }
89
+
90
+ void fe25519_unpack(fe25519 *r, const unsigned char x[32])
91
+ {
92
+ int i;
93
+ for(i=0;i<32;i++) r->v[i] = x[i];
94
+ r->v[31] &= 127;
95
+ }
96
+
97
+ /* Assumes input x being reduced below 2^255 */
98
+ void fe25519_pack(unsigned char r[32], const fe25519 *x)
99
+ {
100
+ int i;
101
+ fe25519 y = *x;
102
+ fe25519_freeze(&y);
103
+ for(i=0;i<32;i++)
104
+ r[i] = y.v[i];
105
+ }
106
+
107
+ int fe25519_iszero(const fe25519 *x)
108
+ {
109
+ int i, r;
110
+ fe25519 t = *x;
111
+ fe25519_freeze(&t);
112
+ r = equal(t.v[0],0);
113
+ for(i=1;i<32;i++)
114
+ r &= equal(t.v[i],0);
115
+ return r;
116
+ }
117
+
118
+ int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
119
+ {
120
+ int i;
121
+ fe25519 t1 = *x;
122
+ fe25519 t2 = *y;
123
+ fe25519_freeze(&t1);
124
+ fe25519_freeze(&t2);
125
+ for(i=0;i<32;i++)
126
+ if(t1.v[i] != t2.v[i]) return 0;
127
+ return 1;
128
+ }
129
+
130
+ void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
131
+ {
132
+ int i;
133
+ crypto_uint32 mask = b;
134
+ mask = -mask;
135
+ for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
136
+ }
137
+
138
+ unsigned char fe25519_getparity(const fe25519 *x)
139
+ {
140
+ fe25519 t = *x;
141
+ fe25519_freeze(&t);
142
+ return t.v[0] & 1;
143
+ }
144
+
145
+ void fe25519_setone(fe25519 *r)
146
+ {
147
+ int i;
148
+ r->v[0] = 1;
149
+ for(i=1;i<32;i++) r->v[i]=0;
150
+ }
151
+
152
+ void fe25519_setzero(fe25519 *r)
153
+ {
154
+ int i;
155
+ for(i=0;i<32;i++) r->v[i]=0;
156
+ }
157
+
158
+ void fe25519_neg(fe25519 *r, const fe25519 *x)
159
+ {
160
+ fe25519 t;
161
+ int i;
162
+ for(i=0;i<32;i++) t.v[i]=x->v[i];
163
+ fe25519_setzero(r);
164
+ fe25519_sub(r, r, &t);
165
+ }
166
+
167
+ void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
168
+ {
169
+ int i;
170
+ for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
171
+ reduce_add_sub(r);
172
+ }
173
+
174
+ void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
175
+ {
176
+ int i;
177
+ crypto_uint32 t[32];
178
+ t[0] = x->v[0] + 0x1da;
179
+ t[31] = x->v[31] + 0xfe;
180
+ for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
181
+ for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
182
+ reduce_add_sub(r);
183
+ }
184
+
185
+ void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
186
+ {
187
+ int i,j;
188
+ crypto_uint32 t[63];
189
+ for(i=0;i<63;i++)t[i] = 0;
190
+
191
+ for(i=0;i<32;i++)
192
+ for(j=0;j<32;j++)
193
+ t[i+j] += x->v[i] * y->v[j];
194
+
195
+ for(i=32;i<63;i++)
196
+ r->v[i-32] = t[i-32] + times38(t[i]);
197
+ r->v[31] = t[31]; /* result now in r[0]...r[31] */
198
+
199
+ reduce_mul(r);
200
+ }
201
+
202
+ void fe25519_square(fe25519 *r, const fe25519 *x)
203
+ {
204
+ fe25519_mul(r, x, x);
205
+ }
206
+
207
+ void fe25519_invert(fe25519 *r, const fe25519 *x)
208
+ {
209
+ fe25519 z2;
210
+ fe25519 z9;
211
+ fe25519 z11;
212
+ fe25519 z2_5_0;
213
+ fe25519 z2_10_0;
214
+ fe25519 z2_20_0;
215
+ fe25519 z2_50_0;
216
+ fe25519 z2_100_0;
217
+ fe25519 t0;
218
+ fe25519 t1;
219
+ int i;
220
+
221
+ /* 2 */ fe25519_square(&z2,x);
222
+ /* 4 */ fe25519_square(&t1,&z2);
223
+ /* 8 */ fe25519_square(&t0,&t1);
224
+ /* 9 */ fe25519_mul(&z9,&t0,x);
225
+ /* 11 */ fe25519_mul(&z11,&z9,&z2);
226
+ /* 22 */ fe25519_square(&t0,&z11);
227
+ /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
228
+
229
+ /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
230
+ /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
231
+ /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
232
+ /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
233
+ /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
234
+ /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
235
+
236
+ /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
237
+ /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
238
+ /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
239
+ /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
240
+
241
+ /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
242
+ /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
243
+ /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
244
+ /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
245
+
246
+ /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
247
+ /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
248
+ /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
249
+ /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
250
+
251
+ /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
252
+ /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
253
+ /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
254
+ /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
255
+
256
+ /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
257
+ /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
258
+ /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
259
+ /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
260
+
261
+ /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
262
+ /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
263
+ /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
264
+ /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
265
+
266
+ /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
267
+ /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
268
+ /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
269
+ /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
270
+ /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
271
+ /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);
272
+ }
273
+
274
+ void fe25519_pow2523(fe25519 *r, const fe25519 *x)
275
+ {
276
+ fe25519 z2;
277
+ fe25519 z9;
278
+ fe25519 z11;
279
+ fe25519 z2_5_0;
280
+ fe25519 z2_10_0;
281
+ fe25519 z2_20_0;
282
+ fe25519 z2_50_0;
283
+ fe25519 z2_100_0;
284
+ fe25519 t;
285
+ int i;
286
+
287
+ /* 2 */ fe25519_square(&z2,x);
288
+ /* 4 */ fe25519_square(&t,&z2);
289
+ /* 8 */ fe25519_square(&t,&t);
290
+ /* 9 */ fe25519_mul(&z9,&t,x);
291
+ /* 11 */ fe25519_mul(&z11,&z9,&z2);
292
+ /* 22 */ fe25519_square(&t,&z11);
293
+ /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
294
+
295
+ /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
296
+ /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
297
+ /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
298
+
299
+ /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
300
+ /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
301
+ /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
302
+
303
+ /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
304
+ /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
305
+ /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
306
+
307
+ /* 2^41 - 2^1 */ fe25519_square(&t,&t);
308
+ /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
309
+ /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
310
+
311
+ /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
312
+ /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
313
+ /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
314
+
315
+ /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
316
+ /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
317
+ /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
318
+
319
+ /* 2^201 - 2^1 */ fe25519_square(&t,&t);
320
+ /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
321
+ /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
322
+
323
+ /* 2^251 - 2^1 */ fe25519_square(&t,&t);
324
+ /* 2^252 - 2^2 */ fe25519_square(&t,&t);
325
+ /* 2^252 - 3 */ fe25519_mul(r,&t,x);
326
+ }