waves_ruby_client 0.1.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.
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module BTC
6
+ # This allows doing `BTC.to_hex(...)`
7
+ module Data; end
8
+ include Data
9
+ extend self
10
+
11
+ module Data
12
+ extend self
13
+
14
+ HEX_PACK_CODE = 'H*'
15
+ BYTE_PACK_CODE = 'C*'
16
+
17
+ # Generates a secure random number of a given length
18
+ def random_data(length = 32)
19
+ SecureRandom.random_bytes(length)
20
+ end
21
+
22
+ # Converts hexadecimal string to a binary data string.
23
+ def data_from_hex(hex_string)
24
+ raise ArgumentError, 'Hex string is missing' unless hex_string
25
+ hex_string = hex_string.strip
26
+ data = [hex_string].pack(HEX_PACK_CODE)
27
+ if hex_from_data(data) != hex_string.downcase # invalid hex string was detected
28
+ raise FormatError, "Hex string is invalid: #{hex_string.inspect}"
29
+ end
30
+ data
31
+ end
32
+
33
+ # Converts binary string to lowercase hexadecimal representation.
34
+ def hex_from_data(data)
35
+ raise ArgumentError, 'Data is missing' unless data
36
+ data.unpack(HEX_PACK_CODE).first
37
+ end
38
+
39
+ def to_hex(data)
40
+ hex_from_data(data)
41
+ end
42
+
43
+ def from_hex(hex)
44
+ data_from_hex(hex)
45
+ end
46
+
47
+ # Converts a binary string to an array of bytes (list of integers).
48
+ # Returns a much more efficient slice of bytes if offset/limit or
49
+ # range are specified. That is, avoids converting the entire buffer to byte array.
50
+ #
51
+ # Note 1: if range is specified, it takes precedence over offset/limit.
52
+ #
53
+ # Note 2: byteslice(...).bytes is less efficient as it creates
54
+ # an intermediate shorter string.
55
+ #
56
+ def bytes_from_data(data, offset: 0, limit: nil, range: nil)
57
+ raise ArgumentError, 'Data is missing' unless data
58
+ return data.bytes if offset == 0 && limit.nil? && range.nil?
59
+ if range
60
+ offset = range.begin
61
+ limit = range.size
62
+ end
63
+ bytes = []
64
+ data.each_byte do |byte|
65
+ if offset > 0
66
+ offset -= 1
67
+ else
68
+ if !limit || limit > 0
69
+ bytes << byte
70
+ limit -= 1 if limit
71
+ else
72
+ break
73
+ end
74
+ end
75
+ end
76
+ bytes
77
+ end
78
+
79
+ # Converts binary string to an array of bytes (list of integers).
80
+ def data_from_bytes(bytes)
81
+ raise ArgumentError, 'Bytes are missing' unless bytes
82
+ bytes.pack(BYTE_PACK_CODE)
83
+ end
84
+
85
+ # Returns string as-is if it is ASCII-compatible
86
+ # (that is, if you are interested in 7-bit characters exposed as #bytes).
87
+ # If it is not, attempts to transcode to UTF8 replacing invalid characters if there are any.
88
+ # If options are not specified, uses safe default that replaces unknown characters with standard character.
89
+ # If options are specified, they are used as-is for String#encode method.
90
+ def ensure_ascii_compatible_encoding(string, options = nil)
91
+ if string.encoding.ascii_compatible?
92
+ string
93
+ else
94
+ string.encode(Encoding::UTF_8, options || { invalid: :replace, undef: :replace })
95
+ end
96
+ end
97
+
98
+ # Returns string as-is if it is already encoded in binary encoding (aka BINARY or ASCII-8BIT).
99
+ # If it is not, converts to binary by calling stdlib's method #b.
100
+ def ensure_binary_encoding(string)
101
+ raise ArgumentError, 'String is missing' unless string
102
+ if string.encoding == Encoding::BINARY
103
+ string
104
+ else
105
+ string.b
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,1154 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Stupid ruby port from https://github.com/wavesplatform/curve25519-js/blob/master/axlsign.js
4
+
5
+ # Curve25519 signatures (and also key agreement)
6
+ # like in the early Axolotl.
7
+ #
8
+ # Written by Dmitry Chestnykh.
9
+ # You can use it under MIT or CC0 license.
10
+
11
+ # Curve25519 signatures idea and math by Trevor Perrin
12
+ # https://moderncrypto.org/mail-archive/curves/2014/000205.html
13
+
14
+ # Derived from TweetNaCl.js (https://tweetnacl.js.org/)
15
+ # Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.
16
+ # Public domain.
17
+ #
18
+ # Implementation derived from TweetNaCl version 20140427.
19
+ # See for details: http://tweetnacl.cr.yp.to/
20
+
21
+ class Axlsign
22
+ def self.gf(init = nil)
23
+ r = Array.new(16, 0)
24
+ (0..init.length - 1).each { |i| r[i] = init[i] } if init
25
+ r
26
+ end
27
+
28
+ @_0 = []
29
+ @_9 = []
30
+ @_9[0] = 9
31
+
32
+ @gf1 = gf([1])
33
+ @gf0 = gf
34
+ @D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203])
35
+ @D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406])
36
+ @X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169])
37
+ @Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666])
38
+
39
+ def self.ts64(x, i, h, l) # >>
40
+ x[i] = (h >> 24) & 0xff
41
+ x[i + 1] = (h >> 16) & 0xff
42
+ x[i + 2] = (h >> 8) & 0xff
43
+ x[i + 3] = h & 0xff
44
+ x[i + 4] = (l >> 24) & 0xff
45
+ x[i + 5] = (l >> 16) & 0xff
46
+ x[i + 6] = (l >> 8) & 0xff
47
+ x[i + 7] = l & 0xff
48
+ x
49
+ end
50
+
51
+ def self.set25519(r, a)
52
+ (0..15).each { |i| r[i] = a[i] | 0 }
53
+ r
54
+ end
55
+
56
+ def self.car25519(o)
57
+ c = 1
58
+ (0..15).each do |i|
59
+ v = o[i] + c + 65_535
60
+ c = (v.to_f / 65_536).floor
61
+ o[i] = v - c * 65_536
62
+ end
63
+ o[0] += c - 1 + 37 * (c - 1)
64
+ o
65
+ end
66
+
67
+ def self.sel25519(p, q, b)
68
+ c = ~(b - 1)
69
+ (0..15).each do |i|
70
+ t = c & (p[i] ^ q[i])
71
+ p[i] ^= t.to_i
72
+ q[i] ^= t.to_i
73
+ end
74
+ [p, q]
75
+ end
76
+
77
+ def self.pack25519(o, n) # >>
78
+ m = gf
79
+ t = gf
80
+ (0..15).each { |i| t[i] = n[i] }
81
+ t = car25519(t)
82
+ t = car25519(t)
83
+ t = car25519(t)
84
+ (0..1).each do |_j|
85
+ m[0] = t[0] - 0xffed
86
+ (1..14).each do |i|
87
+ m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1)
88
+ m[i - 1] &= 0xffff
89
+ end
90
+ m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1)
91
+ b = (m[15] >> 16) & 1
92
+ m[14] &= 0xffff
93
+ t, m = sel25519(t, m, 1 - b)
94
+ end
95
+ (0..15).each do |i|
96
+ o[2 * i] = t[i] & 0xff
97
+ o[2 * i + 1] = t[i] >> 8
98
+ end
99
+ o
100
+ end
101
+
102
+ def self.par25519(a)
103
+ d = []
104
+ d = pack25519(d, a)
105
+ d[0] & 1
106
+ end
107
+
108
+ def self.A(o, a, b)
109
+ (0..15).each { |i| o[i] = a[i] + b[i] }
110
+ o
111
+ end
112
+
113
+ def self.Z(o, a, b)
114
+ (0..15).each { |i| o[i] = a[i] - b[i] }
115
+ o
116
+ end
117
+
118
+ def self.M(o, a, b)
119
+ t0 = 0
120
+ t1 = 0
121
+ t2 = 0
122
+ t3 = 0
123
+ t4 = 0
124
+ t5 = 0
125
+ t6 = 0
126
+ t7 = 0
127
+ t8 = 0
128
+ t9 = 0
129
+ t10 = 0
130
+ t11 = 0
131
+ t12 = 0
132
+ t13 = 0
133
+ t14 = 0
134
+ t15 = 0
135
+ t16 = 0
136
+ t17 = 0
137
+ t18 = 0
138
+ t19 = 0
139
+ t20 = 0
140
+ t21 = 0
141
+ t22 = 0
142
+ t23 = 0
143
+ t24 = 0
144
+ t25 = 0
145
+ t26 = 0
146
+ t27 = 0
147
+ t28 = 0
148
+ t29 = 0
149
+ t30 = 0
150
+ b0 = b[0]
151
+ b1 = b[1]
152
+ b2 = b[2]
153
+ b3 = b[3]
154
+ b4 = b[4]
155
+ b5 = b[5]
156
+ b6 = b[6]
157
+ b7 = b[7]
158
+ b8 = b[8]
159
+ b9 = b[9]
160
+ b10 = b[10]
161
+ b11 = b[11]
162
+ b12 = b[12]
163
+ b13 = b[13]
164
+ b14 = b[14]
165
+ b15 = b[15]
166
+
167
+ v = a[0]
168
+ t0 += v * b0
169
+ t1 += v * b1
170
+ t2 += v * b2
171
+ t3 += v * b3
172
+ t4 += v * b4
173
+ t5 += v * b5
174
+ t6 += v * b6
175
+ t7 += v * b7
176
+ t8 += v * b8
177
+ t9 += v * b9
178
+ t10 += v * b10
179
+ t11 += v * b11
180
+ t12 += v * b12
181
+ t13 += v * b13
182
+ t14 += v * b14
183
+ t15 += v * b15
184
+ v = a[1]
185
+ t1 += v * b0
186
+ t2 += v * b1
187
+ t3 += v * b2
188
+ t4 += v * b3
189
+ t5 += v * b4
190
+ t6 += v * b5
191
+ t7 += v * b6
192
+ t8 += v * b7
193
+ t9 += v * b8
194
+ t10 += v * b9
195
+ t11 += v * b10
196
+ t12 += v * b11
197
+ t13 += v * b12
198
+ t14 += v * b13
199
+ t15 += v * b14
200
+ t16 += v * b15
201
+ v = a[2]
202
+ t2 += v * b0
203
+ t3 += v * b1
204
+ t4 += v * b2
205
+ t5 += v * b3
206
+ t6 += v * b4
207
+ t7 += v * b5
208
+ t8 += v * b6
209
+ t9 += v * b7
210
+ t10 += v * b8
211
+ t11 += v * b9
212
+ t12 += v * b10
213
+ t13 += v * b11
214
+ t14 += v * b12
215
+ t15 += v * b13
216
+ t16 += v * b14
217
+ t17 += v * b15
218
+ v = a[3]
219
+ t3 += v * b0
220
+ t4 += v * b1
221
+ t5 += v * b2
222
+ t6 += v * b3
223
+ t7 += v * b4
224
+ t8 += v * b5
225
+ t9 += v * b6
226
+ t10 += v * b7
227
+ t11 += v * b8
228
+ t12 += v * b9
229
+ t13 += v * b10
230
+ t14 += v * b11
231
+ t15 += v * b12
232
+ t16 += v * b13
233
+ t17 += v * b14
234
+ t18 += v * b15
235
+ v = a[4]
236
+ t4 += v * b0
237
+ t5 += v * b1
238
+ t6 += v * b2
239
+ t7 += v * b3
240
+ t8 += v * b4
241
+ t9 += v * b5
242
+ t10 += v * b6
243
+ t11 += v * b7
244
+ t12 += v * b8
245
+ t13 += v * b9
246
+ t14 += v * b10
247
+ t15 += v * b11
248
+ t16 += v * b12
249
+ t17 += v * b13
250
+ t18 += v * b14
251
+ t19 += v * b15
252
+ v = a[5]
253
+ t5 += v * b0
254
+ t6 += v * b1
255
+ t7 += v * b2
256
+ t8 += v * b3
257
+ t9 += v * b4
258
+ t10 += v * b5
259
+ t11 += v * b6
260
+ t12 += v * b7
261
+ t13 += v * b8
262
+ t14 += v * b9
263
+ t15 += v * b10
264
+ t16 += v * b11
265
+ t17 += v * b12
266
+ t18 += v * b13
267
+ t19 += v * b14
268
+ t20 += v * b15
269
+ v = a[6]
270
+ t6 += v * b0
271
+ t7 += v * b1
272
+ t8 += v * b2
273
+ t9 += v * b3
274
+ t10 += v * b4
275
+ t11 += v * b5
276
+ t12 += v * b6
277
+ t13 += v * b7
278
+ t14 += v * b8
279
+ t15 += v * b9
280
+ t16 += v * b10
281
+ t17 += v * b11
282
+ t18 += v * b12
283
+ t19 += v * b13
284
+ t20 += v * b14
285
+ t21 += v * b15
286
+ v = a[7]
287
+ t7 += v * b0
288
+ t8 += v * b1
289
+ t9 += v * b2
290
+ t10 += v * b3
291
+ t11 += v * b4
292
+ t12 += v * b5
293
+ t13 += v * b6
294
+ t14 += v * b7
295
+ t15 += v * b8
296
+ t16 += v * b9
297
+ t17 += v * b10
298
+ t18 += v * b11
299
+ t19 += v * b12
300
+ t20 += v * b13
301
+ t21 += v * b14
302
+ t22 += v * b15
303
+ v = a[8]
304
+ t8 += v * b0
305
+ t9 += v * b1
306
+ t10 += v * b2
307
+ t11 += v * b3
308
+ t12 += v * b4
309
+ t13 += v * b5
310
+ t14 += v * b6
311
+ t15 += v * b7
312
+ t16 += v * b8
313
+ t17 += v * b9
314
+ t18 += v * b10
315
+ t19 += v * b11
316
+ t20 += v * b12
317
+ t21 += v * b13
318
+ t22 += v * b14
319
+ t23 += v * b15
320
+ v = a[9]
321
+ t9 += v * b0
322
+ t10 += v * b1
323
+ t11 += v * b2
324
+ t12 += v * b3
325
+ t13 += v * b4
326
+ t14 += v * b5
327
+ t15 += v * b6
328
+ t16 += v * b7
329
+ t17 += v * b8
330
+ t18 += v * b9
331
+ t19 += v * b10
332
+ t20 += v * b11
333
+ t21 += v * b12
334
+ t22 += v * b13
335
+ t23 += v * b14
336
+ t24 += v * b15
337
+ v = a[10]
338
+ t10 += v * b0
339
+ t11 += v * b1
340
+ t12 += v * b2
341
+ t13 += v * b3
342
+ t14 += v * b4
343
+ t15 += v * b5
344
+ t16 += v * b6
345
+ t17 += v * b7
346
+ t18 += v * b8
347
+ t19 += v * b9
348
+ t20 += v * b10
349
+ t21 += v * b11
350
+ t22 += v * b12
351
+ t23 += v * b13
352
+ t24 += v * b14
353
+ t25 += v * b15
354
+ v = a[11]
355
+ t11 += v * b0
356
+ t12 += v * b1
357
+ t13 += v * b2
358
+ t14 += v * b3
359
+ t15 += v * b4
360
+ t16 += v * b5
361
+ t17 += v * b6
362
+ t18 += v * b7
363
+ t19 += v * b8
364
+ t20 += v * b9
365
+ t21 += v * b10
366
+ t22 += v * b11
367
+ t23 += v * b12
368
+ t24 += v * b13
369
+ t25 += v * b14
370
+ t26 += v * b15
371
+ v = a[12]
372
+ t12 += v * b0
373
+ t13 += v * b1
374
+ t14 += v * b2
375
+ t15 += v * b3
376
+ t16 += v * b4
377
+ t17 += v * b5
378
+ t18 += v * b6
379
+ t19 += v * b7
380
+ t20 += v * b8
381
+ t21 += v * b9
382
+ t22 += v * b10
383
+ t23 += v * b11
384
+ t24 += v * b12
385
+ t25 += v * b13
386
+ t26 += v * b14
387
+ t27 += v * b15
388
+ v = a[13]
389
+ t13 += v * b0
390
+ t14 += v * b1
391
+ t15 += v * b2
392
+ t16 += v * b3
393
+ t17 += v * b4
394
+ t18 += v * b5
395
+ t19 += v * b6
396
+ t20 += v * b7
397
+ t21 += v * b8
398
+ t22 += v * b9
399
+ t23 += v * b10
400
+ t24 += v * b11
401
+ t25 += v * b12
402
+ t26 += v * b13
403
+ t27 += v * b14
404
+ t28 += v * b15
405
+ v = a[14]
406
+ t14 += v * b0
407
+ t15 += v * b1
408
+ t16 += v * b2
409
+ t17 += v * b3
410
+ t18 += v * b4
411
+ t19 += v * b5
412
+ t20 += v * b6
413
+ t21 += v * b7
414
+ t22 += v * b8
415
+ t23 += v * b9
416
+ t24 += v * b10
417
+ t25 += v * b11
418
+ t26 += v * b12
419
+ t27 += v * b13
420
+ t28 += v * b14
421
+ t29 += v * b15
422
+ v = a[15]
423
+ t15 += v * b0
424
+ t16 += v * b1
425
+ t17 += v * b2
426
+ t18 += v * b3
427
+ t19 += v * b4
428
+ t20 += v * b5
429
+ t21 += v * b6
430
+ t22 += v * b7
431
+ t23 += v * b8
432
+ t24 += v * b9
433
+ t25 += v * b10
434
+ t26 += v * b11
435
+ t27 += v * b12
436
+ t28 += v * b13
437
+ t29 += v * b14
438
+ t30 += v * b15
439
+
440
+ t0 += 38 * t16
441
+ t1 += 38 * t17
442
+ t2 += 38 * t18
443
+ t3 += 38 * t19
444
+ t4 += 38 * t20
445
+ t5 += 38 * t21
446
+ t6 += 38 * t22
447
+ t7 += 38 * t23
448
+ t8 += 38 * t24
449
+ t9 += 38 * t25
450
+ t10 += 38 * t26
451
+ t11 += 38 * t27
452
+ t12 += 38 * t28
453
+ t13 += 38 * t29
454
+ t14 += 38 * t30
455
+ # t15 left as is
456
+
457
+ # first car
458
+ c = 1
459
+ v = t0 + c + 65_535
460
+ c = (v.to_f / 65_536).floor
461
+ t0 = v - c * 65_536
462
+ v = t1 + c + 65_535
463
+ c = (v.to_f / 65_536).floor
464
+ t1 = v - c * 65_536
465
+ v = t2 + c + 65_535
466
+ c = (v.to_f / 65_536).floor
467
+ t2 = v - c * 65_536
468
+ v = t3 + c + 65_535
469
+ c = (v.to_f / 65_536).floor
470
+ t3 = v - c * 65_536
471
+ v = t4 + c + 65_535
472
+ c = (v.to_f / 65_536).floor
473
+ t4 = v - c * 65_536
474
+ v = t5 + c + 65_535
475
+ c = (v.to_f / 65_536).floor
476
+ t5 = v - c * 65_536
477
+ v = t6 + c + 65_535
478
+ c = (v.to_f / 65_536).floor
479
+ t6 = v - c * 65_536
480
+ v = t7 + c + 65_535
481
+ c = (v.to_f / 65_536).floor
482
+ t7 = v - c * 65_536
483
+ v = t8 + c + 65_535
484
+ c = (v.to_f / 65_536).floor
485
+ t8 = v - c * 65_536
486
+ v = t9 + c + 65_535
487
+ c = (v.to_f / 65_536).floor
488
+ t9 = v - c * 65_536
489
+ v = t10 + c + 65_535
490
+ c = (v.to_f / 65_536).floor
491
+ t10 = v - c * 65_536
492
+ v = t11 + c + 65_535
493
+ c = (v.to_f / 65_536).floor
494
+ t11 = v - c * 65_536
495
+ v = t12 + c + 65_535
496
+ c = (v.to_f / 65_536).floor
497
+ t12 = v - c * 65_536
498
+ v = t13 + c + 65_535
499
+ c = (v.to_f / 65_536).floor
500
+ t13 = v - c * 65_536
501
+ v = t14 + c + 65_535
502
+ c = (v.to_f / 65_536).floor
503
+ t14 = v - c * 65_536
504
+ v = t15 + c + 65_535
505
+ c = (v.to_f / 65_536).floor
506
+ t15 = v - c * 65_536
507
+
508
+ t0 += c - 1 + 37 * (c - 1)
509
+
510
+ # second car
511
+ c = 1
512
+ v = t0 + c + 65_535
513
+ c = (v.to_f / 65_536).floor
514
+ t0 = v - c * 65_536
515
+ v = t1 + c + 65_535
516
+ c = (v.to_f / 65_536).floor
517
+ t1 = v - c * 65_536
518
+ v = t2 + c + 65_535
519
+ c = (v.to_f / 65_536).floor
520
+ t2 = v - c * 65_536
521
+ v = t3 + c + 65_535
522
+ c = (v.to_f / 65_536).floor
523
+ t3 = v - c * 65_536
524
+ v = t4 + c + 65_535
525
+ c = (v.to_f / 65_536).floor
526
+ t4 = v - c * 65_536
527
+ v = t5 + c + 65_535
528
+ c = (v.to_f / 65_536).floor
529
+ t5 = v - c * 65_536
530
+ v = t6 + c + 65_535
531
+ c = (v.to_f / 65_536).floor
532
+ t6 = v - c * 65_536
533
+ v = t7 + c + 65_535
534
+ c = (v.to_f / 65_536).floor
535
+ t7 = v - c * 65_536
536
+ v = t8 + c + 65_535
537
+ c = (v.to_f / 65_536).floor
538
+ t8 = v - c * 65_536
539
+ v = t9 + c + 65_535
540
+ c = (v.to_f / 65_536).floor
541
+ t9 = v - c * 65_536
542
+ v = t10 + c + 65_535
543
+ c = (v.to_f / 65_536).floor
544
+ t10 = v - c * 65_536
545
+ v = t11 + c + 65_535
546
+ c = (v.to_f / 65_536).floor
547
+ t11 = v - c * 65_536
548
+ v = t12 + c + 65_535
549
+ c = (v.to_f / 65_536).floor
550
+ t12 = v - c * 65_536
551
+ v = t13 + c + 65_535
552
+ c = (v.to_f / 65_536).floor
553
+ t13 = v - c * 65_536
554
+ v = t14 + c + 65_535
555
+ c = (v.to_f / 65_536).floor
556
+ t14 = v - c * 65_536
557
+ v = t15 + c + 65_535
558
+ c = (v.to_f / 65_536).floor
559
+ t15 = v - c * 65_536
560
+
561
+ t0 += c - 1 + 37 * (c - 1)
562
+
563
+ o[0] = t0
564
+ o[1] = t1
565
+ o[2] = t2
566
+ o[3] = t3
567
+ o[4] = t4
568
+ o[5] = t5
569
+ o[6] = t6
570
+ o[7] = t7
571
+ o[8] = t8
572
+ o[9] = t9
573
+ o[10] = t10
574
+ o[11] = t11
575
+ o[12] = t12
576
+ o[13] = t13
577
+ o[14] = t14
578
+ o[15] = t15
579
+ o
580
+ end
581
+
582
+ def self.S(o, a)
583
+ M(o, a, a)
584
+ end
585
+
586
+ def self.inv25519(o, i)
587
+ c = gf
588
+ (0..15).each { |a| c[a] = i[a] }
589
+ (0..253).to_a.reverse.each do |a|
590
+ c = S(c, c)
591
+ c = M(c, c, i) if a != 2 && a != 4
592
+ end
593
+ (0..15).each { |a| o[a] = c[a] }
594
+ o
595
+ end
596
+
597
+ @K = [
598
+ 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
599
+ 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
600
+ 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
601
+ 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
602
+ 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
603
+ 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
604
+ 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
605
+ 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
606
+ 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
607
+ 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
608
+ 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
609
+ 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
610
+ 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
611
+ 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
612
+ 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
613
+ 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
614
+ 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
615
+ 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
616
+ 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
617
+ 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
618
+ 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
619
+ 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
620
+ 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
621
+ 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
622
+ 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
623
+ 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
624
+ 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
625
+ 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
626
+ 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
627
+ 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
628
+ 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
629
+ 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
630
+ 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
631
+ 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
632
+ 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
633
+ 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
634
+ 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
635
+ 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
636
+ 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
637
+ 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
638
+ ]
639
+
640
+ def self.crypto_hashblocks_wh_wl(m, pos)
641
+ wh = []
642
+ wl = []
643
+ (0..15).each do |i|
644
+ j = 8 * i + pos
645
+ mj = (0..7).to_a.map { |n| Int32.new(m[j + n].to_i) }
646
+ wh[i] = (mj[0] << 24) | (mj[1] << 16) | (mj[2] << 8) | mj[3]
647
+ wl[i] = (mj[4] << 24) | (mj[5] << 16) | (mj[6] << 8) | mj[7]
648
+ end
649
+ [wh, wl]
650
+ end
651
+
652
+ def self.crypto_hashblocks_hl(hh, hl, m, n)
653
+ hh.map! { |v| Int32.new(v) }
654
+ hl.map! { |v| Int32.new(v) }
655
+ m.map! { |v| Int32.new(v) }
656
+
657
+ ah = hh.dup
658
+ al = hl.dup
659
+
660
+ pos = 0
661
+ while n >= 128
662
+
663
+ wh, wl = crypto_hashblocks_wh_wl(m, pos)
664
+
665
+ (0..79).each do |i|
666
+ bh = ah.dup
667
+ bl = al.dup
668
+
669
+ # add
670
+ h = ah[7].dup
671
+ l = al[7].dup
672
+
673
+ a = Int32.new(l & 0xffff)
674
+ b = Int32.new(l).r_shift_pos(16)
675
+ c = Int32.new(h & 0xffff)
676
+ d = Int32.new(h).r_shift_pos(16)
677
+
678
+ # Sigma1
679
+ h = Int32.new((ah[4].r_shift_pos(14) | (al[4] << (32 - 14))) ^ (ah[4].r_shift_pos(18) | (al[4] << (32 - 18))) ^ (al[4].r_shift_pos((41 - 32)) | (ah[4] << (32 - (41 - 32)))))
680
+ l = Int32.new((al[4].r_shift_pos(14) | (ah[4] << (32 - 14))) ^ (al[4].r_shift_pos(18) | (ah[4] << (32 - 18))) ^ (ah[4].r_shift_pos((41 - 32)) | (al[4] << (32 - (41 - 32)))))
681
+
682
+ a += Int32.new(l & 0xffff)
683
+ b += Int32.new(l).r_shift_pos(16)
684
+ c += Int32.new(h & 0xffff)
685
+ d += Int32.new(h).r_shift_pos(16)
686
+
687
+ # Ch
688
+ h = (ah[4] & ah[5]) ^ (~ah[4] & ah[6])
689
+ l = (al[4] & al[5]) ^ (~al[4] & al[6])
690
+
691
+ a += l & 0xffff
692
+ b += l.r_shift_pos(16)
693
+ c += h & 0xffff
694
+ d += h.r_shift_pos(16)
695
+
696
+ # K
697
+ h = Int32.new(@K[i * 2])
698
+ l = Int32.new(@K[i * 2 + 1])
699
+
700
+ a += l & 0xffff
701
+ b += l.r_shift_pos(16)
702
+ c += h & 0xffff
703
+ d += h.r_shift_pos(16)
704
+
705
+ # w
706
+ h = wh[i % 16]
707
+ l = wl[i % 16]
708
+
709
+ a += l & 0xffff
710
+ b += l.r_shift_pos(16)
711
+ c += h & 0xffff
712
+ d += h.r_shift_pos(16)
713
+
714
+ b += a.r_shift_pos(16)
715
+ c += b.r_shift_pos(16)
716
+ d += c.r_shift_pos(16)
717
+
718
+ th = c & 0xffff | d << 16
719
+ tl = a & 0xffff | b << 16
720
+
721
+ # add
722
+ h = th
723
+ l = tl
724
+
725
+ a = l & 0xffff
726
+ b = l.r_shift_pos(16)
727
+ c = h & 0xffff
728
+ d = h.r_shift_pos(16)
729
+
730
+ # Sigma0
731
+ h = (ah[0].r_shift_pos(28) | (al[0] << (32 - 28))) ^ (al[0].r_shift_pos((34 - 32)) | (ah[0] << (32 - (34 - 32)))) ^ (al[0].r_shift_pos((39 - 32)) | (ah[0] << (32 - (39 - 32))))
732
+ l = (al[0].r_shift_pos(28) | (ah[0] << (32 - 28))) ^ (ah[0].r_shift_pos((34 - 32)) | (al[0] << (32 - (34 - 32)))) ^ (ah[0].r_shift_pos((39 - 32)) | (al[0] << (32 - (39 - 32))))
733
+
734
+ a += l & 0xffff
735
+ b += l.r_shift_pos(16)
736
+ c += h & 0xffff
737
+ d += h.r_shift_pos(16)
738
+
739
+ # Maj
740
+ h = (ah[0] & ah[1]) ^ (ah[0] & ah[2]) ^ (ah[1] & ah[2])
741
+ l = (al[0] & al[1]) ^ (al[0] & al[2]) ^ (al[1] & al[2])
742
+
743
+ a += l & 0xffff
744
+ b += l.r_shift_pos(16)
745
+ c += h & 0xffff
746
+ d += h.r_shift_pos(16)
747
+
748
+ b += a.r_shift_pos(16)
749
+ c += b.r_shift_pos(16)
750
+ d += c.r_shift_pos(16)
751
+
752
+ bh[7] = (c & 0xffff) | (d << 16)
753
+ bl[7] = (a & 0xffff) | (b << 16)
754
+
755
+ # add
756
+ h = bh[3]
757
+ l = bl[3]
758
+
759
+ a = l & 0xffff
760
+ b = l.r_shift_pos(16)
761
+ c = h & 0xffff
762
+ d = h.r_shift_pos(16)
763
+
764
+ h = th
765
+ l = tl
766
+
767
+ a += l & 0xffff
768
+ b += l.r_shift_pos(16)
769
+ c += h & 0xffff
770
+ d += h.r_shift_pos(16)
771
+
772
+ b += a.r_shift_pos(16)
773
+ c += b.r_shift_pos(16)
774
+ d += c.r_shift_pos(16)
775
+
776
+ bh[3] = (c & 0xffff) | (d << 16)
777
+ bl[3] = (a & 0xffff) | (b << 16)
778
+
779
+ ah[0] = bh[7]
780
+ ah[1..-1] = bh[0..-2]
781
+
782
+ al[0] = bl[7]
783
+ al[1..-1] = bl[0..-2]
784
+
785
+ next unless i % 16 == 15
786
+ (0..15).each do |j|
787
+ # add
788
+ h = wh[j]
789
+ l = wl[j]
790
+
791
+ a = Int32.new(l & 0xffff)
792
+ b = Int32.new(l).r_shift_pos(16)
793
+ c = Int32.new(h & 0xffff)
794
+ d = Int32.new(h).r_shift_pos(16)
795
+
796
+ h = wh[(j + 9) % 16]
797
+ l = wl[(j + 9) % 16]
798
+
799
+ a += l & 0xffff
800
+ b += l.r_shift_pos(16)
801
+ c += h & 0xffff
802
+ d += h.r_shift_pos(16)
803
+
804
+ # sigma0
805
+ th = wh[(j + 1) % 16]
806
+ tl = wl[(j + 1) % 16]
807
+ h = (th.r_shift_pos(1) | (tl << (32 - 1))) ^ (th.r_shift_pos(8) | (tl << (32 - 8))) ^ th.r_shift_pos(7)
808
+ l = (tl.r_shift_pos(1) | (th << (32 - 1))) ^ (tl.r_shift_pos(8) | (th << (32 - 8))) ^ (tl.r_shift_pos(7) | (th << (32 - 7)))
809
+
810
+ a += l & 0xffff
811
+ b += l.r_shift_pos(16)
812
+ c += h & 0xffff
813
+ d += h.r_shift_pos(16)
814
+
815
+ # sigma1
816
+ th = wh[(j + 14) % 16]
817
+ tl = wl[(j + 14) % 16]
818
+ h = (th.r_shift_pos(19) | (tl << (32 - 19))) ^ (tl.r_shift_pos((61 - 32)) | (th << (32 - (61 - 32)))) ^ th.r_shift_pos(6)
819
+
820
+ l = (tl.r_shift_pos(19) | (th << (32 - 19))) ^ (th.r_shift_pos((61 - 32)) | (tl << (32 - (61 - 32)))) ^ (tl.r_shift_pos(6) | (th << (32 - 6)))
821
+
822
+ a += l & 0xffff
823
+ b += l.r_shift_pos(16)
824
+ c += h & 0xffff
825
+ d += h.r_shift_pos(16)
826
+
827
+ b += a.r_shift_pos(16)
828
+ c += b.r_shift_pos(16)
829
+ d += c.r_shift_pos(16)
830
+
831
+ wh[j] = (c & 0xffff) | (d << 16)
832
+ wl[j] = (a & 0xffff) | (b << 16)
833
+ end
834
+ end
835
+
836
+ hh, hl, ah, al = hh_hl_update(hh, hl, ah, al)
837
+
838
+ pos += 128
839
+ n -= 128
840
+ end
841
+ [hh, hl, m, n]
842
+ end
843
+
844
+ def self.hh_hl_update(hh, hl, ah, al)
845
+ hh.map! { |v| Int32.new(v) }
846
+ hl.map! { |v| Int32.new(v) }
847
+ ah.map! { |v| Int32.new(v) }
848
+ al.map! { |v| Int32.new(v) }
849
+ (0..7).each do |n|
850
+ h = ah[n]
851
+ l = al[n]
852
+
853
+ a = l & 0xffff
854
+ b = l.r_shift_pos(16)
855
+ c = h & 0xffff
856
+ d = h.r_shift_pos(16)
857
+
858
+ h = hh[n]
859
+ l = hl[n]
860
+
861
+ a += l & 0xffff
862
+ b += l.r_shift_pos(16)
863
+ c += h & 0xffff
864
+ d += h.r_shift_pos(16)
865
+
866
+ b += a.r_shift_pos(16)
867
+ c += b.r_shift_pos(16)
868
+ d += c.r_shift_pos(16)
869
+
870
+ hh[n] = ah[n] = (c & 0xffff) | (d << 16)
871
+ hl[n] = al[n] = (a & 0xffff) | (b << 16)
872
+ end
873
+ [hh, hl, ah, al]
874
+ end
875
+
876
+ def self.crypto_hash(out, m, n)
877
+ hh = Array.new(8, 0)
878
+ hl = Array.new(8, 0)
879
+ x = Array.new(256, 0)
880
+ b = n
881
+
882
+ hh[0] = 0x6a09e667
883
+ hh[1] = 0xbb67ae85
884
+ hh[2] = 0x3c6ef372
885
+ hh[3] = 0xa54ff53a
886
+ hh[4] = 0x510e527f
887
+ hh[5] = 0x9b05688c
888
+ hh[6] = 0x1f83d9ab
889
+ hh[7] = 0x5be0cd19
890
+
891
+ hl[0] = 0xf3bcc908
892
+ hl[1] = 0x84caa73b
893
+ hl[2] = 0xfe94f82b
894
+ hl[3] = 0x5f1d36f1
895
+ hl[4] = 0xade682d1
896
+ hl[5] = 0x2b3e6c1f
897
+ hl[6] = 0xfb41bd6b
898
+ hl[7] = 0x137e2179
899
+
900
+ hh, hl, m, n = crypto_hashblocks_hl(hh, hl, m, n)
901
+ n %= 128
902
+
903
+ (0..n - 1).each { |i| x[i] = m[b - n + i] }
904
+ x[n] = 128
905
+
906
+ n = 256 - 128 * (n < 112 ? 1 : 0)
907
+ x[n - 9] = 0
908
+ x = ts64(x, n - 8, (b / 0x20000000) | 0, b << 3)
909
+
910
+ hh, hl, m, n = crypto_hashblocks_hl(hh, hl, x, n)
911
+
912
+ (0..7).each { |i| out = ts64(out, 8 * i, hh[i], hl[i]) }
913
+ out.map { |v| Int32.new(v) }
914
+ end
915
+
916
+ def self.add(p, q)
917
+ a = gf
918
+ b = gf
919
+ c = gf
920
+ d = gf
921
+ e = gf
922
+ f = gf
923
+ g = gf
924
+ h = gf
925
+ t = gf
926
+
927
+ a = Z(a, p[1], p[0])
928
+ t = Z(t, q[1], q[0])
929
+ a = M(a, a, t)
930
+ b = A(b, p[0], p[1])
931
+ t = A(t, q[0], q[1])
932
+ b = M(b, b, t)
933
+ c = M(c, p[3], q[3])
934
+ c = M(c, c, @D2)
935
+ d = M(d, p[2], q[2])
936
+ d = A(d, d, d)
937
+ e = Z(e, b, a)
938
+ f = Z(f, d, c)
939
+ g = A(g, d, c)
940
+ h = A(h, b, a)
941
+
942
+ p[0] = M(p[0], e, f)
943
+ p[1] = M(p[1], h, g)
944
+ p[2] = M(p[2], g, f)
945
+ p[3] = M(p[3], e, h)
946
+ p
947
+ end
948
+
949
+ def self.cswap(p, q, b)
950
+ (0..3).each do |i|
951
+ p[i], q[i] = sel25519(p[i], q[i], b)
952
+ end
953
+ [p, q]
954
+ end
955
+
956
+ def self.pack(r, p)
957
+ tx = gf
958
+ ty = gf
959
+ zi = gf
960
+ zi = inv25519(zi, p[2])
961
+ tx = M(tx, p[0], zi)
962
+
963
+ ty = M(ty, p[1], zi)
964
+ r = pack25519(r, ty)
965
+
966
+ r[31] ^= par25519(tx) << 7
967
+ r
968
+ end
969
+
970
+ def self.scalarmult(p, q, s)
971
+ p[0] = set25519(p[0], @gf0)
972
+ p[1] = set25519(p[1], @gf1)
973
+ p[2] = set25519(p[2], @gf1)
974
+ p[3] = set25519(p[3], @gf0)
975
+ (0..255).to_a.reverse.each do |i|
976
+ b = (s[(i / 8) | 0] >> (i & 7)) & 1 # >>
977
+ p, q = cswap(p, q, b)
978
+ q = add(q, p)
979
+ p = add(p, p)
980
+ p, q = cswap(p, q, b)
981
+ end
982
+ [p, q, s]
983
+ end
984
+
985
+ def self.scalarbase(p, s)
986
+ q = [gf, gf, gf, gf]
987
+ q[0] = set25519(q[0], @X)
988
+ q[1] = set25519(q[1], @Y)
989
+ q[2] = set25519(q[2], @gf1)
990
+ q[3] = M(q[3], @X, @Y)
991
+ p, q, s = scalarmult(p, q, s)
992
+ [p, s]
993
+ end
994
+
995
+ @L = [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]
996
+
997
+ def self.modL(r, x)
998
+ r.map! { |v| Int32.new(v) }
999
+ (32..63).to_a.reverse.each do |i|
1000
+ carry = 0
1001
+ k = i - 13
1002
+ jtemp = 0
1003
+ (i - 32..k).to_a.each do |j|
1004
+ jtemp = j + 1
1005
+ x[j] = x[j].to_i + carry - 16 * x[i].to_i * @L[j - (i - 32)]
1006
+ carry = (x[j] + 128) >> 8 # >>
1007
+ x[j] -= carry * 256
1008
+ end
1009
+ x[jtemp] += carry
1010
+ x[i] = 0
1011
+ end
1012
+ carry = 0
1013
+ (0..31).each do |j|
1014
+ x[j] += carry - (x[31].to_i >> 4) * @L[j] # >>
1015
+ carry = x[j] >> 8 # >>
1016
+ x[j] &= 255
1017
+ end
1018
+ (0..31).each { |j| x[j] -= carry * @L[j] }
1019
+ (0..31).each do |i|
1020
+ x[i + 1] += x[i].to_i >> 8 # >>
1021
+ r[i] = x[i] & 255
1022
+ end
1023
+ r
1024
+ end
1025
+
1026
+ def self.reduce(r)
1027
+ x = []
1028
+ (0..63).each { |i| x[i] = r[i] }
1029
+ (0..63).each { |i| r[i] = 0 }
1030
+ r = modL(r, x)
1031
+ r
1032
+ end
1033
+
1034
+ # Like crypto_sign, but uses secret key directly in hash.
1035
+ def self.crypto_sign_direct(sm, m, n, sk)
1036
+ h = []
1037
+ r = []
1038
+ x = []
1039
+ p = [gf, gf, gf, gf]
1040
+
1041
+ (0..n - 1).each { |i| sm[64 + i] = m[i] }
1042
+ (0..31).each { |i| sm[32 + i] = sk[i] }
1043
+
1044
+ r = crypto_hash(r, sm[32..-1], n + 32)
1045
+ r = reduce(r)
1046
+ p, r = scalarbase(p, r)
1047
+ sm = pack(sm, p)
1048
+
1049
+ (0..31).each { |i| sm[i + 32] = sk[32 + i] }
1050
+ h = crypto_hash(h, sm, n + 64)
1051
+ h = reduce(h)
1052
+
1053
+ (0..63).each { |i| x[i] = 0 }
1054
+ (0..31).each { |i| x[i] = r[i] }
1055
+ (0..31).each do |i|
1056
+ (0..31).each do |j|
1057
+ x[i + j] += (h[i] * sk[j]).to_i
1058
+ end
1059
+ end
1060
+
1061
+ sm[32..-1] = modL(sm[32..-1], x)
1062
+
1063
+ [sm, m, n + 64, sk]
1064
+ end
1065
+
1066
+ # Note: sm must be n+128.
1067
+ def self.crypto_sign_direct_rnd(sm, m, n, sk, rnd)
1068
+ h = []
1069
+ r = []
1070
+ x = []
1071
+ p = [gf, gf, gf, gf]
1072
+
1073
+ # Hash separation.
1074
+ sm[0] = 0xfe
1075
+ (0..31).each { |i| sm[i] = 0xff }
1076
+
1077
+ # Secret key.
1078
+ (0..31).each { |i| sm[32 + i] = sk[i] }
1079
+
1080
+ # Message.
1081
+ (0..n - 1).each { |i| sm[64 + i] = m[i] }
1082
+
1083
+ # Random suffix.
1084
+ (0..63).each { |i| sm[n + 64 + i] = rnd[i] }
1085
+
1086
+ r = crypto_hash(r, sm, n + 128)
1087
+ r = reduce(r)
1088
+ p, r = scalarbase(p, r)
1089
+ sm = pack(sm, p)
1090
+
1091
+ (0..31).each { |i| sm[i + 32] = sk[32 + i] }
1092
+ h = crypto_hash(h, sm, n + 64)
1093
+ h = reduce(h)
1094
+
1095
+ # Wipe out random suffix.
1096
+ (0..63).each { |i| sm[n + 64 + i] = 0 }
1097
+
1098
+ (0..63).each { |i| x[i] = 0 }
1099
+ (0..31).each { |i| x[i] = r[i] }
1100
+
1101
+ (0..31).each do |i|
1102
+ (0..31).each do |j|
1103
+ x[i + j] += h[i] * sk[j]
1104
+ end
1105
+ end
1106
+
1107
+ sm[32..n + 63] = modL(sm[32..n + 63], x)
1108
+
1109
+ [sm, m, n + 64, sk, rnd]
1110
+ end
1111
+
1112
+ def self.curve25519_sign(sm, m, n, sk, opt_rnd)
1113
+ # If opt_rnd is provided, sm must have n + 128,
1114
+ # otherwise it must have n + 64 bytes.
1115
+
1116
+ # Convert Curve25519 secret key into Ed25519 secret key (includes pub key).
1117
+ edsk = Array.new(64, 0)
1118
+ p = [gf, gf, gf, gf]
1119
+
1120
+ (0..31).each { |i| edsk[i] = sk[i] }
1121
+ # Ensure private key is in the correct format.
1122
+ edsk[0] &= 248
1123
+ edsk[31] &= 127
1124
+ edsk[31] |= 64
1125
+
1126
+ p, edsk = scalarbase(p, edsk)
1127
+ edsk[32..-1] = pack(edsk[32..-1], p)
1128
+
1129
+ # Remember sign bit.
1130
+ signBit = edsk[63] & 128
1131
+
1132
+ if opt_rnd
1133
+ sm, m, n, edsk, opt_rnd = crypto_sign_direct_rnd(sm, m, n, edsk, opt_rnd)
1134
+ else
1135
+ sm, m, smlen, edsk = crypto_sign_direct(sm, m, n, edsk)
1136
+ end
1137
+
1138
+ # Copy sign bit from public key into signature.
1139
+ sm[63] |= signBit
1140
+ sm
1141
+ end
1142
+
1143
+ def self.sign(secret_key, msg, opt_random = SecureRandom.random_bytes(64).bytes)
1144
+ raise 'wrong secret key length' if secret_key.length != 32
1145
+ if opt_random
1146
+ raise 'wrong random data length' if opt_random.length != 64
1147
+ end
1148
+ buf = []
1149
+ buf = curve25519_sign(buf, msg, msg.length, secret_key, opt_random)
1150
+ signature = []
1151
+ (0..63).each { |i| signature[i] = buf[i] }
1152
+ signature.map(&:to_i)
1153
+ end
1154
+ end