nis-ruby 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/README.md +12 -9
  4. data/examples/transactions/importance_transfer.rb +1 -4
  5. data/examples/transactions/mosaic_definition_creation.rb +1 -4
  6. data/examples/transactions/mosaic_supply_change.rb +1 -4
  7. data/examples/transactions/multisig.rb +1 -6
  8. data/examples/transactions/multisig_add_cosignatory.rb +1 -4
  9. data/examples/transactions/multisig_aggregate_modification.rb +1 -4
  10. data/examples/transactions/multisig_signature.rb +2 -5
  11. data/examples/transactions/provision_namespace.rb +1 -4
  12. data/examples/transactions/transfer.rb +1 -4
  13. data/examples/transactions/transfer_remote.rb +19 -0
  14. data/lib/nis/endpoint/account/generate.rb +1 -1
  15. data/lib/nis/endpoint/account/get.rb +4 -4
  16. data/lib/nis/endpoint/account/harvests.rb +1 -1
  17. data/lib/nis/endpoint/account/historical.rb +1 -1
  18. data/lib/nis/endpoint/account/importances.rb +1 -1
  19. data/lib/nis/endpoint/account/lock.rb +1 -1
  20. data/lib/nis/endpoint/account/mosaic.rb +2 -2
  21. data/lib/nis/endpoint/account/namespace.rb +1 -1
  22. data/lib/nis/endpoint/account/status.rb +1 -1
  23. data/lib/nis/endpoint/account/transfers.rb +3 -3
  24. data/lib/nis/endpoint/account/unconfirmed_transactions.rb +1 -1
  25. data/lib/nis/endpoint/account/unlock.rb +1 -1
  26. data/lib/nis/endpoint/account/unlocked.rb +1 -1
  27. data/lib/nis/endpoint/block/at.rb +1 -1
  28. data/lib/nis/endpoint/block/get.rb +1 -1
  29. data/lib/nis/endpoint/chain/height.rb +1 -1
  30. data/lib/nis/endpoint/chain/last_block.rb +1 -1
  31. data/lib/nis/endpoint/chain/score.rb +1 -1
  32. data/lib/nis/endpoint/debug/connections.rb +3 -3
  33. data/lib/nis/endpoint/debug/time_synchronization.rb +1 -1
  34. data/lib/nis/endpoint/heartbeat.rb +1 -1
  35. data/lib/nis/endpoint/local/account/transfers.rb +3 -3
  36. data/lib/nis/endpoint/local/chain.rb +1 -1
  37. data/lib/nis/endpoint/namespace.rb +1 -1
  38. data/lib/nis/endpoint/namespace/mosaic.rb +1 -1
  39. data/lib/nis/endpoint/namespace/root.rb +1 -1
  40. data/lib/nis/endpoint/node/active_peers.rb +1 -1
  41. data/lib/nis/endpoint/node/boot.rb +1 -1
  42. data/lib/nis/endpoint/node/experiences.rb +1 -1
  43. data/lib/nis/endpoint/node/extended_info.rb +1 -1
  44. data/lib/nis/endpoint/node/info.rb +1 -1
  45. data/lib/nis/endpoint/node/peer_list.rb +3 -3
  46. data/lib/nis/endpoint/status.rb +1 -1
  47. data/lib/nis/endpoint/transaction/announce.rb +4 -4
  48. data/lib/nis/endpoint/transaction/prepareAnnounce.rb +4 -4
  49. data/lib/nis/keypair.rb +13 -3
  50. data/lib/nis/request/announce.rb +47 -2
  51. data/lib/nis/request/prepare_announce.rb +1 -1
  52. data/lib/nis/struct/account_importance_view_model.rb +1 -1
  53. data/lib/nis/struct/account_info.rb +1 -1
  54. data/lib/nis/struct/account_meta_data.rb +1 -1
  55. data/lib/nis/struct/account_meta_data_pair.rb +1 -1
  56. data/lib/nis/struct/account_private_key_transactions_page.rb +1 -1
  57. data/lib/nis/struct/application_meta_data.rb +1 -1
  58. data/lib/nis/struct/audit_collection.rb +1 -1
  59. data/lib/nis/struct/audit_info.rb +1 -1
  60. data/lib/nis/struct/block.rb +1 -1
  61. data/lib/nis/struct/block_height.rb +1 -1
  62. data/lib/nis/struct/block_score.rb +1 -1
  63. data/lib/nis/struct/boot_node_request.rb +1 -1
  64. data/lib/nis/struct/error.rb +1 -1
  65. data/lib/nis/struct/explorer_block_view_model.rb +1 -1
  66. data/lib/nis/struct/explorer_transfer_view_model.rb +1 -1
  67. data/lib/nis/struct/explorer_view_model_transaction.rb +1 -1
  68. data/lib/nis/struct/extended_node_experience_pair.rb +1 -1
  69. data/lib/nis/struct/harvest_info.rb +1 -1
  70. data/lib/nis/struct/key_pair_view_model.rb +1 -1
  71. data/lib/nis/struct/mosaic.rb +1 -1
  72. data/lib/nis/struct/mosaic_definition.rb +1 -1
  73. data/lib/nis/struct/mosaic_definition_meta_data.rb +1 -1
  74. data/lib/nis/struct/mosaic_definition_meta_data_pair.rb +1 -1
  75. data/lib/nis/struct/mosaic_id.rb +1 -1
  76. data/lib/nis/struct/mosaic_levy.rb +1 -1
  77. data/lib/nis/struct/mosaic_properties.rb +1 -1
  78. data/lib/nis/struct/multisig_cosignatory_modification.rb +1 -1
  79. data/lib/nis/struct/namespace.rb +1 -1
  80. data/lib/nis/struct/namespace_meta_data.rb +1 -1
  81. data/lib/nis/struct/namespace_meta_data_pair.rb +1 -1
  82. data/lib/nis/struct/nem_announce_result.rb +1 -1
  83. data/lib/nis/struct/nem_async_timer_visitor.rb +1 -1
  84. data/lib/nis/struct/nem_request_result.rb +1 -1
  85. data/lib/nis/struct/nis_node_info.rb +1 -1
  86. data/lib/nis/struct/node.rb +1 -1
  87. data/lib/nis/struct/node_collection.rb +1 -1
  88. data/lib/nis/struct/node_experience.rb +1 -1
  89. data/lib/nis/struct/request_announce.rb +1 -1
  90. data/lib/nis/struct/request_prepare_announce.rb +1 -1
  91. data/lib/nis/struct/time_synchronization_result.rb +1 -1
  92. data/lib/nis/struct/transaction.rb +4 -4
  93. data/lib/nis/struct/transaction_meta_data.rb +1 -1
  94. data/lib/nis/struct/transaction_meta_data_pair.rb +1 -1
  95. data/lib/nis/struct/unconfirmed_transaction_meta_data.rb +1 -1
  96. data/lib/nis/struct/unconfirmed_transaction_meta_data_pair.rb +1 -1
  97. data/lib/nis/transaction/importance_transfer.rb +1 -1
  98. data/lib/nis/transaction/mosaic_definition_creation.rb +1 -1
  99. data/lib/nis/transaction/mosaic_supply_change.rb +1 -1
  100. data/lib/nis/transaction/multisig.rb +1 -1
  101. data/lib/nis/transaction/multisig_aggregate_modification.rb +1 -1
  102. data/lib/nis/transaction/multisig_signature.rb +1 -1
  103. data/lib/nis/transaction/provision_namespace.rb +1 -1
  104. data/lib/nis/transaction/transfer.rb +4 -4
  105. data/lib/nis/unit/address.rb +19 -0
  106. data/lib/nis/util/convert.rb +125 -0
  107. data/lib/nis/util/ed25519.rb +263 -0
  108. data/lib/nis/util/serializer.rb +273 -0
  109. data/lib/nis/version.rb +1 -1
  110. data/nis.gemspec +1 -1
  111. metadata +9 -5
