openssl-signature_algorithm 0.4.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7bc92eb1796a3b0f57e24b861d0eab80d3889189b2dcf48988f205e9d81cd69
4
- data.tar.gz: 365f011c31592f9d3d34a58a45b8ce3713227efbe5ea4a3bfc5fac0f87e68d14
3
+ metadata.gz: 05b32cb5c229b287708d0931b8ac52b8c90c98f53d31e146df38406870300e95
4
+ data.tar.gz: 0b35e770ff3342d8d7d7008f8a76a4cb40e63dfe756676276e84e72da0af6677
5
5
  SHA512:
6
- metadata.gz: 8f13ef1875e61ff4318e2888bba525388dbdddf6295a8eac737cfb02dc070a5d6de38b57297374368b1e8d0a8b1e380b6e1fa12c0d0c004a3300c1fe1d1763f6
7
- data.tar.gz: 96f2e6e633eb38af1d5df34ca33d1428f5fee4ee7945eb92354e481810601a13ce689705aaea29f84984a78eb8e46619fe48b7a623a1c93239f7b8c5fc544ec0
6
+ metadata.gz: f5bfe46225bf0fa061ef6046d94e7297bfd124be0b95cd4fc3cc125f8fcd58a288a8945a64f9af8f50ff3fdd22c148e3495bd643c9de5b535ca8ecb14c266649
7
+ data.tar.gz: 34a46fea3bde198cdbbc3b9e024dec9d635aa8c15484a819d8350bdd3b3a996dff75b6f64b6f9971f890c2796873594c555e0970f83a0e72adce9b22bf54c992
@@ -0,0 +1,54 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: build
9
+
10
+ on: push
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-20.04
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ ruby-version:
19
+ - 3.2.0
20
+ - 3.1.3
21
+ - 3.0.5
22
+ - 2.7.7
23
+ - 2.6.6
24
+ - 2.5.8
25
+ - 2.4.10
26
+ gemfile:
27
+ - openssl_3_1
28
+ - openssl_3_0
29
+ - openssl_2_2
30
+ - openssl_2_1
31
+ exclude:
32
+ - ruby-version: '2.4.10'
33
+ gemfile: openssl_3_0
34
+ - ruby-version: '2.5.8'
35
+ gemfile: openssl_3_0
36
+ - ruby-version: '2.4.10'
37
+ gemfile: openssl_3_1
38
+ - ruby-version: '2.5.8'
39
+ gemfile: openssl_3_1
40
+ env:
41
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
42
+ steps:
43
+ - uses: actions/checkout@v2
44
+ - run: rm Gemfile.lock
45
+ - name: Set up Ruby ${{ matrix.ruby }}
46
+ uses: ruby/setup-ruby@v1
47
+ with:
48
+ ruby-version: ${{ matrix.ruby-version }}
49
+ bundler-cache: true
50
+ - name: Run rubocop
51
+ run: bundle exec rubocop
52
+ if: ${{ matrix.ruby == '3.2.0' }}
53
+ - name: Run tests
54
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  .byebug_history
13
+
14
+ /gemfiles/*.gemfile.lock
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
1
  --format documentation
2
2
  --color
3
3
  --require spec_helper
4
+ --order random
data/.rubocop.yml CHANGED
@@ -1,6 +1,10 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.4
3
3
  DisabledByDefault: true
4
+ NewCops: disable
5
+ Exclude:
6
+ - "gemfiles/**/*"
7
+ - "vendor/bundle/**/*"
4
8
 
5
9
  Bundler:
6
10
  Enabled: true
@@ -17,6 +21,9 @@ Layout/LineLength:
17
21
  Lint:
18
22
  Enabled: true
19
23
 
24
+ Lint/MissingSuper:
25
+ Enabled: false
26
+
20
27
  Naming:
21
28
  Enabled: true
22
29
 
@@ -26,9 +33,6 @@ Security:
26
33
  Style/BlockComments:
27
34
  Enabled: true
28
35
 
29
- Style/BracesAroundHashParameters:
30
- Enabled: true
31
-
32
36
  Style/CaseEquality:
33
37
  Enabled: true
34
38
 
