openssl-signature_algorithm 0.1.1 → 1.1.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: 973a01f83e137fb88da90dee332beee6e310b0b9e2e3e7a2b1e542483af0e6ef
4
- data.tar.gz: 93e691f2283a6d1acbd0448a647ba90f73171fc56a39a4fc05be88aca5be23f5
3
+ metadata.gz: b8ab663827b9c60f9719579871f55a1b12001374d444e9b9194d2708395ba8af
4
+ data.tar.gz: 8af2c52eea842562e1122bd8824bb8eb79ed8923648d24414b11d7a7d0b9adea
5
5
  SHA512:
6
- metadata.gz: a91b04513d6ea59199bba52668fd76958ddea756012375db5b567dd67db86874c6ccb2aca08b7ad33480c33683266e417bb455ebeebc5f067de24fa648d3eb7b
7
- data.tar.gz: 26458502e1b9c12acf6b9652ce79b35572e28175a105f0fe0dc35eb87584039a47208417d079a5d3a2442e7407cc8b2943d7adbb6bb539bd29d9895063f04140
6
+ metadata.gz: 364884d8b267251a5f354d09cfbca71f64f33c7cc6eebac031b42074ab59eff1ed588b202e60f1bb06d392c175bb20c3b69563fda04a6210fe89b1facbb09333
7
+ data.tar.gz: 1a02dbd91e0d8e2dcc5d1e81bf8fe328d989f367f86224abaf77719b3fd3326785f7c5ac94b6adb3c0b3bdc3ab0add2d64ab2dba9479454c0f482c77ac7bc82a
@@ -0,0 +1,37 @@
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.0.0
20
+ - 2.7.2
21
+ - 2.6.6
22
+ - 2.5.8
23
+ - 2.4.10
24
+ gemfile:
25
+ - openssl_2_2
26
+ - openssl_2_1
27
+ - openssl_2_0
28
+ env:
29
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
30
+ steps:
31
+ - uses: actions/checkout@v2
32
+ - run: rm Gemfile.lock
33
+ - uses: ruby/setup-ruby@v1
34
+ with:
35
+ ruby-version: ${{ matrix.ruby-version }}
36
+ bundler-cache: true
37
+ - run: bundle exec rake
data/.gitignore CHANGED
@@ -9,3 +9,6 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
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,9 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.5
2
+ TargetRubyVersion: 2.4
3
3
  DisabledByDefault: true
4
+ Exclude:
5
+ - "gemfiles/**/*"
6
+ - "vendor/bundle/**/*"
4
7
 
5
8
  Bundler:
6
9
  Enabled: true
@@ -26,9 +29,6 @@ Security:
26
29
  Style/BlockComments:
27
30
  Enabled: true
28
31
 
29
- Style/BracesAroundHashParameters:
30
- Enabled: true
31
-
32
32
  Style/CaseEquality:
33
33
  Enabled: true
34
34
 
