cose 1.2.0 → 1.3.0

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 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: "../"