data/Appraisals ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "openssl_3_1" do
4
+ gem "openssl", "~> 3.1.0"
5
+ end
6
+
7
+ appraise "openssl_3_0" do
8
+ gem "openssl", "~> 3.0.0"
9
+ end
10
+
11
+ appraise "openssl_2_2" do
12
+ gem "openssl", "~> 2.2.0"
13
+ end
14
+
15
+ appraise "openssl_2_1" do
16
+ gem "openssl", "~> 2.1.0"
17
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.3.0] - 2023-02-15
4
+
5
+ - Loose OpenSSL dependency to support 3.1 users. Thanks @bdewater <3
6
+
7
+ ## [v1.2.1] - 2022-06-05
8
+
9
+ - Support OpenSSL ~>3.0.0. Credits to @ClearlyClaire <3
10
+
11
+ ## [v1.1.1] - 2021-02-11
12
+
13
+ ### Fixed
14
+
15
+ - Fix error asking for ed25519 gem when actually not using EdDSA
16
+
17
+ ## [v1.1.0] - 2021-02-11
18
+
19
+ ### Added
20
+
21
+ - EdDSA support added (requires adding the `ed25519` gem to your `Gemfile`) ([@santiagorodriguez96])
22
+
23
+ ## [v1.0.0] - 2020-07-08
24
+
25
+ ### Added
26
+
27
+ - ECDSA with **secp256k1** curve support added:
28
+ ```rb
29
+ OpenSSL::SignatureAlgorithm::ECDSA.new(curve: "secp256k1")
30
+ ```
31
+ - Algorithm **arguments** are now **optional**. The following works:
32
+
33
+ ```rb
34
+ OpenSSL::SignatureAlgorithm::ECDSA.new
35
+ # defaults to ECDSA with SHA-256 and NIST P256 curve
36
+ # Same as OpenSSL::SignatureAlgorithm::ECDSA.new(hash_function: "SHA256", curve: "prime256v1")
37
+
38
+ OpenSSL::SignatureAlgorithm::RSAPSS.new
39
+ # defaults to SHA-256
40
+ # Same as OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA256")
41
+
42
+ OpenSSL::SignatureAlgorithm::RSAPKCS1.new
43
+ # defaults to SHA-256
44
+ # Same as OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA256")
45
+ ```
46
+
47
+ ### Changed
48
+
49
+ - Algorithm **instantiation** changed. The positional argument `digest_length` is replaced with keyword arguments, `hash_function:` for RSA algorithms and `hash_function:` and `curve:` for ECDSA. None are required arguments, you get sane defaults if you don't provide any arguments. Code migration examples:
50
+ ```rb
51
+ # Change this
52
+ # OpenSSL::SignatureAlgorithm::ECDSA.new("256")
53
+ # to
54
+ OpenSSL::SignatureAlgorithm::ECDSA.new(hash_function: "SHA256")
55
+ ```
56
+ ```rb
57
+ # Change this
58
+ # OpenSSL::SignatureAlgorithm::RSAPSS.new("384")
59
+ # to
60
+ OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA384")
61
+ ```
62
+
3
63
  ## [v0.4.0] - 2020-01-31
4
64
 
5
65
  ### Added
@@ -32,8 +92,17 @@
32
92
  - `OpenSSL::SignatureAlgorithm::RSAPSS`
33
93
  - `OpenSSL::SignatureAlgorithm::RSAPKCS1`
34
94
 
