cose 1.2.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: a9bd8e1fa2c7e0f08d903f81ec2303a60a2377e6ba63c548b0c7f72d1c3197ee
4
- data.tar.gz: ccf797d8600edc7020c9248db5bfc60ffdfd7c07f11f7c39cad172116176430e
3
+ metadata.gz: 8a7da6d20b462494510800b95be262f6100a46b0b066c8255de6f1250a41429b
4
+ data.tar.gz: a758caf5a05445bc36b4c8e2e64f562c181546eb9740d065e48d2c3c5ea22726
5
5
  SHA512:
6
- metadata.gz: 5f27deece5637039eb3fd8ce9a8d33baf99c31fab75036462e40d599c4e0df789cf6f5ada85fcd4df75ebfddef91faa49132b0f08486f2e322e731cf2e217808
7
- data.tar.gz: 6eebcecddf4fc55ce1b8f7f219d9dc8bd37f1e01a18a4e3877b47b84398de883cae204d6013349e409836111b82c254a6374e9b104e552c4339ad7a94153df4b
6
+ metadata.gz: 47e4e46bb5e633a1e0eccb8fc9081411d1ff09439046f8ead15070aa2a2f3329d3b34e9744aa56a13a1cb0e6ff0490abc3148efe8e87d5d9efcaeb0f86fa514b
7
+ data.tar.gz: 2bc529d8091353b0a90a7b04b8e33d490371bfc87c43149a977cde769234b69e9645d9ca8c5677088a91faef8630806c24435ad304551fe467dba4d0cd421971
@@ -0,0 +1,42 @@
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:
19
+ - 3.0.0
20
+ - 2.7.2
21
+ - 2.6.6
22
+ - 2.5.8
23
+ - 2.4.10
24
+ gemfile:
25
+ - openssl_3_0
26
+ - openssl_2_2
27
+ - openssl_2_1
28
+ - openssl_default
29
+ exclude:
30
+ - ruby: '2.4.10'
31
+ gemfile: openssl_3_0
32
+ - ruby: '2.5.8'
33
+ gemfile: openssl_3_0
34
+ env:
35
+ BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
36
+ steps:
37
+ - uses: actions/checkout@v2
38
+ - uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: ${{ matrix.ruby }}
41
+ bundler-cache: true
42
+ - run: bundle exec rake
data/Appraisals CHANGED
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- appraise "openssl_head" do
4
- gem "openssl", git: "https://github.com/ruby/openssl"
5
- end
6
-
7
3
  appraise "openssl_2_2" do
8
4
  gem "openssl", "~> 2.2.0"
9
5
  end
@@ -12,8 +8,8 @@ appraise "openssl_2_1" do
12
8
  gem "openssl", "~> 2.1.0"
13
9
  end
14
10
 
15
- appraise "openssl_2_0" do
16
- gem "openssl", "~> 2.0.0"
11
+ appraise "openssl_3_0" do
12
+ gem "openssl", "~> 3.0.0"
17
13
  end
18
14
 
