sr25519 0.4.0 → 0.8.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -1
- data/README.md +39 -11
- data/lib/address.rb +24 -1
- data/lib/ed25519_lib.rb +77 -0
- data/lib/sr25519/version.rb +1 -1
- data/lib/sr25519.rb +1 -0
- data/lib/sr25519_lib.rb +58 -6
- data/sr25519.gemspec +4 -1
- metadata +25 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f850eb36c7764e13d17631a64774c526e4358d6943d22148e8fe73ef3dc4fba1
|
4
|
+
data.tar.gz: 23599472953b497a43cd86b4f3352315bb5b5fca9b8ee26fead4c8f3ee50a672
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 868da7d03a1d747a65d093704c160f37e61714aa273f186da73ed38587ccd08bbfbc20df40e2d6344ee2d305a2f83f7d6e1876fe4ed5433dd60faf8ec53a5962
|
7
|
+
data.tar.gz: 97679a83b7680568aaf8a709ce165fd24af6e048e114b4a43b75c06971abf5eedbfb2ac0aa717e3ac50f4df9c3cdc8440149ac08b75f9f7f835eaed6262ca4bd
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sr25519 (0.
|
4
|
+
sr25519 (0.8.0)
|
5
5
|
base58
|
6
6
|
blake2b
|
7
|
+
ed25519 (~> 1.2, >= 1.2.4)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
@@ -11,6 +12,7 @@ GEM
|
|
11
12
|
base58 (0.2.3)
|
12
13
|
blake2b (0.10.0)
|
13
14
|
diff-lcs (1.4.4)
|
15
|
+
ed25519 (1.2.4)
|
14
16
|
ffi (1.15.4)
|
15
17
|
rake (13.0.6)
|
16
18
|
rspec (3.10.0)
|
data/README.md
CHANGED
@@ -22,21 +22,21 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
1. Require ed25519.rb in your Ruby program:
|
25
|
+
#### 1. Require ed25519.rb in your Ruby program:
|
26
26
|
```ruby
|
27
27
|
require "sr25519"
|
28
28
|
```
|
29
29
|
|
30
|
-
2.
|
30
|
+
#### 2. SR25519 Generate keypair
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
# seed is priviate key, is a hex string.
|
34
|
-
# example: SR25519.
|
35
|
-
|
34
|
+
# example: SR25519.keypair_from_seed("0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e")
|
35
|
+
keypair = SR25519.keypair_from_seed(seed)
|
36
36
|
|
37
37
|
```
|
38
38
|
|
39
|
-
3. Generate public_key
|
39
|
+
#### 3. SR25519 Generate public_key
|
40
40
|
|
41
41
|
```ruby
|
42
42
|
public_key = SR25519.get_public_key_from_seed(seed)
|
@@ -46,30 +46,58 @@ public_key_str = public_key.to_s
|
|
46
46
|
|
47
47
|
```
|
48
48
|
|
49
|
-
4. Encode address
|
49
|
+
#### 4. Encode address
|
50
50
|
```ruby
|
51
51
|
address = Address.encode(public_key.to_s)
|
52
52
|
```
|
53
53
|
|
54
|
-
5. Decode address
|
54
|
+
#### 5. Decode address
|
55
55
|
|
56
56
|
```ruby
|
57
|
-
|
57
|
+
public_key_str = Address.decode(address)
|
58
58
|
```
|
59
59
|
|
60
|
-
6. Sign message
|
60
|
+
#### 6. SR25519 Sign message
|
61
61
|
|
62
62
|
```ruby
|
63
|
+
# message = "Hello World"
|
63
64
|
signature_result = SR25519.sign(message, keypair)
|
64
65
|
|
65
66
|
```
|
66
67
|
|
67
|
-
7. Verify message
|
68
|
+
#### 7. SR25519 Verify message
|
68
69
|
|
69
70
|
```ruby
|
70
|
-
SR25519.verify(address, message, signature_result)
|
71
|
+
verify_result = SR25519.verify(address, message, signature_result)
|
71
72
|
```
|
72
73
|
|
74
|
+
#### 8. ED25519 Generate keypair
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
keypair = ED25519.keypair_from_seed(seed)
|
78
|
+
```
|
79
|
+
|
80
|
+
#### 9. ED25519 Sign message
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
signature_result = ED25519.sign(message, keypair)
|
84
|
+
```
|
85
|
+
|
86
|
+
#### 10. ED25519 Get public key
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
pulick_key_str = ED25519.get_public_key_from_seed(seed)
|
90
|
+
```
|
91
|
+
|
92
|
+
#### 11. ED25519 Verify message
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# public_key_str = ED25519.get_public_key_from_seed(seed)
|
96
|
+
# address = Address.encode(public_key_str)
|
97
|
+
verify_result = ED25519.verify(address, message, signature_result)
|
98
|
+
```
|
99
|
+
|
100
|
+
|
73
101
|
## Running tests
|
74
102
|
1. Run all tests
|
75
103
|
|
data/lib/address.rb
CHANGED
@@ -1,7 +1,30 @@
|
|
1
|
+
|
2
|
+
# The MIT License (MIT)
|
3
|
+
|
4
|
+
# Copyright (c) 2019 Wu Minzhe
|
5
|
+
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
|
1
24
|
require 'base58'
|
2
25
|
require 'blake2b'
|
3
26
|
|
4
|
-
|
27
|
+
# The code is copy from https://github.com/itering/scale.rb/blob/develop/lib/common.rb
|
5
28
|
class Address
|
6
29
|
SS58_PREFIX = 'SS58PRE'
|
7
30
|
|
data/lib/ed25519_lib.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require "ed25519"
|
2
|
+
class ED25519
|
3
|
+
|
4
|
+
# Sign the given message
|
5
|
+
# @param message [String] the message
|
6
|
+
# @param key_pair [Class] ED25519 keypair
|
7
|
+
# @return [String] sign result as a hex string
|
8
|
+
# @example
|
9
|
+
# message = "Hello world"
|
10
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
11
|
+
# keypair = ED25519.keypair_from_seed(seed)
|
12
|
+
# signature_result = ED25519.sign(message, keypair)
|
13
|
+
|
14
|
+
def self.sign(message, key_pair)
|
15
|
+
"0x" + key_pair.sign(message).unpack1("H*")
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Verify the sign result
|
20
|
+
# @param message [String] the message
|
21
|
+
# @param key_pair [Class] ED25519 keypair
|
22
|
+
# @return [String] sign result as a hex string
|
23
|
+
# @example
|
24
|
+
# message = "Hello world"
|
25
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
26
|
+
# public_key = ED25519.get_public_key_from_seed(seed)
|
27
|
+
# address = Address.encode(public_key)
|
28
|
+
# keypair = ED25519.keypair_from_seed(seed)
|
29
|
+
# signature_result = ED25519.sign(message, keypair)
|
30
|
+
# verify_result = ED25519.verify(address, message, signature_result)
|
31
|
+
|
32
|
+
def self.verify(address, message, signature_result)
|
33
|
+
if signature_result.start_with?("0x")
|
34
|
+
signature_result = signature_result.sub(/0x/, "")
|
35
|
+
end
|
36
|
+
signature = [signature_result].pack("H*")
|
37
|
+
public_key = Address.decode(address)
|
38
|
+
verify_key_bytes = [public_key].pack("H*")
|
39
|
+
verify_key = Ed25519::VerifyKey.new(verify_key_bytes)
|
40
|
+
begin
|
41
|
+
verify_key.verify(signature, message)
|
42
|
+
rescue
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Generate ED25519 keypair
|
49
|
+
# @param seed [String] private key
|
50
|
+
# @return [Class] ED25519 keypair
|
51
|
+
# @example
|
52
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
53
|
+
# keypair = ED25519.keypair_from_seed(seed)
|
54
|
+
|
55
|
+
def self.keypair_from_seed(seed)
|
56
|
+
if seed.start_with?("0x")
|
57
|
+
seed = seed.sub(/0x/, "")
|
58
|
+
end
|
59
|
+
seed = "".tap { |binary| seed.scan(/../) { |hn| binary << hn.to_i(16).chr } }
|
60
|
+
signing_key = Ed25519::SigningKey.new(seed)
|
61
|
+
return signing_key
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Get ED25519 public key
|
66
|
+
# @param seed [String] private key
|
67
|
+
# @return [String] public key
|
68
|
+
# @example
|
69
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
70
|
+
# public_key = ED25519.get_public_key_from_seed(seed)
|
71
|
+
|
72
|
+
def self.get_public_key_from_seed(seed)
|
73
|
+
signing_key = self.keypair_from_seed(seed)
|
74
|
+
return signing_key.verify_key.to_bytes.unpack1('H*')
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
data/lib/sr25519/version.rb
CHANGED
data/lib/sr25519.rb
CHANGED
data/lib/sr25519_lib.rb
CHANGED
@@ -5,7 +5,6 @@ module SR25519Lib
|
|
5
5
|
|
6
6
|
ffi_lib FFI::Library::LIBC
|
7
7
|
|
8
|
-
# The library is compile from https://github.com/Warchant/sr25519-crust
|
9
8
|
ffi_lib File.dirname(__FILE__) + '/libsr25519crust.so' if RUBY_PLATFORM =~ /linux/
|
10
9
|
ffi_lib File.dirname(__FILE__) + '/libsr25519crust.dylib' if RUBY_PLATFORM =~ /darwin/
|
11
10
|
|
@@ -19,6 +18,8 @@ class KeyPair < FFI::Struct
|
|
19
18
|
# [32b key | 32b nonce | 32b public]
|
20
19
|
layout :String, [:uint8, 96]
|
21
20
|
|
21
|
+
##
|
22
|
+
# Return the keypair public key
|
22
23
|
def public_key
|
23
24
|
pub_key = self[:String].to_a[64..96]
|
24
25
|
public_key = PublicKey.new
|
@@ -55,6 +56,8 @@ end
|
|
55
56
|
class SigMessage < FFI::Struct
|
56
57
|
layout :String, [:uint8, 64]
|
57
58
|
|
59
|
+
##
|
60
|
+
# Return the sign message as hex string
|
58
61
|
def to_s
|
59
62
|
self[:String].to_a.pack("c*").unpack1("H*")
|
60
63
|
end
|
@@ -62,17 +65,32 @@ end
|
|
62
65
|
|
63
66
|
class SR25519
|
64
67
|
|
68
|
+
# Sign message result
|
69
|
+
# @param message [String] message
|
70
|
+
# @param private_key [String] private_key
|
71
|
+
# @return [String] sign result
|
72
|
+
# @example
|
73
|
+
# message = "Hello World"
|
74
|
+
# private_key = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
75
|
+
# signature_result = SR25519.sr25519_sign(message, private_key)
|
65
76
|
def self.sr25519_sign(message, private_key)
|
66
77
|
sig = SigMessage.new
|
67
78
|
msg = FFI::MemoryPointer.from_string(message)
|
68
|
-
key_pair = self.
|
79
|
+
key_pair = self.keypair_from_seed(private_key)
|
69
80
|
public_key = key_pair.public_key
|
70
81
|
SR25519Lib.sr25519_sign(sig, public_key, key_pair, msg, message.length)
|
71
82
|
sig.to_s
|
72
83
|
end
|
73
84
|
|
74
|
-
|
75
|
-
#
|
85
|
+
# Sign message result
|
86
|
+
# @param message [String] message
|
87
|
+
# @param key_pair [KeyPair] Sr25519 keypair
|
88
|
+
# @return [String] sign result
|
89
|
+
# @example
|
90
|
+
# message = "Hello World"
|
91
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
92
|
+
# keypair = SR25519.keypair_from_seed(seed)
|
93
|
+
# signature_result = SR25519.sign(message, keypair)
|
76
94
|
def self.sign(message, key_pair)
|
77
95
|
sig = SigMessage.new
|
78
96
|
msg = FFI::MemoryPointer.from_string(message)
|
@@ -81,6 +99,19 @@ class SR25519
|
|
81
99
|
sig.to_s
|
82
100
|
end
|
83
101
|
|
102
|
+
# Verify the sign result
|
103
|
+
# @param address [String] account address
|
104
|
+
# @param message [String] message
|
105
|
+
# @param signature_result [String] Sr25519 sign result
|
106
|
+
# @return [boolean] sign result
|
107
|
+
# @example
|
108
|
+
# message = "Hello World"
|
109
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
110
|
+
# keypair = SR25519.keypair_from_seed(seed)
|
111
|
+
# public_key = SR25519.get_public_key_from_seed(seed)
|
112
|
+
# address = Address.encode(public_key.to_s)
|
113
|
+
# signature_result = SR25519.sign(message, keypair)
|
114
|
+
# verify_result = SR25519.verify(address, message, signature_result)
|
84
115
|
def self.verify(address, message, signature_result)
|
85
116
|
pk = PublicKey.new
|
86
117
|
public_key = self.decode_address(address)
|
@@ -97,7 +128,13 @@ class SR25519
|
|
97
128
|
verify = SR25519Lib.sr25519_verify(sig, msg, message.size, pk)
|
98
129
|
end
|
99
130
|
|
100
|
-
|
131
|
+
# Generate SR25519 keypair
|
132
|
+
# @param seed [String] private key
|
133
|
+
# @return [KeyPair] SR25519 keypair
|
134
|
+
# @example
|
135
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
136
|
+
# keypair = SR25519.keypair_from_seed(seed)
|
137
|
+
def self.keypair_from_seed(seed)
|
101
138
|
if seed.start_with?("0x")
|
102
139
|
seed = seed.sub(/0x/, "")
|
103
140
|
end
|
@@ -109,11 +146,26 @@ class SR25519
|
|
109
146
|
return key_pair
|
110
147
|
end
|
111
148
|
|
149
|
+
# Get SR25519 public key
|
150
|
+
# @param seed [String] private key
|
151
|
+
# @return [String] public key
|
152
|
+
# @example
|
153
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
154
|
+
# public_key = SR25519.get_public_key_from_seed(seed)
|
112
155
|
def self.get_public_key_from_seed(seed)
|
113
|
-
key_pair = self.
|
156
|
+
key_pair = self.keypair_from_seed(seed)
|
114
157
|
key_pair.public_key
|
115
158
|
end
|
116
159
|
|
160
|
+
# Get SR25519 public key
|
161
|
+
# @param address [String] account address
|
162
|
+
# @param addr_type [Interger] address type
|
163
|
+
# @return [String] public key
|
164
|
+
# @example
|
165
|
+
# seed = "0xfac7959dbfe72f052e5a0c3c8d6530f202b02fd8f9f5ca3580ec8deb7797479e"
|
166
|
+
# public_key = SR25519.get_public_key_from_seed(seed)
|
167
|
+
# address = Address.encode(public_key.to_s)
|
168
|
+
# public_key = SR25519.decode_address(address)
|
117
169
|
def self.decode_address(address,addr_type=42)
|
118
170
|
public_address = Address.decode(address,addr_type)
|
119
171
|
end
|
data/sr25519.gemspec
CHANGED
@@ -28,11 +28,14 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.bindir = "exe"
|
29
29
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
30
|
spec.require_paths = ["lib"]
|
31
|
+
spec.extra_rdoc_files = [
|
32
|
+
"README.md"
|
33
|
+
]
|
31
34
|
|
32
35
|
spec.add_development_dependency "rake", "~> 13.0"
|
33
36
|
spec.add_development_dependency "rspec", "~> 3.2"
|
34
37
|
spec.add_dependency "blake2b"
|
35
38
|
spec.add_dependency "base58"
|
36
39
|
spec.add_development_dependency "ffi", "~> 1.15.0"
|
37
|
-
|
40
|
+
spec.add_dependency "ed25519", '~> 1.2', '>= 1.2.4'
|
38
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sr25519
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- xuxh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -80,12 +80,33 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.15.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ed25519
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.2'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.2.4
|
93
|
+
type: :runtime
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '1.2'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.2.4
|
83
103
|
description: Sign and verify message with sr25519
|
84
104
|
email:
|
85
105
|
- xxh2611@gmail.com
|
86
106
|
executables: []
|
87
107
|
extensions: []
|
88
|
-
extra_rdoc_files:
|
108
|
+
extra_rdoc_files:
|
109
|
+
- README.md
|
89
110
|
files:
|
90
111
|
- ".github/workflows/ruby.yml"
|
91
112
|
- ".gitignore"
|
@@ -100,6 +121,7 @@ files:
|
|
100
121
|
- bin/console
|
101
122
|
- bin/setup
|
102
123
|
- lib/address.rb
|
124
|
+
- lib/ed25519_lib.rb
|
103
125
|
- lib/libsr25519crust.dylib
|
104
126
|
- lib/libsr25519crust.so
|
105
127
|
- lib/sr25519.rb
|