x25519 0.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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +5 -0
- data/.rubocop.yml +32 -0
- data/.travis.yml +12 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +11 -0
- data/LICENSE +165 -0
- data/README.md +67 -0
- data/Rakefile +11 -0
- data/ext/x25519/bytes.c +42 -0
- data/ext/x25519/bytes.h +25 -0
- data/ext/x25519/fp25519_x64.c +826 -0
- data/ext/x25519/fp25519_x64.h +91 -0
- data/ext/x25519/random.c +51 -0
- data/ext/x25519/random.h +24 -0
- data/ext/x25519/rfc7748_precompted.h +49 -0
- data/ext/x25519/rfc7748_precomputed.c +20 -0
- data/ext/x25519/table_ladder_x25519.h +277 -0
- data/ext/x25519/x25519_x64.c +244 -0
- data/lib/x25519.rb +7 -0
- data/lib/x25519/version.rb +5 -0
- data/x25519.gemspec +28 -0
- metadata +82 -0
@@ -0,0 +1,244 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright (c) 2017 Armando Faz <armfazh@ic.unicamp.br>.
|
3
|
+
* Institute of Computing.
|
4
|
+
* University of Campinas, Brazil.
|
5
|
+
*
|
6
|
+
* This program is free software: you can redistribute it and/or modify
|
7
|
+
* it under the terms of the GNU Lesser General Public License as
|
8
|
+
* published by the Free Software Foundation, version 3.
|
9
|
+
*
|
10
|
+
* This program 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
|
+
* Lesser General Public License for more details.
|
14
|
+
*
|
15
|
+
* You should have received a copy of the GNU Lesser General Public License
|
16
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
*/
|
18
|
+
#include <fp25519_x64.h>
|
19
|
+
#include <table_ladder_x25519.h>
|
20
|
+
#include "rfc7748_precompted.h"
|
21
|
+
#include "random.h"
|
22
|
+
|
23
|
+
void print_X25519_key(argKey key)
|
24
|
+
{
|
25
|
+
print_bytes(key,X25519_KEYSIZE_BYTES);
|
26
|
+
}
|
27
|
+
void random_X25519_key(argKey key)
|
28
|
+
{
|
29
|
+
random_bytes(key,X25519_KEYSIZE_BYTES);
|
30
|
+
}
|
31
|
+
|
32
|
+
/****** Implementation of Montgomery Ladder Algorithm ************/
|
33
|
+
static inline void cswap_x64(uint64_t bit, uint64_t *const px, uint64_t *const py)
|
34
|
+
{
|
35
|
+
int i=0;
|
36
|
+
uint64_t mask = (uint64_t)0-bit;
|
37
|
+
for(i=0;i<NUM_WORDS_ELTFP25519_X64;i++)
|
38
|
+
{
|
39
|
+
uint64_t t = mask & (px[i] ^ py[i]);
|
40
|
+
px[i] = px[i] ^ t;
|
41
|
+
py[i] = py[i] ^ t;
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
static void x25519_shared_secret_x64(argKey shared, argKey session_key, argKey private_key)
|
46
|
+
{
|
47
|
+
ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
|
48
|
+
ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
|
49
|
+
ALIGN uint64_t workspace[6*NUM_WORDS_ELTFP25519_X64];
|
50
|
+
uint64_t save=0;
|
51
|
+
|
52
|
+
int i=0, j=0;
|
53
|
+
uint64_t prev = 0;
|
54
|
+
uint64_t *const X1 = (uint64_t*)session_key;
|
55
|
+
uint64_t *const key = (uint64_t*)private_key;
|
56
|
+
uint64_t *const Px = coordinates+0;
|
57
|
+
uint64_t *const Pz = coordinates+4;
|
58
|
+
uint64_t *const Qx = coordinates+8;
|
59
|
+
uint64_t *const Qz = coordinates+12;
|
60
|
+
uint64_t *const X2 = Qx;
|
61
|
+
uint64_t *const Z2 = Qz;
|
62
|
+
uint64_t *const X3 = Px;
|
63
|
+
uint64_t *const Z3 = Pz;
|
64
|
+
uint64_t *const X2Z2 = Qx;
|
65
|
+
uint64_t *const X3Z3 = Px;
|
66
|
+
|
67
|
+
uint64_t *const A = workspace+0;
|
68
|
+
uint64_t *const B = workspace+4;
|
69
|
+
uint64_t *const D = workspace+8;
|
70
|
+
uint64_t *const C = workspace+12;
|
71
|
+
uint64_t *const DA = workspace+16;
|
72
|
+
uint64_t *const CB = workspace+20;
|
73
|
+
uint64_t *const AB = A;
|
74
|
+
uint64_t *const DC = D;
|
75
|
+
uint64_t *const DACB = DA;
|
76
|
+
uint64_t *const buffer_1w = buffer;
|
77
|
+
uint64_t *const buffer_2w = buffer;
|
78
|
+
|
79
|
+
/* clampC function */
|
80
|
+
save = private_key[X25519_KEYSIZE_BYTES-1]<<16 | private_key[0];
|
81
|
+
private_key[0] = private_key[0] & (~(uint8_t)0x7);
|
82
|
+
private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)64 | (private_key[X25519_KEYSIZE_BYTES-1] & (uint8_t)0x7F);
|
83
|
+
|
84
|
+
/**
|
85
|
+
* As in the draft:
|
86
|
+
* When receiving such an array, implementations of curve25519
|
87
|
+
* MUST mask the most-significant bit in the final byte. This
|
88
|
+
* is done to preserve compatibility with point formats which
|
89
|
+
* reserve the sign bit for use in other protocols and to
|
90
|
+
* increase resistance to implementation fingerprinting
|
91
|
+
**/
|
92
|
+
session_key[X25519_KEYSIZE_BYTES-1] &= (1<<(255%8))-1;
|
93
|
+
|
94
|
+
copy_EltFp25519_1w_x64(Px,(uint64_t*)session_key);
|
95
|
+
setzero_EltFp25519_1w_x64(Pz);
|
96
|
+
setzero_EltFp25519_1w_x64(Qx);
|
97
|
+
setzero_EltFp25519_1w_x64(Qz);
|
98
|
+
|
99
|
+
Pz[0] = 1;
|
100
|
+
Qx[0] = 1;
|
101
|
+
|
102
|
+
/* main-loop */
|
103
|
+
prev = 0;
|
104
|
+
j = 62;
|
105
|
+
for(i=3;i>=0;i--)
|
106
|
+
{
|
107
|
+
while(j >= 0)
|
108
|
+
{
|
109
|
+
uint64_t bit = (key[i]>>j)&0x1;
|
110
|
+
uint64_t swap = bit^prev;
|
111
|
+
prev = bit;
|
112
|
+
|
113
|
+
add_EltFp25519_1w_x64(A, X2, Z2); /* A = (X2+Z2) */
|
114
|
+
sub_EltFp25519_1w_x64(B, X2, Z2); /* B = (X2-Z2) */
|
115
|
+
add_EltFp25519_1w_x64(C, X3, Z3); /* C = (X3+Z3) */
|
116
|
+
sub_EltFp25519_1w_x64(D, X3, Z3); /* D = (X3-Z3) */
|
117
|
+
mul_EltFp25519_2w_x64(DACB,AB,DC); /* [DA|CB] = [A|B]*[D|C] */
|
118
|
+
|
119
|
+
cswap_x64(swap, A, C);
|
120
|
+
cswap_x64(swap, B, D);
|
121
|
+
|
122
|
+
sqr_EltFp25519_2w_x64(AB); /* [AA|BB] = [A^2|B^2] */
|
123
|
+
add_EltFp25519_1w_x64(X3, DA, CB); /* X3 = (DA+CB) */
|
124
|
+
sub_EltFp25519_1w_x64(Z3, DA, CB); /* Z3 = (DA-CB) */
|
125
|
+
sqr_EltFp25519_2w_x64(X3Z3); /* [X3|Z3] = [(DA+CB)|(DA+CB)]^2 */
|
126
|
+
|
127
|
+
copy_EltFp25519_1w_x64(X2,B); /* X2 = B^2 */
|
128
|
+
sub_EltFp25519_1w_x64(Z2, A, B); /* Z2 = E = AA-BB */
|
129
|
+
mul_a24_EltFp25519_1w_x64(B, Z2); /* B = a24*E */
|
130
|
+
add_EltFp25519_1w_x64(B, B, X2); /* B = a24*E+B */
|
131
|
+
mul_EltFp25519_2w_x64(X2Z2,X2Z2,AB); /* [X2|Z2] = [B|E]*[A|a24*E+B] */
|
132
|
+
mul_EltFp25519_1w_x64(Z3,Z3,X1); /* Z3 = Z3*X1 */
|
133
|
+
|
134
|
+
j--;
|
135
|
+
}
|
136
|
+
j = 63;
|
137
|
+
}
|
138
|
+
|
139
|
+
inv_EltFp25519_1w_x64(A, Qz);
|
140
|
+
mul_EltFp25519_1w_x64((uint64_t*)shared,Qx,A);
|
141
|
+
fred_EltFp25519_1w_x64((uint64_t *) shared);
|
142
|
+
private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)((save>>16) & 0xFF);
|
143
|
+
private_key[0] = (uint8_t)(save & 0xFF);
|
144
|
+
}
|
145
|
+
|
146
|
+
static void x25519_keygen_precmp_x64(argKey session_key, argKey private_key)
|
147
|
+
{
|
148
|
+
ALIGN uint64_t buffer[4*NUM_WORDS_ELTFP25519_X64];
|
149
|
+
ALIGN uint64_t coordinates[4*NUM_WORDS_ELTFP25519_X64];
|
150
|
+
ALIGN uint64_t workspace[4*NUM_WORDS_ELTFP25519_X64];
|
151
|
+
uint64_t save;
|
152
|
+
|
153
|
+
int i=0, j=0, k=0;
|
154
|
+
uint64_t *const key = (uint64_t*)private_key;
|
155
|
+
uint64_t *const Ur1 = coordinates+0;
|
156
|
+
uint64_t *const Zr1 = coordinates+4;
|
157
|
+
uint64_t *const Ur2 = coordinates+8;
|
158
|
+
uint64_t *const Zr2 = coordinates+12;
|
159
|
+
|
160
|
+
uint64_t *const UZr1 = coordinates+0;
|
161
|
+
uint64_t *const ZUr2 = coordinates+8;
|
162
|
+
|
163
|
+
uint64_t *const A = workspace+0;
|
164
|
+
uint64_t *const B = workspace+4;
|
165
|
+
uint64_t *const C = workspace+8;
|
166
|
+
uint64_t *const D = workspace+12;
|
167
|
+
|
168
|
+
uint64_t *const AB = workspace+0;
|
169
|
+
uint64_t *const CD = workspace+8;
|
170
|
+
|
171
|
+
uint64_t *const buffer_1w = buffer;
|
172
|
+
uint64_t *const buffer_2w = buffer;
|
173
|
+
uint64_t * P = (uint64_t *)Table_Ladder_8k;
|
174
|
+
|
175
|
+
/* clampC function */
|
176
|
+
save = private_key[X25519_KEYSIZE_BYTES-1]<<16 | private_key[0];
|
177
|
+
private_key[0] = private_key[0] & (~(uint8_t)0x7);
|
178
|
+
private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)64 | (private_key[X25519_KEYSIZE_BYTES-1] & (uint8_t)0x7F);
|
179
|
+
|
180
|
+
setzero_EltFp25519_1w_x64(Ur1);
|
181
|
+
setzero_EltFp25519_1w_x64(Zr1);
|
182
|
+
setzero_EltFp25519_1w_x64(Zr2);
|
183
|
+
Ur1[0] = 1;
|
184
|
+
Zr1[0] = 1;
|
185
|
+
Zr2[0] = 1;
|
186
|
+
|
187
|
+
/* G-S */
|
188
|
+
Ur2[3] = 0x1eaecdeee27cab34;
|
189
|
+
Ur2[2] = 0xadc7a0b9235d48e2;
|
190
|
+
Ur2[1] = 0xbbf095ae14b2edf8;
|
191
|
+
Ur2[0] = 0x7e94e1fec82faabd;
|
192
|
+
|
193
|
+
/* main-loop */
|
194
|
+
const int ite[4] = {64,64,64,63};
|
195
|
+
const int q = 3;
|
196
|
+
uint64_t swap = 1;
|
197
|
+
|
198
|
+
j = q;
|
199
|
+
for(i=0;i<NUM_WORDS_ELTFP25519_X64;i++)
|
200
|
+
{
|
201
|
+
while(j < ite[i])
|
202
|
+
{
|
203
|
+
k = (64*i+j-q);
|
204
|
+
uint64_t bit = (key[i]>>j)&0x1;
|
205
|
+
swap = swap ^ bit;
|
206
|
+
cswap_x64(swap, Ur1, Ur2);
|
207
|
+
cswap_x64(swap, Zr1, Zr2);
|
208
|
+
swap = bit;
|
209
|
+
/** Addition */
|
210
|
+
sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
|
211
|
+
add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
|
212
|
+
mul_EltFp25519_1w_x64(C,&P[4*k],B); /* C = M0-B */
|
213
|
+
sub_EltFp25519_1w_x64(B, A, C); /* B = (Ur1+Zr1) - M*(Ur1-Zr1) */
|
214
|
+
add_EltFp25519_1w_x64(A, A, C); /* A = (Ur1+Zr1) + M*(Ur1-Zr1) */
|
215
|
+
sqr_EltFp25519_2w_x64(AB); /* A = A^2 | B = B^2 */
|
216
|
+
mul_EltFp25519_2w_x64(UZr1,ZUr2,AB); /* Ur1 = Zr2*A | Zr1 = Ur2*B */
|
217
|
+
j++;
|
218
|
+
}
|
219
|
+
j = 0;
|
220
|
+
}
|
221
|
+
|
222
|
+
/** Doubling */
|
223
|
+
for(i=0;i<q;i++)
|
224
|
+
{
|
225
|
+
add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */
|
226
|
+
sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */
|
227
|
+
sqr_EltFp25519_2w_x64(AB); /* A = A**2 B = B**2 */
|
228
|
+
copy_EltFp25519_1w_x64(C,B); /* C = B */
|
229
|
+
sub_EltFp25519_1w_x64(B, A, B); /* B = A-B */
|
230
|
+
mul_a24_EltFp25519_1w_x64(D, B); /* D = my_a24*B */
|
231
|
+
add_EltFp25519_1w_x64(D, D, C); /* D = D+C */
|
232
|
+
mul_EltFp25519_2w_x64(UZr1,AB,CD); /* Ur1 = A*B Zr1 = Zr1*A */
|
233
|
+
}
|
234
|
+
|
235
|
+
/* Convert to affine coordinates */
|
236
|
+
inv_EltFp25519_1w_x64(A, Zr1);
|
237
|
+
mul_EltFp25519_1w_x64((uint64_t*)session_key,Ur1,A);
|
238
|
+
fred_EltFp25519_1w_x64((uint64_t *) session_key);
|
239
|
+
private_key[X25519_KEYSIZE_BYTES-1] = (uint8_t)((save>>16) & 0xFF);
|
240
|
+
private_key[0] = (uint8_t)(save & 0xFF);
|
241
|
+
}
|
242
|
+
|
243
|
+
const KeyGen X25519_KeyGen_x64 = x25519_keygen_precmp_x64;
|
244
|
+
const Shared X25519_Shared_x64 = x25519_shared_secret_x64;
|
data/lib/x25519.rb
ADDED
data/x25519.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path("../lib", __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
require "x25519/version"
|
7
|
+
|
8
|
+
Gem::Specification.new do |spec|
|
9
|
+
spec.name = "x25519"
|
10
|
+
spec.version = X25519::VERSION
|
11
|
+
spec.authors = ["Tony Arcieri"]
|
12
|
+
spec.email = ["bascule@gmail.com"]
|
13
|
+
spec.summary = "Public key cryptography library providing the X25519 D-H function"
|
14
|
+
spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
|
15
|
+
An efficient public key cryptography library for Ruby providing key
|
16
|
+
exchange/agreement via the X25519 (a.k.a. Curve25519) Elliptic Curve
|
17
|
+
Diffie-Hellman function as described in [RFC7748].
|
18
|
+
DESCRIPTION
|
19
|
+
spec.homepage = "https://github.com/cryptosphere/x25519"
|
20
|
+
spec.license = "MIT"
|
21
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.required_ruby_version = ">= 2.2.2"
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: x25519
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tony Arcieri
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
description: An efficient public key cryptography library for Ruby providing key exchange/agreement
|
28
|
+
via the X25519 (a.k.a. Curve25519) Elliptic Curve Diffie-Hellman function as described
|
29
|
+
in [RFC7748].
|
30
|
+
email:
|
31
|
+
- bascule@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".gitignore"
|
37
|
+
- ".rspec"
|
38
|
+
- ".rubocop.yml"
|
39
|
+
- ".travis.yml"
|
40
|
+
- CODE_OF_CONDUCT.md
|
41
|
+
- Gemfile
|
42
|
+
- LICENSE
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- ext/x25519/bytes.c
|
46
|
+
- ext/x25519/bytes.h
|
47
|
+
- ext/x25519/fp25519_x64.c
|
48
|
+
- ext/x25519/fp25519_x64.h
|
49
|
+
- ext/x25519/random.c
|
50
|
+
- ext/x25519/random.h
|
51
|
+
- ext/x25519/rfc7748_precompted.h
|
52
|
+
- ext/x25519/rfc7748_precomputed.c
|
53
|
+
- ext/x25519/table_ladder_x25519.h
|
54
|
+
- ext/x25519/x25519_x64.c
|
55
|
+
- lib/x25519.rb
|
56
|
+
- lib/x25519/version.rb
|
57
|
+
- x25519.gemspec
|
58
|
+
homepage: https://github.com/cryptosphere/x25519
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata: {}
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options: []
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 2.2.2
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 2.6.13
|
79
|
+
signing_key:
|
80
|
+
specification_version: 4
|
81
|
+
summary: Public key cryptography library providing the X25519 D-H function
|
82
|
+
test_files: []
|