19
15
  appraise "openssl_default" do
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.3.0] - 2022-10-28
4
+
5
+ - Add support for EdDSA (#55). Credits to @bdewater.
6
+
7
+ ## [v1.2.1] - 2022-07-03
8
+
9
+ - Support OpenSSL ~>3.0.0. Credits to @ClearlyClaire <3
10
+
3
11
  ## [v1.2.0] - 2020-07-10
4
12
 
5
13
  ### Added
@@ -135,6 +143,8 @@ NOTE: No breaking changes. Moving out of `v0.x` to express the intention to keep
135
143
  - EC2 key object
136
144
  - Works with ruby 2.5
137
145
 
146
+ [v1.3.0]: https://github.com/cedarcode/cose-ruby/compare/v1.2.1...v1.3.0/
147
+ [v1.2.1]: https://github.com/cedarcode/cose-ruby/compare/v1.2.0...v1.2.1/
138
148
  [v1.2.0]: https://github.com/cedarcode/cose-ruby/compare/v1.1.0...v1.2.0/
139
149
  [v1.1.0]: https://github.com/cedarcode/cose-ruby/compare/v1.0.0...v1.1.0/
140
150
  [v1.0.0]: https://github.com/cedarcode/cose-ruby/compare/v0.11.0...v1.0.0/
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Ruby implementation of RFC [8152](https://tools.ietf.org/html/rfc8152) CBOR Object Signing and Encryption (COSE)
4
4
 
5
5
  [![Gem](https://img.shields.io/gem/v/cose.svg?style=flat-square&color=informational)](https://rubygems.org/gems/cose)
6
- [![Travis](https://img.shields.io/travis/cedarcode/cose-ruby.svg?style=flat-square)](https://travis-ci.org/cedarcode/cose-ruby)
6
+ [![Actions Build](https://github.com/cedarcode/cose-ruby/workflows/build/badge.svg)](https://github.com/cedarcode/cose-ruby/actions)
7
7
 
8
8
  ## Installation
9
9
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "openssl", "~> 2.0.0"
5
+ gem "openssl", "~> 3.0.0"
6
6
 
7
7
  gemspec path: "../"
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cose/algorithm/signature_algorithm"
4
+ require "cose/error"
5
+ require "cose/key/okp"
6
+ require "openssl"
7
+
8
+ module COSE
9
+ module Algorithm
10
+ class EdDSA < SignatureAlgorithm
11
+ private
12
+
13
+ def valid_key?(key)
14
+ cose_key = to_cose_key(key)
15
+
16
+ cose_key.is_a?(COSE::Key::OKP) && (!cose_key.alg || cose_key.alg == id)
17
+ end
18
+
19
+ def to_pkey(key)
20
+ case key
21
+ when COSE::Key::OKP
22
+ key.to_pkey
23
+ when OpenSSL::PKey::PKey
24
+ key
25
+ else
26
+ raise(COSE::Error, "Incompatible key for algorithm")
27
+ end
28
+ end
29
+
30
+ def valid_signature?(key, signature, verification_data)
31
+ pkey = to_pkey(key)
32
+
33
+ begin
34
+ pkey.verify(nil, signature, verification_data)
35
+ rescue OpenSSL::PKey::PKeyError
36
+ false
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cose/algorithm/ecdsa"
4
+ require "cose/algorithm/eddsa"
4
5
  require "cose/algorithm/hmac"
5
6
  require "cose/algorithm/rsa_pss"
6
7
 
@@ -30,6 +31,7 @@ module COSE
30
31
  register(ECDSA.new(-35, "ES384", hash_function: "SHA384", curve_name: "P-384"))
31
32
  register(ECDSA.new(-36, "ES512", hash_function: "SHA512", curve_name: "P-521"))
32
33
  register(ECDSA.new(-47, "ES256K", hash_function: "SHA256", curve_name: "secp256k1"))
34
+ register(EdDSA.new(-8, "EdDSA"))
33
35
  register(RSAPSS.new(-37, "PS256", hash_function: "SHA256", salt_length: 32))
34
36
  register(RSAPSS.new(-38, "PS384", hash_function: "SHA384", salt_length: 48))
35
37
  register(RSAPSS.new(-39, "PS512", hash_function: "SHA512", salt_length: 64))
@@ -32,4 +32,6 @@ end
32
32
  COSE::Key::Curve.register(1, "P-256", "prime256v1")
33
33
  COSE::Key::Curve.register(2, "P-384", "secp384r1")
34
34
  COSE::Key::Curve.register(3, "P-521", "secp521r1")
35
+ COSE::Key::Curve.register(6, "Ed25519", "ED25519")
36
+ COSE::Key::Curve.register(7, "Ed448", "ED448")
35
37
  COSE::Key::Curve.register(8, "secp256k1", "secp256k1")
data/lib/cose/key/ec2.rb CHANGED
@@ -68,16 +68,39 @@ module COSE
68
68
  def to_pkey
69
69
  if curve
70
70
  group = OpenSSL::PKey::EC::Group.new(curve.pkey_name)
71
- pkey = OpenSSL::PKey::EC.new(group)
72
71
  public_key_bn = OpenSSL::BN.new("\x04" + x + y, 2)
73
72
  public_key_point = OpenSSL::PKey::EC::Point.new(group, public_key_bn)
74
- pkey.public_key = public_key_point
73
+
74
+ # RFC5480 SubjectPublicKeyInfo
75
+ asn1 = OpenSSL::ASN1::Sequence(
76
+ [
77
+ OpenSSL::ASN1::Sequence(
78
+ [
79
+ OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
80
+ OpenSSL::ASN1::ObjectId(curve.pkey_name),
81
+ ]
82
+ ),
83
+ OpenSSL::ASN1::BitString(public_key_point.to_octet_string(:uncompressed))
84
+ ]
85
+ )
75
86
 
76
87
  if d
77
- pkey.private_key = OpenSSL::BN.new(d, 2)
88
+ # RFC5915 ECPrivateKey
89
+ asn1 = OpenSSL::ASN1::Sequence(
90
+ [
91
+ OpenSSL::ASN1::Integer.new(1),
92
+ # Not properly padded but OpenSSL doesn't mind
93
+ OpenSSL::ASN1::OctetString(OpenSSL::BN.new(d, 2).to_s(2)),
94
+ OpenSSL::ASN1::ObjectId(curve.pkey_name, 0, :EXPLICIT),
95
+ OpenSSL::ASN1::BitString(public_key_point.to_octet_string(:uncompressed), 1, :EXPLICIT),
96
+ ]
97
+ )
98
+
99
+ der = asn1.to_der
100
+ return OpenSSL::PKey::EC.new(der)
78
101
  end
79
102
 
80
- pkey
103
+ OpenSSL::PKey::EC.new(asn1.to_der)
81
104
  else
82
105
  raise "Unsupported curve #{crv}"
83
106
  end
data/lib/cose/key/okp.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cose/key/curve"
3
4
  require "cose/key/curve_key"
4
5
  require "openssl"
5
6
 
@@ -14,9 +15,56 @@ module COSE
14
15
  end
15
16
  end
16
17
 
18
+ def self.from_pkey(pkey)
19
+ curve = Curve.by_pkey_name(pkey.oid) || raise("Unsupported edwards curve #{pkey.oid}")
20
+ attributes = { crv: curve.id }
21
+
22
+ asymmetric_key = pkey.public_to_der
23
+ public_key_bit_string = OpenSSL::ASN1.decode(asymmetric_key).value.last.value
24
+ attributes[:x] = public_key_bit_string
25
+ begin
26
+ asymmetric_key = pkey.private_to_der
27
+ private_key = OpenSSL::ASN1.decode(asymmetric_key).value.last.value
28
+ curve_private_key = OpenSSL::ASN1.decode(private_key).value
29
+ attributes[:d] = curve_private_key
30
+ rescue OpenSSL::PKey::PKeyError
31
+ # work around lack of https://github.com/ruby/openssl/pull/527, otherwise raises this error
32
+ # with message 'i2d_PKCS8PrivateKey_bio: error converting private key' for public keys
33
+ nil
34
+ end
35
+
36
+ new(**attributes)
37
+ end
38
+
17
39
  def map
18
40
  super.merge(LABEL_KTY => KTY_OKP)
19
41
  end
42
+
43
+ def to_pkey
44
+ if curve
45
+ private_key_algo = OpenSSL::ASN1::Sequence.new(
46
+ [OpenSSL::ASN1::ObjectId.new(curve.pkey_name)]
47
+ )
48
+ seq = if d
49
+ version = OpenSSL::ASN1::Integer.new(0)
50
+ curve_private_key = OpenSSL::ASN1::OctetString.new(d).to_der
51
+ private_key = OpenSSL::ASN1::OctetString.new(curve_private_key)
52
+ [version, private_key_algo, private_key]
53
+ else
54
+ public_key = OpenSSL::ASN1::BitString.new(x)
55
+ [private_key_algo, public_key]
56
+ end
57
+
58
+ asymmetric_key = OpenSSL::ASN1::Sequence.new(seq)
59
+ OpenSSL::PKey.read(asymmetric_key.to_der)
60
+ else
61
+ raise "Unsupported curve #{crv}"
62
+ end
63
+ end
64
+
65
+ def curve
66
+ Curve.find(crv)
67
+ end
20
68
  end
21
69
  end
22
70
  end
data/lib/cose/key/rsa.rb CHANGED
@@ -88,31 +88,32 @@ module COSE
88
88
  end
89
89
 
90
90
  def to_pkey
91
- pkey = OpenSSL::PKey::RSA.new
92
-
93
- if pkey.respond_to?(:set_key)
94
- pkey.set_key(bn(n), bn(e), bn(d))
95
- else
96
- pkey.n = bn(n)
97
- pkey.e = bn(e)
98
- pkey.d = bn(d)
99
- end
91
+ # PKCS#1 RSAPublicKey
92
+ asn1 = OpenSSL::ASN1::Sequence(
93
+ [
94
+ OpenSSL::ASN1::Integer.new(bn(n)),
95
+ OpenSSL::ASN1::Integer.new(bn(e)),
96
+ ]
97
+ )
98
+ pkey = OpenSSL::PKey::RSA.new(asn1.to_der)
100
99
 
101
100
  if private?
102
- if pkey.respond_to?(:set_factors)
103
- pkey.set_factors(bn(p), bn(q))
104
- else
105
- pkey.p = bn(p)
106
- pkey.q = bn(q)
107
- end
101
+ # PKCS#1 RSAPrivateKey
102
+ asn1 = OpenSSL::ASN1::Sequence(
103
+ [
104
+ OpenSSL::ASN1::Integer.new(0),
105
+ OpenSSL::ASN1::Integer.new(bn(n)),
106
+ OpenSSL::ASN1::Integer.new(bn(e)),
107
+ OpenSSL::ASN1::Integer.new(bn(d)),
108
+ OpenSSL::ASN1::Integer.new(bn(p)),
109
+ OpenSSL::ASN1::Integer.new(bn(q)),
110
+ OpenSSL::ASN1::Integer.new(bn(dp)),
111
+ OpenSSL::ASN1::Integer.new(bn(dq)),
112
+ OpenSSL::ASN1::Integer.new(bn(qinv)),
113
+ ]
114
+ )
108
115
 
109
- if pkey.respond_to?(:set_crt_params)
110
- pkey.set_crt_params(bn(dp), bn(dq), bn(qinv))
111
- else
112
- pkey.dmp1 = bn(dp)
113
- pkey.dmq1 = bn(dq)
114
- pkey.iqmp = bn(qinv)
115
- end
116
+ pkey = OpenSSL::PKey::RSA.new(asn1.to_der)
116
117
  end
117
118
 
118
119
  pkey
data/lib/cose/key.rb CHANGED
@@ -24,6 +24,8 @@ module COSE
24
24
  COSE::Key::EC2.from_pkey(pkey)
25
25
  when OpenSSL::PKey::RSA
26
26
  COSE::Key::RSA.from_pkey(pkey)
27
+ when OpenSSL::PKey::PKey
28
+ COSE::Key::OKP.from_pkey(pkey)
27
29
  else
28
30
  raise "Unsupported #{pkey.class} object"
29
31
  end
data/lib/cose/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module COSE
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.0"
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cose
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
8
8
  - Braulio Martinez
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-07-10 00:00:00.000000000 Z
12
+ date: 2022-10-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cbor
@@ -143,7 +143,7 @@ dependencies:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
145
  version: '1.4'
146
- description:
146
+ description:
147
147
  email:
148
148
  - gonzalo@cedarcode.com
149
149
  - braulio@cedarcode.com
@@ -151,11 +151,11 @@ executables: []
151
151
  extensions: []
152
152
  extra_rdoc_files: []
153
153
  files:
154
+ - ".github/workflows/build.yml"
154
155
  - ".gitignore"
155
156
  - ".gitmodules"
156
157
  - ".rspec"
157
158
  - ".rubocop.yml"
158
- - ".travis.yml"
159
159
  - Appraisals
160
160
  - CHANGELOG.md
161
161
  - Gemfile
@@ -166,15 +166,15 @@ files:
166
166
  - bin/console
167
167
  - bin/setup
168
168
  - cose.gemspec
169
- - gemfiles/openssl_2_0.gemfile
170
169
  - gemfiles/openssl_2_1.gemfile
171
170
  - gemfiles/openssl_2_2.gemfile
171
+ - gemfiles/openssl_3_0.gemfile
172
172
  - gemfiles/openssl_default.gemfile
173
- - gemfiles/openssl_head.gemfile
174
173
  - lib/cose.rb
175
174
  - lib/cose/algorithm.rb
176
175
  - lib/cose/algorithm/base.rb
177
176
  - lib/cose/algorithm/ecdsa.rb
177
+ - lib/cose/algorithm/eddsa.rb
178
178
  - lib/cose/algorithm/hmac.rb
179
179
  - lib/cose/algorithm/rsa_pss.rb
180
180
  - lib/cose/algorithm/signature_algorithm.rb
@@ -205,7 +205,7 @@ metadata:
205
205
  bug_tracker_uri: https://github.com/cedarcode/cose-ruby/issues
206
206
  changelog_uri: https://github.com/cedarcode/cose-ruby/blob/master/CHANGELOG.md
207
207
  source_code_uri: https://github.com/cedarcode/cose-ruby
208
- post_install_message:
208
+ post_install_message:
209
209
  rdoc_options: []
210
210
  require_paths:
211
211
  - lib
@@ -220,8 +220,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
220
  - !ruby/object:Gem::Version
221
221
  version: '0'
222
222
  requirements: []
223
- rubygems_version: 3.1.4
224
- signing_key:
223
+ rubygems_version: 3.2.32
224
+ signing_key:
225
225
  specification_version: 4
226
226
  summary: Ruby implementation of RFC 8152 CBOR Object Signing and Encryption (COSE)
227
227
  test_files: []
data/.travis.yml DELETED
@@ -1,25 +0,0 @@
1
- dist: bionic
2
- language: ruby
3
- cache: bundler
4
-
5
- rvm:
6
- - ruby-head
7
- - 2.7.1
8
- - 2.6.6
9
- - 2.5.8
10
- - 2.4.10
11
-
12
- gemfile:
13
- - gemfiles/openssl_head.gemfile
14
- - gemfiles/openssl_2_2.gemfile
15
- - gemfiles/openssl_2_1.gemfile
16
- - gemfiles/openssl_2_0.gemfile
17
- - gemfiles/openssl_default.gemfile
18
-
19
- before_install: gem install bundler -v '~> 2.0'
20
-
21
- matrix:
22
- fast_finish: true
23
- allow_failures:
24
- - rvm: ruby-head
25
- - gemfile: gemfiles/openssl_head.gemfile
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", git: "https://github.com/ruby/openssl"
6
-
7
- gemspec path: "../"