sm2-crypto 0.1 → 0.2
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/README.md +25 -1
- data/lib/sm2_crypto.rb +99 -3
- data/sm2-crypto.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e11ed586baf19d83dea3bde65ca1c67c793229c1618222c3b0eab7dcaf4aa145
|
4
|
+
data.tar.gz: 87b1ef2ecdcb6cf6852a5616e2da6655964f065a62a0418824702936fd5a0a31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42430a1b69e52b255684bdfaf35ff4f501f908cb78be9516575c2a2e850288e29cb99c705b512b967eaab1d25f960319fc89f8acb6d79883608e199dc8825b61
|
7
|
+
data.tar.gz: 3c2142bcb64674f49d147791fe66fb726953e6fd7973969392ed0e892ef17424e9018ee31706164f45f85c3eab56f57b49e9ca456ab11c7ffe2b39bacb331207
|
data/README.md
CHANGED
@@ -30,13 +30,15 @@ $ gem install sm2-crypto
|
|
30
30
|
|
31
31
|
## Usage
|
32
32
|
|
33
|
+
### Encrypt and Decrypt
|
34
|
+
|
33
35
|
```ruby
|
34
36
|
require 'sm2_crypto'
|
35
37
|
|
36
38
|
# Generate key pair
|
37
39
|
keypair = OpenSSL::PKey::EC.generate("SM2")
|
38
40
|
private_key = keypair.private_key.to_s(2)
|
39
|
-
public_key = keypair.public_key.
|
41
|
+
public_key = keypair.public_key.to_octet_string(:uncompressed)
|
40
42
|
|
41
43
|
# Encrypt data
|
42
44
|
message = "Hello, SM2 encryption!"
|
@@ -48,6 +50,28 @@ decrypted_message = SM2Crypto.decrypt(private_key, encrypted_data)
|
|
48
50
|
puts "Decrypted message: #{decrypted_message}"
|
49
51
|
```
|
50
52
|
|
53
|
+
### Sign and Verify
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
message = "Hello, SM2 signature!"
|
57
|
+
# get signatrue
|
58
|
+
sign = SM2Crypto.sign(private_key, message)
|
59
|
+
# verify signatrue
|
60
|
+
SM2Crypto.verify(public_key, message, sign)
|
61
|
+
|
62
|
+
user_id = "31323334353637383132333435363738" # user_id should be a hex string
|
63
|
+
# sign with hash and user_id
|
64
|
+
sign = SM2Crypto.sign(private_key, message, sm3_hash: true, user_id: user_id)
|
65
|
+
# verify with hash and user_id
|
66
|
+
SM2Crypto.verify(public_key, message, sign, sm3_hash: true, user_id: user_id)
|
67
|
+
```
|
68
|
+
|
69
|
+
### Get Public Key from Private Key
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
public_key = SM2Crypto.get_public_key(private_key)
|
73
|
+
```
|
74
|
+
|
51
75
|
## Contributing
|
52
76
|
|
53
77
|
Contributions to the project are welcome. Please fork the repository, create a feature branch, and submit a pull request. Be sure to add tests and update documentation as needed.
|
data/lib/sm2_crypto.rb
CHANGED
@@ -32,10 +32,10 @@ module SM2Crypto
|
|
32
32
|
point = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("SM2"), OpenSSL::BN.new(public_key, 2))
|
33
33
|
random_key = OpenSSL::PKey::EC.generate("SM2")
|
34
34
|
k = random_key.private_key
|
35
|
-
c1 = random_key.public_key.
|
35
|
+
c1 = random_key.public_key.to_octet_string(:uncompressed)
|
36
36
|
|
37
37
|
p = point.mul(k)
|
38
|
-
p_bin_str = p.
|
38
|
+
p_bin_str = p.to_octet_string(:uncompressed)
|
39
39
|
x2 = p_bin_str[1, 32]
|
40
40
|
y2 = p_bin_str[33, 32]
|
41
41
|
|
@@ -71,7 +71,7 @@ module SM2Crypto
|
|
71
71
|
point = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("SM2"), OpenSSL::BN.new(c1, 2))
|
72
72
|
pkey = OpenSSL::BN.new(private_key, 2)
|
73
73
|
p = point.mul(pkey)
|
74
|
-
p_bin_str = p.
|
74
|
+
p_bin_str = p.to_octet_string(:uncompressed)
|
75
75
|
x2 = p_bin_str[1, 32]
|
76
76
|
y2 = p_bin_str[33, 32]
|
77
77
|
|
@@ -85,4 +85,100 @@ module SM2Crypto
|
|
85
85
|
|
86
86
|
msg
|
87
87
|
end
|
88
|
+
|
89
|
+
# get public key from private key
|
90
|
+
#
|
91
|
+
# @param private_key [String] private key, format: binary string
|
92
|
+
# @return [String] public key, format: binary string
|
93
|
+
def get_public_key(private_key)
|
94
|
+
pkey = OpenSSL::BN.new(private_key, 2)
|
95
|
+
group = OpenSSL::PKey::EC::Group.new("SM2")
|
96
|
+
group.generator.mul(pkey).to_octet_string(:uncompressed)
|
97
|
+
end
|
98
|
+
|
99
|
+
# sign with private key
|
100
|
+
#
|
101
|
+
# @param private_key [String] private key, format: binary string
|
102
|
+
# @param data [String]
|
103
|
+
# @param sm3_hash [Boolean], option to sign with sm3 hash, default: false
|
104
|
+
# @param user_id [String], format: hex string, default: "31323334353637383132333435363738"
|
105
|
+
# @return [String] signature, format: hex string
|
106
|
+
def sign(private_key, data, sm3_hash: false, user_id: "31323334353637383132333435363738")
|
107
|
+
data = data.unpack1("a*") unless data.ascii_only?
|
108
|
+
if sm3_hash
|
109
|
+
public_key = get_public_key(private_key)
|
110
|
+
data = OpenSSL::Digest.digest("SM3", za(public_key, user_id) + data)
|
111
|
+
end
|
112
|
+
|
113
|
+
n = OpenSSL::BN.new("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
|
114
|
+
da = OpenSSL::BN.new(private_key, 2)
|
115
|
+
e = OpenSSL::BN.new(data, 2)
|
116
|
+
one = OpenSSL::BN.new(1)
|
117
|
+
|
118
|
+
k = 0
|
119
|
+
s = 0
|
120
|
+
r = 0
|
121
|
+
while s.zero?
|
122
|
+
while r.zero? || r + k == n
|
123
|
+
random_key = OpenSSL::PKey::EC.generate("SM2")
|
124
|
+
k = random_key.private_key
|
125
|
+
x1 = OpenSSL::BN.new(random_key.public_key.to_octet_string(:uncompressed)[1, 32], 2)
|
126
|
+
# r = (e + x1) mod n
|
127
|
+
r = (e + x1) % n
|
128
|
+
end
|
129
|
+
# s = ((1 + dA)^-1 * (k - r * dA)) mod n
|
130
|
+
s = ((one + da).mod_inverse(n) * (k - (r * da))).to_i % n.to_i
|
131
|
+
end
|
132
|
+
|
133
|
+
r.to_s(16).rjust(64, "0") + s.to_s(16).rjust(64, "0")
|
134
|
+
end
|
135
|
+
|
136
|
+
# verify the signature with public_key
|
137
|
+
#
|
138
|
+
# @param public_key [String] public key, format: binary string
|
139
|
+
# @param data [String]
|
140
|
+
# @param signature [String], hex string
|
141
|
+
# @param sm3_hash [Boolean], option to sign with sm3 hash, default: false
|
142
|
+
# @param user_id [String], format: hex string, default: "31323334353637383132333435363738"
|
143
|
+
# @return [Boolean] verify result
|
144
|
+
def verify(public_key, data, signature, sm3_hash: false, user_id: "31323334353637383132333435363738")
|
145
|
+
return false if signature.size != 128
|
146
|
+
|
147
|
+
public_key = "\x04#{public_key}" if public_key.size == 64 && public_key[0] != "\x04"
|
148
|
+
data = data.unpack1("a*") unless data.ascii_only?
|
149
|
+
if sm3_hash
|
150
|
+
data = OpenSSL::Digest.digest("SM3", za(public_key, user_id) + data)
|
151
|
+
end
|
152
|
+
r = OpenSSL::BN.new(signature[0, 64], 16)
|
153
|
+
s = OpenSSL::BN.new(signature[64, 64], 16)
|
154
|
+
n = OpenSSL::BN.new("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
|
155
|
+
e = OpenSSL::BN.new(data, 2)
|
156
|
+
|
157
|
+
# t = (r + s) mod n
|
158
|
+
t = (r + s) % n
|
159
|
+
return false if t.zero?
|
160
|
+
|
161
|
+
point = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("SM2"), OpenSSL::BN.new(public_key, 2))
|
162
|
+
|
163
|
+
# x1y1 = s * G + t * PA
|
164
|
+
x1y1 = point.mul(t, s)
|
165
|
+
x1 = OpenSSL::BN.new(x1y1.to_octet_string(:uncompressed)[1, 32], 2)
|
166
|
+
|
167
|
+
# R = (e + x1) mod n
|
168
|
+
r1 = (e + x1) % n
|
169
|
+
|
170
|
+
r == r1
|
171
|
+
end
|
172
|
+
|
173
|
+
# ZA = H256(ENTLA || IDA || a || b || gx || gy || px || py)
|
174
|
+
def za(public_key, user_id)
|
175
|
+
ida = [user_id].pack("H*")
|
176
|
+
entla = [ida.size * 8].pack("n")
|
177
|
+
a = ["FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC"].pack("H*")
|
178
|
+
b = ["28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93"].pack("H*")
|
179
|
+
gxgy = OpenSSL::PKey::EC::Group.new("SM2").generator.to_octet_string(:uncompressed)[1, 64]
|
180
|
+
public_key = public_key[1, 64] if public_key.size == 65
|
181
|
+
|
182
|
+
OpenSSL::Digest.digest("SM3", entla + ida + a + b + gxgy + public_key)
|
183
|
+
end
|
88
184
|
end
|
data/sm2-crypto.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sm2-crypto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.2'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seekr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|