waves_ruby_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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