95
+ [v1.3.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v1.2.1...v1.3.0/
96
+ [v1.2.1]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v1.1.1...v1.2.1/
97
+ [v1.1.1]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v1.1.0...v1.1.1/
98
+ [v1.1.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v1.0.0...v1.1.0/
99
+ [v1.0.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.4.0...v1.0.0/
35
100
  [v0.4.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.3.0...v0.4.0/
36
101
  [v0.3.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.2.0...v0.3.0/
37
102
  [v0.2.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.1.1...v0.2.0/
38
103
  [v0.1.1]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.1.0...v0.1.1/
39
104
  [v0.1.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/41887c277dc7fa0c884ccf8924cf990ff76784d9...v0.1.0/
105
+
106
+ [@santiagorodriguez96]: https://github.com/santiagorodriguez96
107
+ [@ClearlyClaire]: https://github.com/clearlyclaire
108
+ [@bdewater]: https://github.com/bdewater
data/Gemfile CHANGED
@@ -5,7 +5,9 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in openssl-signature_algorithm.gemspec
6
6
  gemspec
7
7
 
8
+ gem "appraisal", "~> 2.2"
8
9
  gem "byebug", "~> 11.0"
9
- gem "rake", "~> 12.0"
10
+ gem "ed25519", "~> 1.2"
11
+ gem "rake", "~> 13.0"
10
12
  gem "rspec", "~> 3.0"
11
- gem "rubocop", "~> 0.79.0"
13
+ gem "rubocop", "~> 1.0"
data/Gemfile.lock CHANGED
@@ -1,52 +1,69 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openssl-signature_algorithm (0.4.0)
4
+ openssl-signature_algorithm (1.2.1)
5
+ openssl (> 2.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- ast (2.4.0)
10
+ appraisal (2.2.0)
11
+ bundler
12
+ rake
13
+ thor (>= 0.14.0)
14
+ ast (2.4.2)
10
15
  byebug (11.1.1)
11
16
  diff-lcs (1.3)
12
- jaro_winkler (1.5.4)
13
- parallel (1.19.1)
14
- parser (2.7.0.2)
15
- ast (~> 2.4.0)
16
- rainbow (3.0.0)
17
- rake (12.3.3)
17
+ ed25519 (1.2.4)
18
+ json (2.6.3)
19
+ openssl (3.0.0)
20
+ parallel (1.22.1)
21
+ parser (3.2.1.0)
22
+ ast (~> 2.4.1)
23
+ rainbow (3.1.1)
24
+ rake (13.0.1)
25
+ regexp_parser (2.7.0)
26
+ rexml (3.2.5)
18
27
  rspec (3.9.0)
19
28
  rspec-core (~> 3.9.0)
20
29
  rspec-expectations (~> 3.9.0)
21
30
  rspec-mocks (~> 3.9.0)
22
31
  rspec-core (3.9.1)
23
32
  rspec-support (~> 3.9.1)
24
- rspec-expectations (3.9.0)
33
+ rspec-expectations (3.9.1)
25
34
  diff-lcs (>= 1.2.0, < 2.0)
26
35
  rspec-support (~> 3.9.0)
27
36
  rspec-mocks (3.9.1)
28
37
  diff-lcs (>= 1.2.0, < 2.0)
29
38
  rspec-support (~> 3.9.0)
30
39
  rspec-support (3.9.2)
31
- rubocop (0.79.0)
32
- jaro_winkler (~> 1.5.1)
40
+ rubocop (1.45.1)
41
+ json (~> 2.3)
33
42
  parallel (~> 1.10)
34
- parser (>= 2.7.0.1)
43
+ parser (>= 3.2.0.0)
35
44
  rainbow (>= 2.2.2, < 4.0)
45
+ regexp_parser (>= 1.8, < 3.0)
46
+ rexml (>= 3.2.5, < 4.0)
47
+ rubocop-ast (>= 1.24.1, < 2.0)
36
48
  ruby-progressbar (~> 1.7)
37
- unicode-display_width (>= 1.4.0, < 1.7)
38
- ruby-progressbar (1.10.1)
39
- unicode-display_width (1.6.1)
49
+ unicode-display_width (>= 2.4.0, < 3.0)
50
+ rubocop-ast (1.24.1)
51
+ parser (>= 3.1.1.0)
52
+ ruby-progressbar (1.11.0)
53
+ thor (1.0.1)
54
+ unicode-display_width (2.4.2)
40
55
 
41
56
  PLATFORMS
42
57
  ruby
43
58
 
44
59
  DEPENDENCIES
60
+ appraisal (~> 2.2)
45
61
  byebug (~> 11.0)
62
+ ed25519 (~> 1.2)
46
63
  openssl-signature_algorithm!
47
- rake (~> 12.0)
64
+ rake (~> 13.0)
48
65
  rspec (~> 3.0)
49
- rubocop (~> 0.79.0)
66
+ rubocop (~> 1.0)
50
67
 
51
68
  BUNDLED WITH
52
- 2.1.4
69
+ 2.3.26
data/README.md CHANGED
@@ -1,12 +1,18 @@
1
1
  # OpenSSL::SignatureAlgorithm
2
2
 
3
- Provides `OpenSSL::SignatureAlgorithm::ECDSA`, `OpenSSL::SignatureAlgorithm::RSAPSS`
4
- and `OpenSSL::SignatureAlgorithm::RSAPKCS1` ruby object wrapers on top of `OpenSSL::PKey::EC`
5
- and `OpenSSL::PKey::RSA`, so that you can reason in terms of signature algorithms when
6
- signing and/or verifying signatures, instead of keys.
3
+ > ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 signature algorithms for ruby
4
+
5
+ Sign and verify using signature algorithm wrappers, instead of key objects.
6
+
7
+ Provides `OpenSSL::SignatureAlgorithm::ECDSA`, `OpenSSL::SignatureAlgorithm::EdDSA`, `OpenSSL::SignatureAlgorithm::RSAPSS`
8
+ and `OpenSSL::SignatureAlgorithm::RSAPKCS1` ruby object wrappers on top of `OpenSSL::PKey::EC`
9
+ and `OpenSSL::PKey::RSA`, so that you can reason in terms of the algorithms and do less when
10
+ signing or verifying signatures.
11
+
12
+ Loosely inspired by [rbnacl](https://github.com/RubyCrypto/rbnacl)'s [Digital Signatures](https://github.com/RubyCrypto/rbnacl/wiki/Digital-Signatures) interface.
7
13
 
8
14
  [![Gem](https://img.shields.io/gem/v/openssl-signature_algorithm.svg?style=flat-square&color=informational)](https://rubygems.org/gems/openssl-signature_algorithm)
9
- [![Travis](https://img.shields.io/travis/cedarcode/openssl-signature_algorithm.svg?style=flat-square)](https://travis-ci.org/cedarcode/openssl-signature_algorithm)
15
+ [![Actions Build](https://github.com/cedarcode/openssl-signature_algorithm/workflows/build/badge.svg)](https://github.com/cedarcode/openssl-signature_algorithm/actions)
10
16
 
11
17
  ## Installation
12
18
 
@@ -32,7 +38,7 @@ Or install it yourself as:
32
38
  to_be_signed = "to-be-signed"
33
39
 
34
40
  # Signer
35
- algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new("256")
41
+ algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new
36
42
  signing_key = algorithm.generate_signing_key
37
43
  signature = algorithm.sign(to_be_signed)
38
44
 
@@ -41,7 +47,31 @@ verify_key_string = signing_key.verify_key.serialize
41
47
 
42
48
  # Verifier
43
49
  verify_key = OpenSSL::SignatureAlgorithm::ECDSA::VerifyKey.deserialize(verify_key_string)
44
- algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new("256")
50
+ algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new
51
+ algorithm.verify_key = verify_key
52
+ algorithm.verify(signature, to_be_signed)
53
+ ```
54
+
55
+ ### EdDSA
56
+
57
+ Requires adding the `ed25519` gem to your `Gemfile`
58
+
59
+ ```ruby
60
+ require "openssl/signature_algorithm/eddsa"
61
+
62
+ to_be_signed = "to-be-signed"
63
+
64
+ # Signer
65
+ algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
66
+ signing_key = algorithm.generate_signing_key
67
+ signature = algorithm.sign(to_be_signed)
68
+
69
+ # Signer sends verify key to Verifier
70
+ verify_key_string = signing_key.verify_key.serialize
71
+
72
+ # Verifier
73
+ verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
74
+ algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
45
75
  algorithm.verify_key = verify_key
46
76
  algorithm.verify(signature, to_be_signed)
47
77
  ```
@@ -52,7 +82,7 @@ algorithm.verify(signature, to_be_signed)
52
82
  to_be_signed = "to-be-signed"
53
83
 
54
84
  # Signer
55
- algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new("256")
85
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new
56
86
  signing_key = algorithm.generate_signing_key
57
87
  signature = algorithm.sign(to_be_signed)
58
88
 
@@ -61,7 +91,7 @@ verify_key_string = signing_key.verify_key.serialize
61
91
 
62
92
  # Verifier
63
93
  verify_key = OpenSSL::SignatureAlgorithm::RSAPSS::VerifyKey.deserialize(verify_key_string)
64
- algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new("256")
94
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new
65
95
  algorithm.verify_key = verify_key
66
96
  algorithm.verify(signature, to_be_signed)
67
97
  ```
@@ -72,7 +102,7 @@ algorithm.verify(signature, to_be_signed)
72
102
  to_be_signed = "to-be-signed"
73
103
 
74
104
  # Signer
75
- algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new("256")
105
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new
76
106
  signing_key = algorithm.generate_signing_key
77
107
  signature = algorithm.sign(to_be_signed)
78
108
 
@@ -81,7 +111,7 @@ verify_key_string = signing_key.verify_key.serialize
81
111
 
82
112
  # Verifier
83
113
  verify_key = OpenSSL::SignatureAlgorithm::RSAPKCS1::VerifyKey.deserialize(verify_key_string)
84
- algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new("256")
114
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new
85
115
  algorithm.verify_key = verify_key
86
116
  algorithm.verify(signature, to_be_signed)
87
117
  ```
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", "~> 2.2"
6
+ gem "byebug", "~> 11.0"
7
+ gem "ed25519", "~> 1.2"
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.0"
11
+ gem "openssl", "~> 2.1.0"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", "~> 2.2"
6
+ gem "byebug", "~> 11.0"
7
+ gem "ed25519", "~> 1.2"
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.0"
11
+ gem "openssl", "~> 2.2.0"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", "~> 2.2"
6
+ gem "byebug", "~> 11.0"
7
+ gem "ed25519", "~> 1.2"
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.0"
11
+ gem "openssl", "~> 3.0.0"
12
+
13
+ gemspec path: "../"
@@ -0,0 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "appraisal", "~> 2.2"
6
+ gem "byebug", "~> 11.0"
7
+ gem "ed25519", "~> 1.2"
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.0"
11
+ gem "openssl", "~> 3.1.0"
12
+
13
+ gemspec path: "../"
@@ -5,20 +5,27 @@ require "openssl/signature_algorithm/error"
5
5
 
6
6
  module OpenSSL
7
7
  module SignatureAlgorithm
8
+ class SignatureVerificationError < Error; end
9
+ class UnsupportedParameterError < Error; end
10
+ class VerifyKeyError < Error; end
11
+
8
12
  class Base
9
- attr_reader :digest_length, :signing_key
10
- attr_accessor :verify_key
13
+ attr_reader :signing_key, :verify_key
11
14
 
12
- def initialize(digest_length)
13
- @digest_length = digest_length
15
+ def verify_key=(key)
16
+ if compatible_verify_key?(key)
17
+ @verify_key = key
18
+ else
19
+ raise(OpenSSL::SignatureAlgorithm::VerifyKeyError, "Incompatible verify key for algorithm")
20
+ end
14
21
  end
15
22
 
16
- def sign(data)
17
- signing_key.sign(hash_function, data)
23
+ def compatible_verify_key?(verify_key)
24
+ verify_key.respond_to?(:verify)
18
25
  end
19
26
 
20
- def hash_function
21
- OpenSSL::Digest.new("sha#{digest_length}")
27
+ def sign(data)
28
+ signing_key.sign(hash_function, data)
22
29
  end
23
30
 
24
31
  def verify(signature, verification_data)
@@ -30,7 +37,7 @@ module OpenSSL
30
37
  end
31
38
 
32
39
  verify_key.verify(hash_function, formatted_signature, verification_data) ||
33
- raise(OpenSSL::SignatureAlgorithm::Error, "Signature verification failed")
40
+ raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
34
41
  end
35
42
  end
36
43
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "delegate"
3
4
  require "openssl"
4
5
  require "openssl/signature_algorithm/base"
5
6
 
@@ -8,9 +9,9 @@ module OpenSSL
8
9
  class ECDSA < Base
9
10
  BYTE_LENGTH = 8
10
11
 
11
- class SigningKey < OpenSSL::PKey::EC
12
+ class SigningKey < DelegateClass(OpenSSL::PKey::EC)
12
13
  def initialize(*args)
13
- super(*args).generate_key
14
+ super(OpenSSL::PKey::EC.generate(*args))
14
15
  end
15
16
 
16
17
  def verify_key
@@ -18,7 +19,11 @@ module OpenSSL
18
19
  end
19
20
  end
20
21
 
21
- class VerifyKey < OpenSSL::PKey::EC::Point
22
+ class VerifyKey < DelegateClass(OpenSSL::PKey::EC::Point)
23
+ def initialize(*args)
24
+ super(OpenSSL::PKey::EC::Point.new(*args))
25
+ end
26
+
22
27
  def self.deserialize(pem_string)
23
28
  new(OpenSSL::PKey::EC.new(pem_string).public_key)
24
29
  end
@@ -30,10 +35,20 @@ module OpenSSL
30
35
  def ec_key
31
36
  @ec_key ||=
32
37
  begin
33
- ec_key = OpenSSL::PKey::EC.new(group)
34
- ec_key.public_key = self
35
-
36
- ec_key
38
+ # RFC5480 SubjectPublicKeyInfo
39
+ asn1 = OpenSSL::ASN1::Sequence(
40
+ [
41
+ OpenSSL::ASN1::Sequence(
42
+ [
43
+ OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
44
+ OpenSSL::ASN1::ObjectId(group.curve_name),
45
+ ]
46
+ ),
47
+ OpenSSL::ASN1::BitString(to_octet_string(:uncompressed))
48
+ ]
49
+ )
50
+
51
+ OpenSSL::PKey::EC.new(asn1.to_der)
37
52
  end
38
53
  end
39
54
 
@@ -42,19 +57,25 @@ module OpenSSL
42
57
  end
43
58
  end
44
59
 
45
- CURVE_BY_DIGEST_LENGTH = {
46
- "256" => "prime256v1",
47
- "384" => "secp384r1",
48
- "512" => "secp521r1"
49
- }.freeze
60
+ ACCEPTED_PARAMETERS = [
61
+ { curve: "prime256v1", hash_function: "SHA256" },
62
+ { curve: "secp384r1", hash_function: "SHA384" },
63
+ { curve: "secp521r1", hash_function: "SHA512" },
64
+ { curve: "secp256k1", hash_function: "SHA256" }
65
+ ].freeze
66
+
67
+ attr_reader :curve, :hash_function
68
+
69
+ def initialize(curve: nil, hash_function: nil)
70
+ @curve, @hash_function = pick_parameters(curve, hash_function)
71
+ end
50
72
 
51
73
  def generate_signing_key
52
- @signing_key = SigningKey.new(curve_name)
74
+ @signing_key = SigningKey.new(curve)
53
75
  end
54
76
 
55
- def curve_name
56
- CURVE_BY_DIGEST_LENGTH[digest_length] ||
57
- raise(OpenSSL::SignatureAlgorithm::Error, "Unsupported digest length #{digest_length}")
77
+ def compatible_verify_key?(key)
78
+ super && key.respond_to?(:group) && key.group.curve_name == curve
58
79
  end
59
80
 
60
81
  private
@@ -79,6 +100,28 @@ module OpenSSL
79
100
  def verify_key_length
80
101
  verify_key.group.degree
81
102
  end
103
+
104
+ def pick_parameters(curve, hash_function)
105
+ parameters = ACCEPTED_PARAMETERS.detect do |params|
106
+ if curve
107
+ if hash_function
108
+ params[:curve] == curve && params[:hash_function] == hash_function
109
+ else
110
+ params[:curve] == curve
111
+ end
112
+ elsif hash_function
113
+ params[:hash_function] == hash_function
114
+ else
115
+ true
116
+ end
117
+ end
118
+
119
+ if parameters
120
+ [parameters[:curve], parameters[:hash_function]]
121
+ else
122
+ raise(OpenSSL::SignatureAlgorithm::UnsupportedParameterError, "Unsupported algorithm parameters")
123
+ end
124
+ end
82
125
  end
83
126
  end
84
127
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ gem "ed25519", ">= 1.0.0"
5
+ require "ed25519"
6
+ rescue LoadError
7
+ warn "OpenSSL::SignatureAlgorithm::EdDSA requires the ed25519 gem, version 1.0 or higher. "\
8
+ "Please add it to your Gemfile: `gem \"ed25519\", \"~> 1.0\"`"
9
+ raise
10
+ end
11
+
12
+ require "openssl/signature_algorithm/base"
13
+
14
+ module OpenSSL
15
+ module SignatureAlgorithm
16
+ class EdDSA < Base
17
+ class SigningKey < ::Ed25519::SigningKey
18
+ def verify_key
19
+ VerifyKey.new(keypair[32, 32])
20
+ end
21
+ end
22
+
23
+ class VerifyKey < ::Ed25519::VerifyKey
24
+ def self.deserialize(key_bytes)
25
+ new(key_bytes)
26
+ end
27
+
28
+ def serialize
29
+ to_bytes
30
+ end
31
+ end
32
+
33
+ def generate_signing_key
34
+ @signing_key = SigningKey.generate
35
+ end
36
+
37
+ def sign(data)
38
+ signing_key.sign(data)
39
+ end
40
+
41
+ def verify(signature, verification_data)
42
+ verify_key.verify(signature, verification_data)
43
+ rescue ::Ed25519::VerifyError
44
+ raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "delegate"
4
+ require "openssl"
5
+ require "openssl/signature_algorithm/base"
6
+
7
+ module OpenSSL
8
+ module SignatureAlgorithm
9
+ class RSA < Base
10
+ class SigningKey < DelegateClass(OpenSSL::PKey::RSA)
11
+ def initialize(*args)
12
+ super(OpenSSL::PKey::RSA.new(*args))
13
+ end
14
+
15
+ def verify_key
16
+ VerifyKey.new(public_key.to_pem)
17
+ end
18
+ end
19
+
20
+ class VerifyKey < DelegateClass(OpenSSL::PKey::RSA)
21
+ class << self
22
+ alias_method :deserialize, :new
23
+ end
24
+
25
+ def initialize(*args)
26
+ super(OpenSSL::PKey::RSA.new(*args))
27
+ end
28
+
29
+ def serialize
30
+ to_pem
31
+ end
32
+ end
33
+
34
+ ACCEPTED_HASH_FUNCTIONS = ["SHA256", "SHA384", "SHA512"].freeze
35
+ DEFAULT_KEY_SIZE = 2048
36
+
37
+ attr_reader :hash_function
38
+
39
+ def initialize(hash_function: self.class::ACCEPTED_HASH_FUNCTIONS.first)
40
+ if self.class::ACCEPTED_HASH_FUNCTIONS.include?(hash_function)
41
+ @hash_function = hash_function
42
+ else
43
+ raise(OpenSSL::SignatureAlgorithm::UnsupportedParameterError, "Unsupported hash function '#{hash_function}'")
44
+ end
45
+ end
46
+
47
+ def generate_signing_key(size: DEFAULT_KEY_SIZE)
48
+ @signing_key = SigningKey.new(size)
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,32 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "openssl"
4
- require "openssl/signature_algorithm/base"
4
+ require "openssl/signature_algorithm/rsa"
5
5
 
6
6
  module OpenSSL
7
7
  module SignatureAlgorithm
8
- class RSAPKCS1 < Base
9
- class SigningKey < OpenSSL::PKey::RSA
10
- def verify_key
11
- VerifyKey.new(public_key.to_pem)
12
- end
13
- end
14
-
15
- class VerifyKey < OpenSSL::PKey::RSA
16
- class << self
17
- alias_method :deserialize, :new
18
- end
19
-
20
- def serialize
21
- to_pem
22
- end
23
- end
24
-
25
- DEFAULT_KEY_SIZE = 2048
26
-
27
- def generate_signing_key(size: DEFAULT_KEY_SIZE)
28
- @signing_key = SigningKey.new(size)
29
- end
8
+ class RSAPKCS1 < RSA
30
9
  end
31
10
  end
32
11
  end
@@ -1,33 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "openssl"
4
- require "openssl/signature_algorithm/base"
4
+ require "openssl/signature_algorithm/rsa"
5
5
 
6
6
  module OpenSSL
7
7
  module SignatureAlgorithm
8
- class RSAPSS < Base
9
- class SigningKey < OpenSSL::PKey::RSA
10
- def verify_key
11
- VerifyKey.new(public_key.to_pem)
12
- end
13
- end
14
-
15
- class VerifyKey < OpenSSL::PKey::RSA
16
- class << self
17
- alias_method :deserialize, :new
18
- end
19
-
20
- def serialize
21
- to_pem
22
- end
23
- end
24
-
25
- DEFAULT_KEY_SIZE = 2048
26
-
27
- def generate_signing_key(size: DEFAULT_KEY_SIZE)
28
- @signing_key = SigningKey.new(size)
29
- end
30
-
8
+ class RSAPSS < RSA
31
9
  def sign(data)
32
10
  signing_key.sign_pss(hash_function, data, salt_length: :max, mgf1_hash: mgf1_hash_function)
33
11
  end
@@ -39,7 +17,7 @@ module OpenSSL
39
17
  verification_data,
40
18
  salt_length: :auto,
41
19
  mgf1_hash: mgf1_hash_function
42
- ) || raise(OpenSSL::SignatureAlgorithm::Error, "Signature verification failed")
20
+ ) || raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
43
21
  end
44
22
 
45
23
  def mgf1_hash_function
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OpenSSL
4
4
  module SignatureAlgorithm
5
- VERSION = "0.4.0"
5
+ VERSION = "1.3.0"
6
6
  end
7
7
  end
@@ -9,14 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["gonzalo@cedarcode.com"]
10
10
  spec.license = "Apache-2.0"
11
11
 
12
- spec.summary = "OpenSSL::SignatureAlgorithm helpers for signing and verifying signatures with openssl ruby gem"
13
-
14
- spec.description = <<-DESC
15
- Provides OpenSSL::SignatureAlgorithm::ECDSA, OpenSSL::SignatureAlgorithm::RSAPSS
16
- and OpenSSL::SignatureAlgorithm::RSAPKCS1 ruby object wrapers on top of OpenSSL::PKey::EC
17
- and OpenSSL::PKey::RSA, so that you can reason in terms of signature algorithms when
18
- signing and/or verifying signatures, instead of keys.
19
- DESC
12
+ spec.summary = "ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby"
13
+ spec.description = spec.summary
20
14
 
21
15
  spec.homepage = "https://github.com/cedarcode/openssl-signature_algorithm"
22
16
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
@@ -33,4 +27,6 @@ Gem::Specification.new do |spec|
33
27
  spec.bindir = "exe"
34
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
29
  spec.require_paths = ["lib"]
30
+
31
+ spec.add_runtime_dependency "openssl", "> 2.0"
36
32
  end
metadata CHANGED
@@ -1,30 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openssl-signature_algorithm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
12
- dependencies: []
13
- description: |2
14
- Provides OpenSSL::SignatureAlgorithm::ECDSA, OpenSSL::SignatureAlgorithm::RSAPSS
15
- and OpenSSL::SignatureAlgorithm::RSAPKCS1 ruby object wrapers on top of OpenSSL::PKey::EC
16
- and OpenSSL::PKey::RSA, so that you can reason in terms of signature algorithms when
17
- signing and/or verifying signatures, instead of keys.
11
+ date: 2023-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: openssl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ description: ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby
18
28
  email:
19
29
  - gonzalo@cedarcode.com
20
30
  executables: []
21
31
  extensions: []
22
32
  extra_rdoc_files: []
23
33
  files:
34
+ - ".github/workflows/build.yml"
24
35
  - ".gitignore"
25
36
  - ".rspec"
26
37
  - ".rubocop.yml"
27
- - ".travis.yml"
38
+ - Appraisals
28
39
  - CHANGELOG.md
29
40
  - Gemfile
30
41
  - Gemfile.lock
@@ -33,10 +44,17 @@ files:
33
44
  - Rakefile
34
45
  - bin/console
35
46
  - bin/setup
47
+ - gemfiles/.bundle/config
48
+ - gemfiles/openssl_2_1.gemfile
49
+ - gemfiles/openssl_2_2.gemfile
50
+ - gemfiles/openssl_3_0.gemfile
51
+ - gemfiles/openssl_3_1.gemfile
36
52
  - lib/openssl/signature_algorithm.rb
37
53
  - lib/openssl/signature_algorithm/base.rb
38
54
  - lib/openssl/signature_algorithm/ecdsa.rb
55
+ - lib/openssl/signature_algorithm/eddsa.rb
39
56
  - lib/openssl/signature_algorithm/error.rb
57
+ - lib/openssl/signature_algorithm/rsa.rb
40
58
  - lib/openssl/signature_algorithm/rsapkcs1.rb
41
59
  - lib/openssl/signature_algorithm/rsapss.rb
42
60
  - lib/openssl/signature_algorithm/version.rb
@@ -48,7 +66,7 @@ metadata:
48
66
  homepage_uri: https://github.com/cedarcode/openssl-signature_algorithm
49
67
  source_code_uri: https://github.com/cedarcode/openssl-signature_algorithm
50
68
  changelog_uri: https://github.com/cedarcode/openssl-signature_algorithm/blob/master/CHANGELOG.md
51
- post_install_message:
69
+ post_install_message:
52
70
  rdoc_options: []
53
71
  require_paths:
54
72
  - lib
@@ -63,9 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
81
  - !ruby/object:Gem::Version
64
82
  version: '0'
65
83
  requirements: []
66
- rubygems_version: 3.1.2
67
- signing_key:
84
+ rubygems_version: 3.2.32
85
+ signing_key:
68
86
  specification_version: 4
69
- summary: OpenSSL::SignatureAlgorithm helpers for signing and verifying signatures
70
- with openssl ruby gem
87
+ summary: ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby
71
88
  test_files: []
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- dist: bionic
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.7.0
7
- - 2.6.5
8
- - 2.5.7
9
- - 2.4.9
10
- before_install: gem install bundler -v 2.1.4