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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +12 -9
- data/examples/transactions/importance_transfer.rb +1 -4
- data/examples/transactions/mosaic_definition_creation.rb +1 -4
- data/examples/transactions/mosaic_supply_change.rb +1 -4
- data/examples/transactions/multisig.rb +1 -6
- data/examples/transactions/multisig_add_cosignatory.rb +1 -4
- data/examples/transactions/multisig_aggregate_modification.rb +1 -4
- data/examples/transactions/multisig_signature.rb +2 -5
- data/examples/transactions/provision_namespace.rb +1 -4
- data/examples/transactions/transfer.rb +1 -4
- data/examples/transactions/transfer_remote.rb +19 -0
- data/lib/nis/endpoint/account/generate.rb +1 -1
- data/lib/nis/endpoint/account/get.rb +4 -4
- data/lib/nis/endpoint/account/harvests.rb +1 -1
- data/lib/nis/endpoint/account/historical.rb +1 -1
- data/lib/nis/endpoint/account/importances.rb +1 -1
- data/lib/nis/endpoint/account/lock.rb +1 -1
- data/lib/nis/endpoint/account/mosaic.rb +2 -2
- data/lib/nis/endpoint/account/namespace.rb +1 -1
- data/lib/nis/endpoint/account/status.rb +1 -1
- data/lib/nis/endpoint/account/transfers.rb +3 -3
- data/lib/nis/endpoint/account/unconfirmed_transactions.rb +1 -1
- data/lib/nis/endpoint/account/unlock.rb +1 -1
- data/lib/nis/endpoint/account/unlocked.rb +1 -1
- data/lib/nis/endpoint/block/at.rb +1 -1
- data/lib/nis/endpoint/block/get.rb +1 -1
- data/lib/nis/endpoint/chain/height.rb +1 -1
- data/lib/nis/endpoint/chain/last_block.rb +1 -1
- data/lib/nis/endpoint/chain/score.rb +1 -1
- data/lib/nis/endpoint/debug/connections.rb +3 -3
- data/lib/nis/endpoint/debug/time_synchronization.rb +1 -1
- data/lib/nis/endpoint/heartbeat.rb +1 -1
- data/lib/nis/endpoint/local/account/transfers.rb +3 -3
- data/lib/nis/endpoint/local/chain.rb +1 -1
- data/lib/nis/endpoint/namespace.rb +1 -1
- data/lib/nis/endpoint/namespace/mosaic.rb +1 -1
- data/lib/nis/endpoint/namespace/root.rb +1 -1
- data/lib/nis/endpoint/node/active_peers.rb +1 -1
- data/lib/nis/endpoint/node/boot.rb +1 -1
- data/lib/nis/endpoint/node/experiences.rb +1 -1
- data/lib/nis/endpoint/node/extended_info.rb +1 -1
- data/lib/nis/endpoint/node/info.rb +1 -1
- data/lib/nis/endpoint/node/peer_list.rb +3 -3
- data/lib/nis/endpoint/status.rb +1 -1
- data/lib/nis/endpoint/transaction/announce.rb +4 -4
- data/lib/nis/endpoint/transaction/prepareAnnounce.rb +4 -4
- data/lib/nis/keypair.rb +13 -3
- data/lib/nis/request/announce.rb +47 -2
- data/lib/nis/request/prepare_announce.rb +1 -1
- data/lib/nis/struct/account_importance_view_model.rb +1 -1
- data/lib/nis/struct/account_info.rb +1 -1
- data/lib/nis/struct/account_meta_data.rb +1 -1
- data/lib/nis/struct/account_meta_data_pair.rb +1 -1
- data/lib/nis/struct/account_private_key_transactions_page.rb +1 -1
- data/lib/nis/struct/application_meta_data.rb +1 -1
- data/lib/nis/struct/audit_collection.rb +1 -1
- data/lib/nis/struct/audit_info.rb +1 -1
- data/lib/nis/struct/block.rb +1 -1
- data/lib/nis/struct/block_height.rb +1 -1
- data/lib/nis/struct/block_score.rb +1 -1
- data/lib/nis/struct/boot_node_request.rb +1 -1
- data/lib/nis/struct/error.rb +1 -1
- data/lib/nis/struct/explorer_block_view_model.rb +1 -1
- data/lib/nis/struct/explorer_transfer_view_model.rb +1 -1
- data/lib/nis/struct/explorer_view_model_transaction.rb +1 -1
- data/lib/nis/struct/extended_node_experience_pair.rb +1 -1
- data/lib/nis/struct/harvest_info.rb +1 -1
- data/lib/nis/struct/key_pair_view_model.rb +1 -1
- data/lib/nis/struct/mosaic.rb +1 -1
- data/lib/nis/struct/mosaic_definition.rb +1 -1
- data/lib/nis/struct/mosaic_definition_meta_data.rb +1 -1
- data/lib/nis/struct/mosaic_definition_meta_data_pair.rb +1 -1
- data/lib/nis/struct/mosaic_id.rb +1 -1
- data/lib/nis/struct/mosaic_levy.rb +1 -1
- data/lib/nis/struct/mosaic_properties.rb +1 -1
- data/lib/nis/struct/multisig_cosignatory_modification.rb +1 -1
- data/lib/nis/struct/namespace.rb +1 -1
- data/lib/nis/struct/namespace_meta_data.rb +1 -1
- data/lib/nis/struct/namespace_meta_data_pair.rb +1 -1
- data/lib/nis/struct/nem_announce_result.rb +1 -1
- data/lib/nis/struct/nem_async_timer_visitor.rb +1 -1
- data/lib/nis/struct/nem_request_result.rb +1 -1
- data/lib/nis/struct/nis_node_info.rb +1 -1
- data/lib/nis/struct/node.rb +1 -1
- data/lib/nis/struct/node_collection.rb +1 -1
- data/lib/nis/struct/node_experience.rb +1 -1
- data/lib/nis/struct/request_announce.rb +1 -1
- data/lib/nis/struct/request_prepare_announce.rb +1 -1
- data/lib/nis/struct/time_synchronization_result.rb +1 -1
- data/lib/nis/struct/transaction.rb +4 -4
- data/lib/nis/struct/transaction_meta_data.rb +1 -1
- data/lib/nis/struct/transaction_meta_data_pair.rb +1 -1
- data/lib/nis/struct/unconfirmed_transaction_meta_data.rb +1 -1
- data/lib/nis/struct/unconfirmed_transaction_meta_data_pair.rb +1 -1
- data/lib/nis/transaction/importance_transfer.rb +1 -1
- data/lib/nis/transaction/mosaic_definition_creation.rb +1 -1
- data/lib/nis/transaction/mosaic_supply_change.rb +1 -1
- data/lib/nis/transaction/multisig.rb +1 -1
- data/lib/nis/transaction/multisig_aggregate_modification.rb +1 -1
- data/lib/nis/transaction/multisig_signature.rb +1 -1
- data/lib/nis/transaction/provision_namespace.rb +1 -1
- data/lib/nis/transaction/transfer.rb +4 -4
- data/lib/nis/unit/address.rb +19 -0
- data/lib/nis/util/convert.rb +125 -0
- data/lib/nis/util/ed25519.rb +263 -0
- data/lib/nis/util/serializer.rb +273 -0
- data/lib/nis/version.rb +1 -1
- data/nis.gemspec +1 -1
- 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
|
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
|
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
|
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
|
14
|
-
# @see
|
15
|
-
# @see
|
16
|
-
# @see
|
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
|
|
data/lib/nis/unit/address.rb
CHANGED
@@ -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
|