@@ -8,7 +8,7 @@ class Nis::Transaction
8
8
  # @attr [Integer] version
9
9
  # @attr [String] signer
10
10
  # @attr [String] signature
11
- # @see http://bob.nem.ninja/docs/#multisigAggregateModificationTransaction
11
+ # @see https://nemproject.github.io/#multisigAggregateModificationTransaction
12
12
  class MultisigAggregateModification
13
13
  include Nis::Mixin::Struct
14
14
 
@@ -8,7 +8,7 @@ class Nis::Transaction
8
8
  # @attr [Integer] version
9
9
  # @attr [String] signer
10
10
  # @attr [String] signature
11
- # @see http://bob.nem.ninja/docs/#multisigSignatureTransaction
11
+ # @see https://nemproject.github.io/#multisigSignatureTransaction
12
12
  class MultisigSignature
13
13
  include Nis::Mixin::Struct
14
14
 
@@ -11,7 +11,7 @@ class Nis::Transaction
11
11
  # @attr [String] signer
12
12
  # @attr [String] signature
13
13
  # @attr [Symbol] network
14
- # @see http://bob.nem.ninja/docs/#provisionNamespaceTransaction
14
+ # @see https://nemproject.github.io/#provisionNamespaceTransaction
15
15
  class ProvisionNamespace
