sm2-crypto 0.1
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 +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.txt +21 -0
- data/README.md +59 -0
- data/Rakefile +12 -0
- data/lib/sm2_crypto.rb +88 -0
- data/sm2-crypto.gemspec +32 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b51258ccfa3e81ed0173f642cd16e1f96a1ba5944a6646dc68aa5850cd4d9039
|
4
|
+
data.tar.gz: d9e2bfb6afbd01095baf46c283e906bca986510d5988e4c67e55510cc8fd1c93
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b030ea7c612717190baff608b974cdd74781ca7f15288602f0c8465f73be34d55abc28ce850329e09123e3f9c5d4020e8f6c4ecc903308878680ce929719a661
|
7
|
+
data.tar.gz: f8c0172e0e341570d0e672edebae78e4e552d7aca5441356b266480793b39b91fb428b433dee967a1e64e93dd2af766c56e6de32661330f9f64075b99f43711f
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sm2-crypto (0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
minitest (5.18.0)
|
10
|
+
rake (13.0.6)
|
11
|
+
|
12
|
+
PLATFORMS
|
13
|
+
arm64-darwin-22
|
14
|
+
x86_64-linux
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
minitest (~> 5.0)
|
18
|
+
rake (~> 13.0)
|
19
|
+
sm2-crypto!
|
20
|
+
|
21
|
+
BUNDLED WITH
|
22
|
+
2.4.6
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2023 Seekr
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# sm2-crypto
|
2
|
+
|
3
|
+
sm2-crypto is an implementation of the SM2 encryption and decryption algorithm in pure Ruby based on the OpenSSL SM2 elliptic curve cryptography standard.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
OpenSSL has added support for SM2/SM3/SM4 encryption algorithms since version [1.1.1](https://www.openssl.org/news/openssl-1.1.1-notes.html). However, Ruby does not wrap the C interface related to SM2 encryption and decryption in OpenSSL. This library is not a wrapper for the C interface, but an implementation of the SM2 encryption and decryption algorithm in pure Ruby, based on the `OpenSSL::PKey::EC` interface.
|
7
|
+
|
8
|
+
Before using, please make sure your Ruby's OpenSSL version is `1.1.1` or higher.
|
9
|
+
|
10
|
+
Check the OpenSSL version in Ruby:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
irb(main):001:0> require "openssl"
|
14
|
+
=> true
|
15
|
+
irb(main):002:0> OpenSSL::OPENSSL_VERSION
|
16
|
+
=> "OpenSSL 1.1.1k 25 Mar 2021"
|
17
|
+
```
|
18
|
+
|
19
|
+
Add this line to your Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem "sm2-crypto"
|
23
|
+
```
|
24
|
+
|
25
|
+
Or install it yourself via command line:
|
26
|
+
|
27
|
+
```shell
|
28
|
+
$ gem install sm2-crypto
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'sm2_crypto'
|
35
|
+
|
36
|
+
# Generate key pair
|
37
|
+
keypair = OpenSSL::PKey::EC.generate("SM2")
|
38
|
+
private_key = keypair.private_key.to_s(2)
|
39
|
+
public_key = keypair.public_key.to_bn.to_s(2)
|
40
|
+
|
41
|
+
# Encrypt data
|
42
|
+
message = "Hello, SM2 encryption!"
|
43
|
+
encrypted_data = SM2Crypto.encrypt(public_key, message)
|
44
|
+
puts "Encrypted message: #{encrypted_data}"
|
45
|
+
|
46
|
+
# Decrypt data
|
47
|
+
decrypted_message = SM2Crypto.decrypt(private_key, encrypted_data)
|
48
|
+
puts "Decrypted message: #{decrypted_message}"
|
49
|
+
```
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
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.
|
54
|
+
|
55
|
+
For bug reports and feature requests, please open an issue on the [GitHub repository](https://github.com/numbcoder/sm2-crypto/issues).
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
sm2-crypto is released under the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/lib/sm2_crypto.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module SM2Crypto
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Key Derived Function
|
9
|
+
#
|
10
|
+
# @param key [String] key data
|
11
|
+
# @param klen [Integer] export key length
|
12
|
+
# @return [Array<Integer>] bytes array
|
13
|
+
def kdf(key, klen)
|
14
|
+
# hlen = 32 # 哈希函数 SM3 输出长度 32 字节
|
15
|
+
n = (klen.to_f / 32).ceil # n = klen/hlen 向上取整
|
16
|
+
|
17
|
+
(1..n).map do |ct|
|
18
|
+
OpenSSL::Digest.digest("SM3", key + [ct].pack("N"))
|
19
|
+
end.join.slice(0, klen).bytes
|
20
|
+
end
|
21
|
+
|
22
|
+
# Encrypt
|
23
|
+
#
|
24
|
+
# @param public_key [String] public key, format: binary string
|
25
|
+
# @param data [String] data
|
26
|
+
# @param cipher_mode [Integer] 0: C1C2C3, 1: C1C3C2, default: 1
|
27
|
+
# @return [String] encrypted data, format: binary string
|
28
|
+
def encrypt(public_key, data, cipher_mode: 1)
|
29
|
+
data = data.unpack1("a*") unless data.ascii_only?
|
30
|
+
public_key = "\x04#{public_key}" if public_key.size == 64 && public_key[0] != "\x04"
|
31
|
+
|
32
|
+
point = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("SM2"), OpenSSL::BN.new(public_key, 2))
|
33
|
+
random_key = OpenSSL::PKey::EC.generate("SM2")
|
34
|
+
k = random_key.private_key
|
35
|
+
c1 = random_key.public_key.to_bn.to_s(2)
|
36
|
+
|
37
|
+
p = point.mul(k)
|
38
|
+
p_bin_str = p.to_bn.to_s(2)
|
39
|
+
x2 = p_bin_str[1, 32]
|
40
|
+
y2 = p_bin_str[33, 32]
|
41
|
+
|
42
|
+
t = kdf(x2 + y2, data.bytesize)
|
43
|
+
t = kdf(x2 + y2, data.bytesize) while t[0, 8].uniq == [0] && t.uniq == [0]
|
44
|
+
|
45
|
+
c2 = data.each_byte.map.with_index { |b, i| b ^ t[i] }.pack("C*")
|
46
|
+
|
47
|
+
# c3 = hash(x2 || msg || y2)
|
48
|
+
c3 = OpenSSL::Digest.digest("SM3", x2 + data + y2)
|
49
|
+
|
50
|
+
cipher_mode == 0 ? c1 + c2 + c3 : c1 + c3 + c2
|
51
|
+
end
|
52
|
+
|
53
|
+
# Decrypt
|
54
|
+
#
|
55
|
+
# @param private_key [String] private key, format: binary string
|
56
|
+
# @param data [String] data to be decrypted, format: binary string
|
57
|
+
# @param cipher_mode [Integer] 0: C1C2C3, 1: C1C3C2, default: 1
|
58
|
+
# @return [String] encrypted data, format: binary string
|
59
|
+
def decrypt(private_key, data, cipher_mode: 1)
|
60
|
+
data = "\x04#{data}" if data[0] != "\x04"
|
61
|
+
|
62
|
+
c1 = data[0, 65]
|
63
|
+
c2_size = data.bytesize - 97
|
64
|
+
if cipher_mode == 0
|
65
|
+
c2 = data[65, c2_size]
|
66
|
+
c3 = data[65 + c2_size, 32]
|
67
|
+
else
|
68
|
+
c3 = data[65, 32]
|
69
|
+
c2 = data[97, c2_size]
|
70
|
+
end
|
71
|
+
point = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC::Group.new("SM2"), OpenSSL::BN.new(c1, 2))
|
72
|
+
pkey = OpenSSL::BN.new(private_key, 2)
|
73
|
+
p = point.mul(pkey)
|
74
|
+
p_bin_str = p.to_bn.to_s(2)
|
75
|
+
x2 = p_bin_str[1, 32]
|
76
|
+
y2 = p_bin_str[33, 32]
|
77
|
+
|
78
|
+
t = kdf(x2 + y2, c2_size)
|
79
|
+
raise ArgumentError, "KDF is 0" if t[0, 8].uniq == [0] && t.uniq == [0]
|
80
|
+
|
81
|
+
msg = c2.each_byte.map.with_index { |b, i| b ^ t[i] }.pack("C*")
|
82
|
+
|
83
|
+
digest = OpenSSL::Digest.digest("SM3", x2 + msg + y2)
|
84
|
+
raise ArgumentError, "Digest no match" if c3 != digest
|
85
|
+
|
86
|
+
msg
|
87
|
+
end
|
88
|
+
end
|
data/sm2-crypto.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "sm2-crypto"
|
5
|
+
spec.version = "0.1"
|
6
|
+
spec.authors = ["Seekr"]
|
7
|
+
spec.email = ["wzhao23@gmail.com"]
|
8
|
+
|
9
|
+
spec.summary = "An SM2 cryptographic algorithm encryption and decryption library for Ruby"
|
10
|
+
spec.description = "sm2-crypto is an implementation of the SM2 encryption and decryption algorithm in pure Ruby based on the OpenSSL"
|
11
|
+
spec.homepage = "https://github.com/numbcoder/sm2-crypto"
|
12
|
+
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = ">= 2.7.0"
|
14
|
+
|
15
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "minitest", ">= 5.0"
|
31
|
+
spec.add_development_dependency "rake", ">= 13.0"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sm2-crypto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Seekr
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-04-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: minitest
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
description: sm2-crypto is an implementation of the SM2 encryption and decryption
|
42
|
+
algorithm in pure Ruby based on the OpenSSL
|
43
|
+
email:
|
44
|
+
- wzhao23@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- CHANGELOG.md
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- lib/sm2_crypto.rb
|
56
|
+
- sm2-crypto.gemspec
|
57
|
+
homepage: https://github.com/numbcoder/sm2-crypto
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata:
|
61
|
+
rubygems_mfa_required: 'true'
|
62
|
+
homepage_uri: https://github.com/numbcoder/sm2-crypto
|
63
|
+
source_code_uri: https://github.com/numbcoder/sm2-crypto
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 2.7.0
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.4.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: An SM2 cryptographic algorithm encryption and decryption library for Ruby
|
83
|
+
test_files: []
|