nis-ruby 0.0.12 → 0.0.13

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.
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