16
16
  include Nis::Mixin::Struct
17
17
 
@@ -10,10 +10,10 @@ class Nis::Transaction
10
10
  # @attr [Integer] version
11
11
  # @attr [String] signer
12
12
  # @attr [Symbol] network
13
- # @see http://bob.nem.ninja/docs/#transferTransaction
14
- # @see http://bob.nem.ninja/docs/#initiating-a-transfer-transaction
15
- # @see http://bob.nem.ninja/docs/#version-1-transfer-transactions
16
- # @see http://bob.nem.ninja/docs/#version-2-transfer-transactions
13
+ # @see https://nemproject.github.io/#transferTransaction
14
+ # @see https://nemproject.github.io/#initiating-a-transfer-transaction
15
+ # @see https://nemproject.github.io/#version-1-transfer-transactions
16
+ # @see https://nemproject.github.io/#version-2-transfer-transactions
17
17
  class Transfer
18
18
  include Nis::Mixin::Struct
19
19
 
@@ -1,3 +1,7 @@
1
+ require 'openssl'
2
+ require 'base32'
3
+ require 'digest/sha3'
4
+
1
5
  module Nis::Unit
2
6
  # @attr [String] value
3
7
  class Address
@@ -37,5 +41,20 @@ module Nis::Unit
37
41
  def ==(other)
38
42
  @value == other.value
39
43
  end
44
+
45
+ def self.from_public_key(public_key, network = :testnet)
46
+ bin_public_key = public_key.scan(/../).map(&:hex).pack('C*')
47
+ public_key_hash = Digest::SHA3.digest(bin_public_key, 256)
48
+ ripe = OpenSSL::Digest::RIPEMD160.digest(public_key_hash)
49
+
50
+ if network == :testnet
51
+ version = "\x98".force_encoding("ASCII-8BIT") + ripe
52
+ else
53
+ version = "\x68" + ripe
54
+ end
55
+
56
+ checksum = Digest::SHA3.digest(version, 256)[0...4]
57
+ self.new(Base32.encode(version + checksum))
58
+ end
40
59
  end
41
60
  end