data/Appraisals ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ appraise "openssl_2_2" do
4
+ gem "openssl", "~> 2.2.0"
5
+ end
6
+
7
+ appraise "openssl_2_1" do
8
+ gem "openssl", "~> 2.1.0"
9
+ end
10
+
11
+ appraise "openssl_2_0" do
12
+ gem "openssl", "~> 2.0.0"
13
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,69 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.1.0] - 2021-02-11
4
+
5
+ ### Added
6
+
7
+ - EdDSA support added (requires adding the `ed25519` gem to your `Gemfile`) ([@santiagorodriguez96])
8
+
9
+ ## [v1.0.0] - 2020-07-08
10
+
11
+ ### Added
12
+
13
+ - ECDSA with **secp256k1** curve support added:
14
+ ```rb
15
+ OpenSSL::SignatureAlgorithm::ECDSA.new(curve: "secp256k1")
16
+ ```
17
+ - Algorithm **arguments** are now **optional**. The following works:
18
+
19
+ ```rb
20
+ OpenSSL::SignatureAlgorithm::ECDSA.new
21
+ # defaults to ECDSA with SHA-256 and NIST P256 curve
22
+ # Same as OpenSSL::SignatureAlgorithm::ECDSA.new(hash_function: "SHA256", curve: "prime256v1")
23
+
24
+ OpenSSL::SignatureAlgorithm::RSAPSS.new
25
+ # defaults to SHA-256
26
+ # Same as OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA256")
27
+
28
+ OpenSSL::SignatureAlgorithm::RSAPKCS1.new
29
+ # defaults to SHA-256
30
+ # Same as OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA256")
31
+ ```
32
+
33
+ ### Changed
34
+
35
+ - 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:
36
+ ```rb
37
+ # Change this
38
+ # OpenSSL::SignatureAlgorithm::ECDSA.new("256")
39
+ # to
40
+ OpenSSL::SignatureAlgorithm::ECDSA.new(hash_function: "SHA256")
41
+ ```
42
+ ```rb
43
+ # Change this
44
+ # OpenSSL::SignatureAlgorithm::RSAPSS.new("384")
45
+ # to
46
+ OpenSSL::SignatureAlgorithm::RSAPSS.new(hash_function: "SHA384")
47
+ ```
48
+
49
+ ## [v0.4.0] - 2020-01-31
50
+
51
+ ### Added
52
+
53
+ - `VerifyKey` serialization and deserialization for easy transmission over the network
54
+
55
+ ## [v0.3.0] - 2020-01-30
56
+
57
+ ### Added
58
+
59
+ - Support ruby v2.4 (without RSA-PSS)
60
+
61
+ ## [v0.2.0] - 2020-01-29
62
+
63
+ ### Added
64
+
65
+ - `OpenSSL::SignatureAlgorithm::ECDSA#verify` now supports raw (non DER) signatures
66
+
3
67
  ## [v0.1.1] - 2020-01-29
4
68
 
5
69
  ### Fixed
@@ -14,5 +78,12 @@
14
78
  - `OpenSSL::SignatureAlgorithm::RSAPSS`
15
79
  - `OpenSSL::SignatureAlgorithm::RSAPKCS1`
16
80
 