@@ -0,0 +1,125 @@
1
+ module Nis::Util
2
+ module Convert
3
+ HEX_ENCODE_ARRAY = %w[0 1 2 3 4 5 6 7 8 9 a b c d e f]
4
+
5
+ def hexlify(obj)
6
+ obj.unpack('H*').first
7
+ end
8
+
9
+ def unhexlify(obj)
10
+ obj.scan(/../).map(&:hex).pack('C*')
11
+ end
12
+
13
+ # Reversed convertion of hex to Uint8Array
14
+ # @param [String] hex
15
+ # @return [Array]
16
+ def self.hex2ua_rev(hex)
17
+ hex2ua(hex).reverse
18
+ end
19
+
20
+ # Convert hex to Uint8Array
21
+ # @param [String] hex
22
+ # @return [Array]
23
+ def self.hex2ua(hex)
24
+ hex.scan(/../).map(&:hex)
25
+ end
26
+
27
+ # Convert an Uint8Array to hex
28
+ # @param [Uint8Array] ua - An Uint8Array
29
+ # @return [string]
30
+ def self.ua2hex(ua)
31
+ ua.map { |el| "#{HEX_ENCODE_ARRAY[el >> 4]}#{HEX_ENCODE_ARRAY[el & 0x0f]}" }.join
32
+ end
33
+
34
+ # Convert hex to string
35
+ # @param [String] hex
36
+ # @return [String]
37
+ def self.hex2a(hex)
38
+ hex.scan(/../).map { |el| el.to_i(16).chr }.join
39
+ end
40
+
41
+ # Convert UTF-8 to hex
42
+ # @param [string] str
43
+ # @return [string]
44
+ def self.utf8_to_hex(str)
45
+ rstr2utf8(str).each_byte.map { |b| b.to_s(16) }.join
46
+ end
47
+
48
+ # // Padding helper for above function
49
+ # let strlpad = function(str, pad, len) {
50
+ # while (str.length < len) {
51
+ # str = pad + str;
52
+ # }
53
+ # return str;
54
+ # }
55
+
56
+ # Convert an Uint8Array to WordArray
57
+ # @param [Uint8Array] ua - An Uint8Array
58
+ # @param [number] uaLength - The Uint8Array length
59
+ # @return [WordArray]
60
+ def self.ua2words(ua, ua_length)
61
+ ua[0, ua_length].each_slice(4).map do |chunk|
62
+ x = chunk[0] * 0x1000000 +
63
+ chunk[1] * 0x10000 +
64
+ chunk[2] * 0x100 +
65
+ chunk[3] * 0x1
66
+ x > 0x7fffffff ? x - 0x100000000 : x
67
+ end
68
+ end
69
+
70
+ # Convert a wordArray to Uint8Array
71
+ # @param [Uint8Array] destUa - A destination Uint8Array
72
+ # @param [WordArray] cryptowords - A wordArray
73
+ # @return [Uint8Array]
74
+ def self.words2ua(words)
75
+ words.map do |v|
76
+ temp = []
77
+ v += 0x100000000 if v < 0
78
+ temp[0] = (v >> 24)
79
+ temp[1] = (v >> 16) & 0xff
80
+ temp[2] = (v >> 8) & 0xff
81
+ temp[3] = (v) & 0xff
82
+ temp
83
+ end.flatten
84
+ end
85
+
86
+ # Converts a raw javascript string into a string of single byte characters using utf8 encoding.
87
+ # This makes it easier to perform other encoding operations on the string.
88
+ # @param [String] str
89
+ # @return [String]
90
+ def self.rstr2utf8(input)
91
+ input.unpack('U*').map do |c|
92
+ case
93
+ when c < 128
94
+ c
95
+ when 128 < c && c < 2048
96
+ [((c >> 6) | 192), ((c & 63) | 128)]
97
+ else
98
+ [((c >> 12) | 224), (((c >> 6) & 63) | 128), ((c & 63) | 128)]
99
+ end
100
+ end.flatten.map(&:chr).join
101
+ end
102
+
103
+ # Does the reverse of rstr2utf8.
104
+ def utf82rstr(input)
105
+ # let output = "", i = 0, c = 0, c1 = 0, c2 = 0, c3 = 0;
106
+ # while (i < input.length) {
107
+ # c = input.charCodeAt(i);
108
+ # if (c < 128) {
109
+ # output += String.fromCharCode(c);
110
+ # i++;
111
+ # } else if ((c > 191) && (c < 224)) {
112
+ # c2 = input.charCodeAt(i + 1);
113
+ # output += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
114
+ # i += 2;
115
+ # } else {
116
+ # c2 = input.charCodeAt(i + 1);
117
+ # c3 = input.charCodeAt(i + 2);
118
+ # output += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
119
+ # i += 3;
120
+ # }
121
+ # }
122
+ # return output;
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,263 @@
1
+ require 'openssl'
2
+ require 'digest/sha3'
3
+ require 'base32'
4
+
5
+ module Nis::Util
6
+ module Ed25519
7
+ class << self
8
+ def int2byte(i)
9
+ i.chr
10
+ end
11
+
12
+ def indexbytes(buf, i)
13
+ buf[i].ord
14
+ end
15
+
16
+ def intlist2bytes(l)
17
+ l.map {|c| c.chr }.join
18
+ end
19
+
20
+ # standard implement
21
+ def H(m)
22
+ OpenSSL::Digest::SHA512.digest(m)
23
+ end
24
+
25
+ def HH(m)
26
+ Digest::SHA3.digest(m)
27
+ end
28
+
29
+ def pow2(x, p)
30
+ # """== pow(x, 2**p, q)"""
31
+ while p > 0 do
32
+ x = x * x % $q
33
+ p -= 1
34
+ end
35
+ x
36
+ end
37
+
38
+ def inv(z)
39
+ # """$= z^{-1} \mod q$, for z != 0"""
40
+ # Adapted from curve25519_athlon.c in djb's Curve25519.
41
+ z2 = z * z % $q # 2
42
+ z9 = pow2(z2, 2) * z % $q # 9
43
+ z11 = z9 * z2 % $q # 11
44
+ z2_5_0 = (z11 * z11) % $q * z9 % $q # 31 == 2^5 - 2^0
45
+ z2_10_0 = pow2(z2_5_0, 5) * z2_5_0 % $q # 2^10 - 2^0
46
+ z2_20_0 = pow2(z2_10_0, 10) * z2_10_0 % $q # ...
47
+ z2_40_0 = pow2(z2_20_0, 20) * z2_20_0 % $q
48
+ z2_50_0 = pow2(z2_40_0, 10) * z2_10_0 % $q
49
+ z2_100_0 = pow2(z2_50_0, 50) * z2_50_0 % $q
50
+ z2_200_0 = pow2(z2_100_0, 100) * z2_100_0 % $q
51
+ z2_250_0 = pow2(z2_200_0, 50) * z2_50_0 % $q # 2^250 - 2^0
52
+ pow2(z2_250_0, 5) * z11 % $q # 2^255 - 2^5 + 11 = q - 2
53
+ end
54
+
55
+ def xrecover(y)
56
+ xx = (y * y - 1) * inv($d * y * y + 1)
57
+ x = xx.to_bn.mod_exp(($q + 3) / 8, $q)
58
+ x = (x * $I) % $q if (x * x - xx) % $q != 0
59
+ x = $q - x if x % 2 != 0
60
+ x
61
+ end
62
+
63
+ def edwards_add(_P, _Q)
64
+ # This is formula sequence 'addition-add-2008-hwcd-3' from
65
+ # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
66
+ x1, y1, z1, t1 = _P
67
+ x2, y2, z2, t2 = _Q
68
+
69
+ a = (y1 - x1) * (y2 - x2) % $q
70
+ b = (y1 + x1) * (y2 + x2) % $q
71
+ c = t1 * 2 * $d * t2 % $q
72
+ dd = z1 * 2 * z2 % $q
73
+ e = b - a
74
+ f = dd - c
75
+ g = dd + c
76
+ h = b + a
77
+ x3 = e * f
78
+ y3 = g * h
79
+ t3 = e * h
80
+ z3 = f * g
81
+
82
+ [x3 % $q, y3 % $q, z3 % $q, t3 % $q]
83
+ end
84
+
85
+ def edwards_double(_P)
86
+ # This is formula sequence 'dbl-2008-hwcd' from
87
+ # http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
88
+ x1, y1, z1, _t1 = _P
89
+
90
+ a = x1 * x1 % $q
91
+ b = y1 * y1 % $q
92
+ c = 2 * z1 * z1 % $q
93
+ # dd = -a
94
+ e = ((x1 + y1) * (x1 + y1) - a - b) % $q
95
+ g = -a + b # dd + b
96
+ f = g - c
97
+ h = -a - b # dd - b
98
+ x3 = e * f
99
+ y3 = g * h
100
+ t3 = e * h
101
+ z3 = f * g
102
+
103
+ return x3 % $q, y3 % $q, z3 % $q, t3 % $q
104
+ end
105
+
106
+ def scalarmult(_P, e)
107
+ return $ident if e == 0
108
+ _Q = scalarmult(_P, e / 2)
109
+ _Q = edwards_double(_Q)
110
+ _Q = edwards_add(_Q, _P) if e & 1
111
+ _Q
112
+ end
113
+
114
+ def make_Bpow
115
+ _P = $B
116
+ (0...253).each do |_|
117
+ $Bpow << _P
118
+ _P = edwards_double(_P)
119
+ end
120
+ end
121
+
122
+ # Implements scalarmult(B, e) more efficiently.
123
+ def scalarmult_B(e)
124
+ # scalarmult(B, l) is the identity
125
+ e = e % $l
126
+ _P = $ident
127
+ (0...253).each do |i|
128
+ _P = edwards_add(_P, $Bpow[i]) if e & 1 == 1
129
+ e = e / 2
130
+ end
131
+ _P
132
+ end
133
+
134
+ def encodeint(y)
135
+ bits = (0...$b).map {|i| (y >> i) & 1}
136
+ (0...$b/8).map {|i| int2byte((0...8).inject(0) {|sum, j| sum + (bits[i * 8 + j] << j) }) }.join
137
+ end
138
+
139
+ def encodepoint(_P)
140
+ x, y, z, _t = _P
141
+ zi = inv(z)
142
+ x = (x * zi) % $q
143
+ y = (y * zi) % $q
144
+ bits = (0...$b-1).map {|i| (y >> i) & 1} + [x & 1]
145
+ (0...$b/8).map {|i| int2byte((0...8).inject(0) {|sum, j| sum + (bits[i * 8 + j] << j) }) }.join
146
+ end
147
+
148
+ def bit(h, i)
149
+ (indexbytes(h, i / 8) >> (i % 8)) & 1
150
+ end
151
+
152
+ def publickey_unsafe(sk)
153
+ h = H(sk)
154
+ a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
155
+ _A = scalarmult_B(a)
156
+ return encodepoint(_A)
157
+ end
158
+
159
+ def publickey_hash_unsafe(sk)
160
+ h = HH(sk)
161
+ a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
162
+ _A = scalarmult_B(a)
163
+ return encodepoint(_A)
164
+ end
165
+
166
+ def Hint(m)
167
+ h = H(m)
168
+ (0...2*$b).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
169
+ end
170
+
171
+ def Hint_hash(m)
172
+ h = HH(m)
173
+ (0...2*$b).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
174
+ end
175
+
176
+ def signature_unsafe(m, sk, pk)
177
+ h = H(sk)
178
+ a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
179
+ r = Hint(
180
+ intlist2bytes(($b/8...$b/4).map {|j| indexbytes(h, j) }) + m
181
+ )
182
+ _R = scalarmult_B(r)
183
+ _S = (r + Hint(encodepoint(_R) + pk + m) * a) % $l
184
+ encodepoint(_R) + encodeint(_S)
185
+ end
186
+
187
+ # Not safe to use with secret keys or secret data.
188
+ #
189
+ # See module docstring. This function should be used for testing only.
190
+ def signature_hash_unsafe(m, sk, pk)
191
+ h = HH(sk)
192
+ a = 2 ** ($b-2) + (3...$b-2).inject(0) {|sum, i| sum + 2 ** i * bit(h, i) }
193
+ r = Hint_hash(
194
+ intlist2bytes(($b/8...$b/4).map {|j| indexbytes(h, j) }) + m
195
+ )
196
+ _R = scalarmult_B(r)
197
+ _S = (r + Hint_hash(encodepoint(_R) + pk + m) * a) % $l
198
+ encodepoint(_R) + encodeint(_S)
199
+ end
200
+
201
+ def isoncurve(_P)
202
+ x, y, z, t = _P
203
+ (z % $q != 0 and
204
+ x * y % $q == z * t % $q and
205
+ (y * y - x * x - z * z - $d * t * t) % $q == 0)
206
+ end
207
+
208
+ def decodeint(s)
209
+ (0...$b).inject(0) {|sum, i| sum + 2 ** i * bit(s, i) }
210
+ end
211
+
212
+ def decodepoint(s)
213
+ y = (0...$b-1).inject(0) {|sum, i| 2 ** i * bit(s, i) }
214
+ x = xrecover(y)
215
+ x = $q - x if x & 1 != bit(s, $b - 1)
216
+ _P = [x, y, 1, (x * y) % $q]
217
+ raise "decoding point that is not on curve" unless isoncurve(_P)
218
+ _P
219
+ end
220
+
221
+ class SignatureMismatch < StandardError
222
+ end
223
+
224
+ # Not safe to use when any argument is secret.
225
+ #
226
+ # See module docstring. This function should be used only for
227
+ # verifying public signatures of public messages.
228
+ def checkvalid(s, m, pk)
229
+ raise "signature length is wrong" if s.size != $b / 4
230
+ raise "public-key length is wrong" if pk.size != $b / 8
231
+
232
+ # _R = decodepoint(s[:b // 8])
233
+ _R = decodepoint(s[0...$b/8])
234
+ _A = decodepoint(pk)
235
+ _S = decodeint(s[$b/8...$b/4])
236
+ h = Hint(encodepoint(_R) + pk + m)
237
+
238
+ x1, y1, z1, _t1 = _P = scalarmult_B(_S)
239
+ x2, y2, z2, _t2 = _Q = edwards_add(_R, scalarmult(_A, h))
240
+
241
+ if (!isoncurve(_P) || !isoncurve(_Q) || (x1 * z2 - x2 * z1) % q != 0 || (y1 * z2 - y2 * z1) % q != 0)
242
+ raise SignatureMismatch("signature does not pass verification")
243
+ end
244
+ end
245
+ end
246
+
247
+ $b = 256
248
+ $q = 2 ** 255 - 19
249
+ $l = 2 ** 252 + 27742317777372353535851937790883648493
250
+
251
+ $d = -121665 * self.inv(121666) % $q
252
+ $I = 2.to_bn.mod_exp(($q - 1) / 4, $q)
253
+
254
+ $By = 4 * self.inv(5)
255
+ $Bx = self.xrecover($By)
256
+ $B = [$Bx % $q, $By % $q, 1, ($Bx * $By) % $q]
257
+ $ident = [0, 1, 1, 0]
258
+
259
+ # Bpow[i] == scalarmult(B, 2**i)
260
+ $Bpow = []
261
+ self.make_Bpow
262
+ end
263
+ end