81
+ [v1.1.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v1.0.0...v1.1.0/
82
+ [v1.0.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.4.0...v1.0.0/
83
+ [v0.4.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.3.0...v0.4.0/
84
+ [v0.3.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.2.0...v0.3.0/
85
+ [v0.2.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.1.1...v0.2.0/
17
86
  [v0.1.1]: https://github.com/cedarcode/openssl-signature_algorithm/compare/v0.1.0...v0.1.1/
18
87
  [v0.1.0]: https://github.com/cedarcode/openssl-signature_algorithm/compare/41887c277dc7fa0c884ccf8924cf990ff76784d9...v0.1.0/
88
+
89
+ [@santiagorodriguez96]: https://github.com/santiagorodriguez96
data/Gemfile CHANGED
@@ -5,6 +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 "rake", "~> 12.0"
8
+ gem "appraisal", "~> 2.2"
9
+ gem "byebug", "~> 11.0"
10
+ gem "ed25519", "~> 1.2"
11
+ gem "rake", "~> 13.0"
9
12
  gem "rspec", "~> 3.0"
10
- gem "rubocop", "~> 0.79.0"
13
+ gem "rubocop", "~> 0.80.1"
data/Gemfile.lock CHANGED
@@ -1,50 +1,64 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openssl-signature_algorithm (0.1.1)
4
+ openssl-signature_algorithm (1.0.0)
5
+ openssl (~> 2.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ appraisal (2.2.0)
11
+ bundler
12
+ rake
13
+ thor (>= 0.14.0)
9
14
  ast (2.4.0)
15
+ byebug (11.1.1)
10
16
  diff-lcs (1.3)
17
+ ed25519 (1.2.4)
11
18
  jaro_winkler (1.5.4)
19
+ openssl (2.2.0)
12
20
  parallel (1.19.1)
13
- parser (2.7.0.2)
21
+ parser (2.7.0.5)
14
22
  ast (~> 2.4.0)
15
23
  rainbow (3.0.0)
16
- rake (12.3.3)
24
+ rake (13.0.1)
25
+ rexml (3.2.4)
17
26
  rspec (3.9.0)
18
27
  rspec-core (~> 3.9.0)
19
28
  rspec-expectations (~> 3.9.0)
20
29
  rspec-mocks (~> 3.9.0)
21
30
  rspec-core (3.9.1)
22
31
  rspec-support (~> 3.9.1)
23
- rspec-expectations (3.9.0)
32
+ rspec-expectations (3.9.1)
24
33
  diff-lcs (>= 1.2.0, < 2.0)
25
34
  rspec-support (~> 3.9.0)
26
35
  rspec-mocks (3.9.1)
27
36
  diff-lcs (>= 1.2.0, < 2.0)
28
37
  rspec-support (~> 3.9.0)
29
38
  rspec-support (3.9.2)
30
- rubocop (0.79.0)
39
+ rubocop (0.80.1)
31
40
  jaro_winkler (~> 1.5.1)
32
41
  parallel (~> 1.10)
33
42
  parser (>= 2.7.0.1)
34
43
  rainbow (>= 2.2.2, < 4.0)
44
+ rexml
35
45
  ruby-progressbar (~> 1.7)
36
46
  unicode-display_width (>= 1.4.0, < 1.7)
37
47
  ruby-progressbar (1.10.1)
48
+ thor (1.0.1)
38
49
  unicode-display_width (1.6.1)
39
50
 
40
51
  PLATFORMS
41
52
  ruby
42
53
 
43
54
  DEPENDENCIES
55
+ appraisal (~> 2.2)
56
+ byebug (~> 11.0)
57
+ ed25519 (~> 1.2)
44
58
  openssl-signature_algorithm!
45
- rake (~> 12.0)
59
+ rake (~> 13.0)
46
60
  rspec (~> 3.0)
47
- rubocop (~> 0.79.0)
61
+ rubocop (~> 0.80.1)
48
62
 
49
63
  BUNDLED WITH
50
- 2.1.4
64
+ 2.2.8
data/README.md CHANGED
@@ -1,11 +1,18 @@
1
1
  # OpenSSL::SignatureAlgorithm
2
2
 
3
- This tiny library introduces `OpenSSL::SignatureAlgorithm::ECDSA`, `OpenSSL::SignatureAlgorithm::RSAPSS` and `OpenSSL::SignatureAlgorithm::RSAPKCS1`, so that you can reason in terms of signature algorithms when signing and/or verifying signatures―instead of keys.
3
+ > ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 signature algorithms for ruby
4
4
 
5
- This provides a higher level of abstraction, on top of `openssl`'s gem `OpenSSL::PKey::EC`, `OpenSSL::PKey::EC::Point` and `OpenSSL::PKey::RSA`.
5
+ Sign and verify using signature algorithm wrappers, instead of key objects.
6
6
 
7
- [![Gem](https://img.shields.io/gem/v/openssl-signature_algorithm.svg?style=flat-square)](https://rubygems.org/gems/openssl-signature_algorithm)
8
- [![Travis](https://img.shields.io/travis/cedarcode/openssl-signature_algorithm.svg?style=flat-square)](https://travis-ci.org/cedarcode/openssl-signature_algorithm)
7
+ Provides `OpenSSL::SignatureAlgorithm::ECDSA`, `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.
13
+
14
+ [![Gem](https://img.shields.io/gem/v/openssl-signature_algorithm.svg?style=flat-square&color=informational)](https://rubygems.org/gems/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)
9
16
 
10
17
  ## Installation
11
18
 
@@ -31,15 +38,38 @@ Or install it yourself as:
31
38
  to_be_signed = "to-be-signed"
32
39
 
33
40
  # Signer
34
- algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new("256")
41
+ algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new
42
+ signing_key = algorithm.generate_signing_key
43
+ signature = algorithm.sign(to_be_signed)
44
+
45
+ # Signer sends verify key to Verifier
46
+ verify_key_string = signing_key.verify_key.serialize
47
+
48
+ # Verifier
49
+ verify_key = OpenSSL::SignatureAlgorithm::ECDSA::VerifyKey.deserialize(verify_key_string)
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
+ to_be_signed = "to-be-signed"
61
+
62
+ # Signer
63
+ algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
35
64
  signing_key = algorithm.generate_signing_key
36
65
  signature = algorithm.sign(to_be_signed)
37
66
 
38
67
  # Signer sends verify key to Verifier
39
- verify_key = signing_key.verify_key
68
+ verify_key_string = signing_key.verify_key.serialize
40
69
 
41
70
  # Verifier
42
- algorithm = OpenSSL::SignatureAlgorithm::ECDSA.new("256")
71
+ verify_key = OpenSSL::SignatureAlgorithm::EdDSA::VerifyKey.deserialize(verify_key_string)
72
+ algorithm = OpenSSL::SignatureAlgorithm::EdDSA.new
43
73
  algorithm.verify_key = verify_key
44
74
  algorithm.verify(signature, to_be_signed)
45
75
  ```
@@ -50,15 +80,16 @@ algorithm.verify(signature, to_be_signed)
50
80
  to_be_signed = "to-be-signed"
51
81
 
52
82
  # Signer
53
- algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new("256")
83
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new
54
84
  signing_key = algorithm.generate_signing_key
55
85
  signature = algorithm.sign(to_be_signed)
56
86
 
57
87
  # Signer sends verify key to Verifier
58
- verify_key = signing_key.verify_key
88
+ verify_key_string = signing_key.verify_key.serialize
59
89
 
60
90
  # Verifier
61
- algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new("256")
91
+ verify_key = OpenSSL::SignatureAlgorithm::RSAPSS::VerifyKey.deserialize(verify_key_string)
92
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPSS.new
62
93
  algorithm.verify_key = verify_key
63
94
  algorithm.verify(signature, to_be_signed)
64
95
  ```
@@ -69,15 +100,16 @@ algorithm.verify(signature, to_be_signed)
69
100
  to_be_signed = "to-be-signed"
70
101
 
71
102
  # Signer
72
- algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new("256")
103
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new
73
104
  signing_key = algorithm.generate_signing_key
74
105
  signature = algorithm.sign(to_be_signed)
75
106
 
76
107
  # Signer sends verify key to Verifier
77
- verify_key = signing_key.verify_key
108
+ verify_key_string = signing_key.verify_key.serialize
78
109
 
79
110
  # Verifier
80
- algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new("256")
111
+ verify_key = OpenSSL::SignatureAlgorithm::RSAPKCS1::VerifyKey.deserialize(verify_key_string)
112
+ algorithm = OpenSSL::SignatureAlgorithm::RSAPKCS1.new
81
113
  algorithm.verify_key = verify_key
82
114
  algorithm.verify(signature, to_be_signed)
83
115
  ```
@@ -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 "rake", "~> 13.0"
8
+ gem "rspec", "~> 3.0"
9
+ gem "rubocop", "~> 0.80.1"
10
+ gem "ed25519", "~> 1.2"
11
+ gem "openssl", "~> 2.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 "rake", "~> 13.0"
8
+ gem "rspec", "~> 3.0"
9
+ gem "rubocop", "~> 0.80.1"
10
+ gem "ed25519", "~> 1.2"
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 "rake", "~> 13.0"
8
+ gem "rspec", "~> 3.0"
9
+ gem "rubocop", "~> 0.80.1"
10
+ gem "ed25519", "~> 1.2"
11
+ gem "openssl", "~> 2.2.0"
12
+
13
+ gemspec path: "../"
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "openssl/signature_algorithm/ecdsa"
4
+ require "openssl/signature_algorithm/eddsa"
4
5
  require "openssl/signature_algorithm/error"
5
6
  require "openssl/signature_algorithm/rsapss"
6
7
  require "openssl/signature_algorithm/rsapkcs1"
@@ -5,25 +5,39 @@ 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)
25
- verify_key.verify(hash_function, signature, verification_data) ||
26
- raise(OpenSSL::SignatureAlgorithm::Error, "Signature verification failed")
32
+ formatted_signature =
33
+ if respond_to?(:formatted_signature, true)
34
+ formatted_signature(signature)
35
+ else
36
+ signature
37
+ end
38
+
39
+ verify_key.verify(hash_function, formatted_signature, verification_data) ||
40
+ raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
27
41
  end
28
42
  end
29
43
  end
@@ -6,6 +6,8 @@ require "openssl/signature_algorithm/base"
6
6
  module OpenSSL
7
7
  module SignatureAlgorithm
8
8
  class ECDSA < Base
9
+ BYTE_LENGTH = 8
10
+
9
11
  class SigningKey < OpenSSL::PKey::EC
10
12
  def initialize(*args)
11
13
  super(*args).generate_key
@@ -17,27 +19,93 @@ module OpenSSL
17
19
  end
18
20
 
19
21
  class VerifyKey < OpenSSL::PKey::EC::Point
20
- def verify(*args)
21
- ec_key = OpenSSL::PKey::EC.new(group)
22
- ec_key.public_key = self
22
+ def self.deserialize(pem_string)
23
+ new(OpenSSL::PKey::EC.new(pem_string).public_key)
24
+ end
23
25
 
26
+ def serialize
27
+ ec_key.to_pem
28
+ end
29
+
30
+ def ec_key
31
+ @ec_key ||=
32
+ begin
33
+ ec_key = OpenSSL::PKey::EC.new(group)
34
+ ec_key.public_key = self
35
+
36
+ ec_key
37
+ end
38
+ end
39
+
40
+ def verify(*args)
24
41
  ec_key.verify(*args)
25
42
  end
26
43
  end
27
44
 
28
- CURVE_BY_DIGEST_LENGTH = {
29
- "256" => "prime256v1",
30
- "384" => "secp384r1",
31
- "512" => "secp521r1"
32
- }.freeze
45
+ ACCEPTED_PARAMETERS = [
46
+ { curve: "prime256v1", hash_function: "SHA256" },
47
+ { curve: "secp384r1", hash_function: "SHA384" },
48
+ { curve: "secp521r1", hash_function: "SHA512" },
49
+ { curve: "secp256k1", hash_function: "SHA256" }
50
+ ].freeze
51
+
52
+ attr_reader :curve, :hash_function
53
+
54
+ def initialize(curve: nil, hash_function: nil)
55
+ @curve, @hash_function = pick_parameters(curve, hash_function)
56
+ end
33
57
 
34
58
  def generate_signing_key
35
- @signing_key = SigningKey.new(curve_name)
59
+ @signing_key = SigningKey.new(curve)
36
60
  end
37
61
 
38
- def curve_name
39
- CURVE_BY_DIGEST_LENGTH[digest_length] ||
40
- raise(OpenSSL::SignatureAlgorithm::Error, "Unsupported digest length #{digest_length}")
62
+ def compatible_verify_key?(key)
63
+ super && key.respond_to?(:group) && key.group.curve_name == curve
64
+ end
65
+
66
+ private
67
+
68
+ # Borrowed from jwt rubygem.
69
+ # https://github.com/jwt/ruby-jwt/blob/7a6a3f1dbaff806993156d1dff9c217bb2523ff8/lib/jwt/security_utils.rb#L34-L39
70
+ #
71
+ # Hopefully this will be provided by openssl rubygem in the future.
72
+ def formatted_signature(signature)
73
+ n = (verify_key_length.to_f / BYTE_LENGTH).ceil
74
+
75
+ if signature.size == n * 2
76
+ r = signature[0..(n - 1)]
77
+ s = signature[n..-1]
78
+
79
+ OpenSSL::ASN1::Sequence.new([r, s].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
80
+ else
81
+ signature
82
+ end
83
+ end
84
+
85
+ def verify_key_length
86
+ verify_key.group.degree
87
+ end
88
+
89
+ def pick_parameters(curve, hash_function)
90
+ parameters = ACCEPTED_PARAMETERS.detect do |params|
91
+ if curve
92
+ if hash_function
93
+ params[:curve] == curve && params[:hash_function] == hash_function
94
+ else
95
+ params[:curve] == curve
96
+ end
97
+ elsif hash_function
98
+ params[:hash_function] == hash_function
99
+ else
100
+ true
101
+ end
102
+ end
103
+
104
+ if parameters
105
+ [parameters[:curve], parameters[:hash_function]]
106
+ else
107
+ raise(OpenSSL::SignatureAlgorithm::UnsupportedParameterError, "Unsupported algorithm parameters")
108
+ end
41
109
  end
42
110
  end
43
111
  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,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "openssl/signature_algorithm/base"
5
+
6
+ module OpenSSL
7
+ module SignatureAlgorithm
8
+ class RSA < 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
+ ACCEPTED_HASH_FUNCTIONS = ["SHA256", "SHA384", "SHA512"].freeze
26
+ DEFAULT_KEY_SIZE = 2048
27
+
28
+ attr_reader :hash_function
29
+
30
+ def initialize(hash_function: self.class::ACCEPTED_HASH_FUNCTIONS.first)
31
+ if self.class::ACCEPTED_HASH_FUNCTIONS.include?(hash_function)
32
+ @hash_function = hash_function
33
+ else
34
+ raise(OpenSSL::SignatureAlgorithm::UnsupportedParameterError, "Unsupported hash function '#{hash_function}'")
35
+ end
36
+ end
37
+
38
+ def generate_signing_key(size: DEFAULT_KEY_SIZE)
39
+ @signing_key = SigningKey.new(size)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,22 +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
- public_key
12
- end
13
- end
14
-
15
- DEFAULT_KEY_SIZE = 2048
16
-
17
- def generate_signing_key(size: DEFAULT_KEY_SIZE)
18
- @signing_key = SigningKey.new(size)
19
- end
8
+ class RSAPKCS1 < RSA
20
9
  end
21
10
  end
22
11
  end
@@ -1,23 +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
- public_key
12
- end
13
- end
14
-
15
- DEFAULT_KEY_SIZE = 2048
16
-
17
- def generate_signing_key(size: DEFAULT_KEY_SIZE)
18
- @signing_key = SigningKey.new(size)
19
- end
20
-
8
+ class RSAPSS < RSA
21
9
  def sign(data)
22
10
  signing_key.sign_pss(hash_function, data, salt_length: :max, mgf1_hash: mgf1_hash_function)
23
11
  end
@@ -29,7 +17,7 @@ module OpenSSL
29
17
  verification_data,
30
18
  salt_length: :auto,
31
19
  mgf1_hash: mgf1_hash_function
32
- ) || raise(OpenSSL::SignatureAlgorithm::Error, "Signature verification failed")
20
+ ) || raise(OpenSSL::SignatureAlgorithm::SignatureVerificationError, "Signature verification failed")
33
21
  end
34
22
 
35
23
  def mgf1_hash_function
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OpenSSL
4
4
  module SignatureAlgorithm
5
- VERSION = "0.1.1"
5
+ VERSION = "1.1.0"
6
6
  end
7
7
  end
@@ -5,20 +5,15 @@ require_relative 'lib/openssl/signature_algorithm/version'
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "openssl-signature_algorithm"
7
7
  spec.version = OpenSSL::SignatureAlgorithm::VERSION
8
- spec.authors = ["Gonzalo"]
8
+ spec.authors = ["Gonzalo Rodriguez"]
9
9
  spec.email = ["gonzalo@cedarcode.com"]
10
10
  spec.license = "Apache-2.0"
11
11
 
12
- spec.summary = "Signature Algorithm abstraction for openssl ruby gem"
13
- spec.description = <<-DESC
14
- This tiny library introduces `OpenSSL::SignatureAlgorithm::ECDSA`,
15
- `OpenSSL::SignatureAlgorithm::RSAPSS` and `OpenSSL::SignatureAlgorithm::RSAPKCS1`,
16
- so that you can reason in terms of signature algorithms when signing and/or
17
- verifying signatures―instead of keys.
18
- DESC
12
+ spec.summary = "ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby"
13
+ spec.description = spec.summary
19
14
 
20
15
  spec.homepage = "https://github.com/cedarcode/openssl-signature_algorithm"
21
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
22
17
 
23
18
  spec.metadata["homepage_uri"] = spec.homepage
24
19
  spec.metadata["source_code_uri"] = spec.homepage
@@ -32,4 +27,6 @@ Gem::Specification.new do |spec|
32
27
  spec.bindir = "exe"
33
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
29
  spec.require_paths = ["lib"]
30
+
31
+ spec.add_runtime_dependency "openssl", "~> 2.0"
35
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.1.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
- - Gonzalo
7
+ - Gonzalo Rodriguez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-29 00:00:00.000000000 Z
12
- dependencies: []
13
- description: |2
14
- This tiny library introduces `OpenSSL::SignatureAlgorithm::ECDSA`,
15
- `OpenSSL::SignatureAlgorithm::RSAPSS` and `OpenSSL::SignatureAlgorithm::RSAPKCS1`,
16
- so that you can reason in terms of signature algorithms when signing and/or
17
- verifying signatures―instead of keys.
11
+ date: 2021-02-11 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,16 @@ files:
33
44
  - Rakefile
34
45
  - bin/console
35
46
  - bin/setup
47
+ - gemfiles/.bundle/config
48
+ - gemfiles/openssl_2_0.gemfile
49
+ - gemfiles/openssl_2_1.gemfile
50
+ - gemfiles/openssl_2_2.gemfile
36
51
  - lib/openssl/signature_algorithm.rb
37
52
  - lib/openssl/signature_algorithm/base.rb
38
53
  - lib/openssl/signature_algorithm/ecdsa.rb
54
+ - lib/openssl/signature_algorithm/eddsa.rb
39
55
  - lib/openssl/signature_algorithm/error.rb
56
+ - lib/openssl/signature_algorithm/rsa.rb
40
57
  - lib/openssl/signature_algorithm/rsapkcs1.rb
41
58
  - lib/openssl/signature_algorithm/rsapss.rb
42
59
  - lib/openssl/signature_algorithm/version.rb
@@ -56,15 +73,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
73
  requirements:
57
74
  - - ">="
58
75
  - !ruby/object:Gem::Version
59
- version: 2.5.0
76
+ version: 2.4.0
60
77
  required_rubygems_version: !ruby/object:Gem::Requirement
61
78
  requirements:
62
79
  - - ">="
63
80
  - !ruby/object:Gem::Version
64
81
  version: '0'
65
82
  requirements: []
66
- rubygems_version: 3.1.2
83
+ rubygems_version: 3.2.8
67
84
  signing_key:
68
85
  specification_version: 4
69
- summary: Signature Algorithm abstraction for openssl ruby gem
86
+ summary: ECDSA, EdDSA, RSA-PSS and RSA-PKCS#1 algorithms for ruby
70
87
  test_files: []
data/.travis.yml DELETED
@@ -1,8 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- - 2.6.5
7
- - 2.5.7
8
- before_install: gem install bundler -v 2.1.4