cose 0.4.1 → 0.5.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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +8 -2
- data/Appraisals +7 -0
- data/CHANGELOG.md +10 -0
- data/README.md +59 -18
- data/cose.gemspec +1 -0
- data/gemfiles/openssl_2_0.gemfile +7 -0
- data/gemfiles/openssl_2_1.gemfile +7 -0
- data/lib/cose/key.rb +12 -0
- data/lib/cose/key/ec2.rb +67 -0
- data/lib/cose/key/rsa.rb +85 -2
- data/lib/cose/version.rb +1 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb978af65e0e7ba43a06e776b45792856bec76e58a7ce6d1d3d88619c6fca09e
|
4
|
+
data.tar.gz: c8cdf73b87523e266c36076c542cf91bb5e252bda826523308b4adc355ce1c6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc8f10f840915de994963318cf3fb5f138eb836bd391280029cceb7b5b4c9a95577dd281be1d67f1dc36def4a5a809af6e4ff665dc26e0cf30990219248cf043
|
7
|
+
data.tar.gz: 87ec47c8278246a0fdbec217a1d13b6588aed62400bfd49010d4573dab75b70a436867fe8d4fb895b784bbe29783c28e2910f576f213aeda8d830662f1067f7f
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
|
+
|
3
4
|
rvm:
|
4
5
|
- ruby-head
|
5
|
-
- 2.6.
|
6
|
-
- 2.5.
|
6
|
+
- 2.6.2
|
7
|
+
- 2.5.4
|
7
8
|
- 2.4.5
|
9
|
+
|
10
|
+
gemfile:
|
11
|
+
- gemfiles/openssl_2_0.gemfile
|
12
|
+
- gemfiles/openssl_2_1.gemfile
|
13
|
+
|
8
14
|
before_install: gem install bundler -v 2.0.1
|
9
15
|
|
10
16
|
matrix:
|
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v0.5.0] - 2019-03-25
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- `COSE::Key.serialize(openssl_pkey)` serializes an `OpenSSL::PKey::PKey` object into CBOR data. Supports RSA keys plus
|
8
|
+
EC keys from curves prime256v1, secp384r1 and secp521r1.
|
9
|
+
- `COSE::Key::EC2#to_pkey` converts to an `OpenSSL::PKey::EC` object
|
10
|
+
- `COSE::Key::RSA#to_pkey` converts to an `OpenSSL::PKey::RSA` object
|
11
|
+
|
3
12
|
## [v0.4.1] - 2019-03-12
|
4
13
|
|
5
14
|
### Fixed
|
@@ -45,6 +54,7 @@
|
|
45
54
|
- EC2 key object
|
46
55
|
- Works with ruby 2.5
|
47
56
|
|
57
|
+
[v0.5.0]: https://github.com/cedarcode/cose-ruby/compare/v0.4.1...v0.5.0/
|
48
58
|
[v0.4.1]: https://github.com/cedarcode/cose-ruby/compare/v0.4.0...v0.4.1/
|
49
59
|
[v0.4.0]: https://github.com/cedarcode/cose-ruby/compare/v0.3.0...v0.4.0/
|
50
60
|
[v0.3.0]: https://github.com/cedarcode/cose-ruby/compare/v0.2.0...v0.3.0/
|
data/README.md
CHANGED
@@ -25,12 +25,23 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
### Key Objects
|
27
27
|
|
28
|
+
#### Deserialization (from CBOR to Ruby objects)
|
29
|
+
|
28
30
|
```ruby
|
29
31
|
cbor_data = "..."
|
30
32
|
|
31
|
-
|
33
|
+
cose_key = COSE::Key.deserialize(cbor_data)
|
34
|
+
```
|
35
|
+
|
36
|
+
Once you have a `COSE::Key` instance you can either access key parameters directly and/or convert it to an
|
37
|
+
`OpenSSL::PKey::PKey` instance for operating with it (encrypting/decrypting, signing/verifying, etc).
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
# Convert to an OpenSSL::PKey::PKey
|
41
|
+
openssl_pkey = cose_key.to_pkey
|
32
42
|
|
33
|
-
|
43
|
+
# Access COSE key parameters
|
44
|
+
case key
|
34
45
|
when COSE::Key::EC2
|
35
46
|
key.curve
|
36
47
|
key.x_coordinate
|
@@ -39,43 +50,73 @@ when COSE::Key::EC2
|
|
39
50
|
when COSE::Key::RSA
|
40
51
|
key.modulus_n
|
41
52
|
key.public_exponent_e
|
53
|
+
key.private_exponent_d
|
54
|
+
key.prime_factor_p
|
55
|
+
key.prime_factor_q
|
56
|
+
key.d_p
|
57
|
+
key.d_q
|
58
|
+
key.q_inv
|
42
59
|
when COSE::Key::Symmetric
|
43
60
|
key.key_value
|
44
61
|
end
|
45
62
|
```
|
46
63
|
|
47
|
-
|
64
|
+
If you already know which COSE key type is encoded in the CBOR data, then:
|
48
65
|
|
49
66
|
```ruby
|
50
|
-
|
67
|
+
ec2_key_cbor = "..."
|
68
|
+
|
69
|
+
cose_ec2_key = COSE::Key::EC2.deserialize(ec2_key_cbor)
|
70
|
+
|
71
|
+
cose_ec2_key.curve
|
72
|
+
cose_ec2_key.x_coordinate
|
73
|
+
cose_ec2_key.y_coordinate
|
74
|
+
cose_ec2_key.d_coordinate
|
51
75
|
|
52
|
-
|
76
|
+
# or
|
53
77
|
|
54
|
-
|
55
|
-
key.x_coordinate
|
56
|
-
key.y_coordinate
|
57
|
-
key.d_coordinate
|
78
|
+
ec_pkey = cose_ec2_key.to_pkey # Instance of an OpenSSL::PKey::EC
|
58
79
|
```
|
59
80
|
|
60
|
-
|
81
|
+
```ruby
|
82
|
+
symmetric_key_cbor = "..."
|
83
|
+
|
84
|
+
cose_symmetric_key = COSE::Key::Symmetric.deserialize(symmetric_key_cbor)
|
85
|
+
|
86
|
+
cose_symmetric_key.key_value
|
87
|
+
```
|
61
88
|
|
62
89
|
```ruby
|
63
|
-
|
90
|
+
rsa_key_cbor = "..."
|
91
|
+
|
92
|
+
cose_rsa_key = COSE::Key::RSA.deserialize(rsa_key_cbor)
|
93
|
+
|
94
|
+
cose_rsa_key.modulus_n
|
95
|
+
cose_rsa_key.public_exponent_e
|
96
|
+
cose_rsa_key.private_exponent_d
|
97
|
+
cose_rsa_key.prime_factor_p
|
98
|
+
cose_rsa_key.prime_factor_q
|
99
|
+
cose_rsa_key.d_p
|
100
|
+
cose_rsa_key.d_q
|
101
|
+
cose_rsa_key.q_inv
|
64
102
|
|
65
|
-
|
103
|
+
# or
|
66
104
|
|
67
|
-
|
105
|
+
rsa_pkey = cose_rsa_key.to_pkey # Instance of an OpenSSL::PKey::RSA
|
68
106
|
```
|
69
107
|
|
70
|
-
####
|
108
|
+
#### Serialization (from Ruby objects to CBOR)
|
71
109
|
|
72
110
|
```ruby
|
73
|
-
|
111
|
+
ec_pkey = OpenSSL::PKey::EC.new("prime256v1").generate_key
|
112
|
+
|
113
|
+
cose_ec2_key_cbor = COSE::Key.serialize(ec_pkey)
|
114
|
+
```
|
74
115
|
|
75
|
-
|
116
|
+
```ruby
|
117
|
+
rsa_pkey = OpenSSL::PKey::RSA.new(2048)
|
76
118
|
|
77
|
-
|
78
|
-
key.public_exponent_e
|
119
|
+
cose_rsa_key_cbor = COSE::Key.serialize(rsa_pkey)
|
79
120
|
```
|
80
121
|
|
81
122
|
### Signing Objects
|
data/cose.gemspec
CHANGED
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
|
34
34
|
spec.add_dependency "cbor", "~> 0.5.9.2"
|
35
35
|
|
36
|
+
spec.add_development_dependency "appraisal", "~> 2.2.0"
|
36
37
|
spec.add_development_dependency "bundler", ">= 1.17", "< 3"
|
37
38
|
spec.add_development_dependency "byebug", "~> 11.0"
|
38
39
|
spec.add_development_dependency "rake", "~> 12.3"
|
data/lib/cose/key.rb
CHANGED
@@ -2,11 +2,23 @@ require "cbor"
|
|
2
2
|
require "cose/key/ec2"
|
3
3
|
require "cose/key/rsa"
|
4
4
|
require "cose/key/symmetric"
|
5
|
+
require "openssl"
|
5
6
|
|
6
7
|
module COSE
|
7
8
|
class UnknownKeyType < StandardError; end
|
8
9
|
|
9
10
|
module Key
|
11
|
+
def self.serialize(pkey)
|
12
|
+
case pkey
|
13
|
+
when OpenSSL::PKey::EC, OpenSSL::PKey::EC::Point
|
14
|
+
COSE::Key::EC2.from_pkey(pkey).serialize
|
15
|
+
when OpenSSL::PKey::RSA
|
16
|
+
COSE::Key::RSA.from_pkey(pkey).serialize
|
17
|
+
else
|
18
|
+
raise "Unsupported serialization of #{pkey.class} object"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
10
22
|
def self.deserialize(data)
|
11
23
|
map = CBOR.decode(data)
|
12
24
|
|
data/lib/cose/key/ec2.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "cose/key/base"
|
4
|
+
require "openssl"
|
4
5
|
|
5
6
|
module COSE
|
6
7
|
module Key
|
@@ -13,6 +14,44 @@ module COSE
|
|
13
14
|
Y_LABEL = -3
|
14
15
|
|
15
16
|
KTY_EC2 = 2
|
17
|
+
CRV_P256 = 1
|
18
|
+
CRV_P384 = 2
|
19
|
+
CRV_P521 = 3
|
20
|
+
|
21
|
+
PKEY_CURVES = {
|
22
|
+
CRV_P256 => "prime256v1",
|
23
|
+
CRV_P384 => "secp384r1",
|
24
|
+
CRV_P521 => "secp521r1"
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
def self.from_pkey(pkey)
|
28
|
+
curve = PKEY_CURVES.key(pkey.group.curve_name) || raise("Unsupported EC curve #{pkey.group.curve_name}")
|
29
|
+
|
30
|
+
case pkey
|
31
|
+
when OpenSSL::PKey::EC::Point
|
32
|
+
public_key = pkey
|
33
|
+
when OpenSSL::PKey::EC
|
34
|
+
public_key = pkey.public_key
|
35
|
+
private_key = pkey.private_key
|
36
|
+
else
|
37
|
+
raise "Unsupported"
|
38
|
+
end
|
39
|
+
|
40
|
+
if public_key
|
41
|
+
bytes = public_key.to_bn.to_s(2)[1..-1]
|
42
|
+
|
43
|
+
coordinate_length = bytes.size / 2
|
44
|
+
|
45
|
+
x_coordinate = bytes[0..(coordinate_length - 1)]
|
46
|
+
y_coordinate = bytes[coordinate_length..-1]
|
47
|
+
end
|
48
|
+
|
49
|
+
if private_key
|
50
|
+
d_coordinate = private_key.to_s(2)
|
51
|
+
end
|
52
|
+
|
53
|
+
new(curve: curve, x_coordinate: x_coordinate, y_coordinate: y_coordinate, d_coordinate: d_coordinate)
|
54
|
+
end
|
16
55
|
|
17
56
|
attr_reader :algorithm, :curve, :d_coordinate, :x_coordinate, :y_coordinate
|
18
57
|
|
@@ -32,6 +71,34 @@ module COSE
|
|
32
71
|
end
|
33
72
|
end
|
34
73
|
|
74
|
+
def serialize
|
75
|
+
CBOR.encode(
|
76
|
+
Base::LABEL_KTY => KTY_EC2,
|
77
|
+
CRV_LABEL => curve,
|
78
|
+
X_LABEL => x_coordinate,
|
79
|
+
Y_LABEL => y_coordinate,
|
80
|
+
D_LABEL => d_coordinate
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_pkey
|
85
|
+
if PKEY_CURVES[curve]
|
86
|
+
group = OpenSSL::PKey::EC::Group.new(PKEY_CURVES[curve])
|
87
|
+
pkey = OpenSSL::PKey::EC.new(group)
|
88
|
+
public_key_bn = OpenSSL::BN.new("\x04" + x_coordinate + y_coordinate, 2)
|
89
|
+
public_key_point = OpenSSL::PKey::EC::Point.new(group, public_key_bn)
|
90
|
+
pkey.public_key = public_key_point
|
91
|
+
|
92
|
+
if d_coordinate
|
93
|
+
pkey.private_key = OpenSSL::BN.new(d_coordinate, 2)
|
94
|
+
end
|
95
|
+
|
96
|
+
pkey
|
97
|
+
else
|
98
|
+
raise "Unsupported curve #{curve}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
35
102
|
def self.from_map(map)
|
36
103
|
enforce_type(map, KTY_EC2, "Not an EC2 key")
|
37
104
|
|
data/lib/cose/key/rsa.rb
CHANGED
@@ -1,18 +1,65 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "cose/key/base"
|
4
|
+
require "openssl"
|
4
5
|
|
5
6
|
module COSE
|
6
7
|
module Key
|
7
8
|
class RSA < Base
|
8
9
|
LABEL_N = -1
|
9
10
|
LABEL_E = -2
|
11
|
+
LABEL_D = -3
|
12
|
+
LABEL_P = -4
|
13
|
+
LABEL_Q = -5
|
14
|
+
LABEL_D_P = -6
|
15
|
+
LABEL_D_Q = -7
|
16
|
+
LABEL_Q_INV = -8
|
10
17
|
|
11
18
|
KTY_RSA = 3
|
12
19
|
|
13
|
-
|
20
|
+
def self.from_pkey(pkey)
|
21
|
+
params = pkey.params
|
14
22
|
|
15
|
-
|
23
|
+
attributes = {
|
24
|
+
modulus_n: params["n"].to_s(2),
|
25
|
+
public_exponent_e: params["e"].to_s(2)
|
26
|
+
}
|
27
|
+
|
28
|
+
if pkey.private?
|
29
|
+
attributes.merge!(
|
30
|
+
private_exponent_d: params["d"].to_s(2),
|
31
|
+
prime_factor_p: params["p"].to_s(2),
|
32
|
+
prime_factor_q: params["q"].to_s(2),
|
33
|
+
d_p: params["dmp1"].to_s(2),
|
34
|
+
d_q: params["dmq1"].to_s(2),
|
35
|
+
q_inv: params["iqmp"].to_s(2)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
new(attributes)
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader(
|
43
|
+
:modulus_n,
|
44
|
+
:public_exponent_e,
|
45
|
+
:private_exponent_d,
|
46
|
+
:prime_factor_p,
|
47
|
+
:prime_factor_q,
|
48
|
+
:d_p,
|
49
|
+
:d_q,
|
50
|
+
:q_inv
|
51
|
+
)
|
52
|
+
|
53
|
+
def initialize(
|
54
|
+
modulus_n:,
|
55
|
+
public_exponent_e:,
|
56
|
+
private_exponent_d: nil,
|
57
|
+
prime_factor_p: nil,
|
58
|
+
prime_factor_q: nil,
|
59
|
+
d_p: nil,
|
60
|
+
d_q: nil,
|
61
|
+
q_inv: nil
|
62
|
+
)
|
16
63
|
if !modulus_n
|
17
64
|
raise ArgumentError, "Required modulus_n is missing"
|
18
65
|
elsif !public_exponent_e
|
@@ -20,14 +67,50 @@ module COSE
|
|
20
67
|
else
|
21
68
|
@modulus_n = modulus_n
|
22
69
|
@public_exponent_e = public_exponent_e
|
70
|
+
@private_exponent_d = private_exponent_d
|
71
|
+
@prime_factor_p = prime_factor_p
|
72
|
+
@prime_factor_q = prime_factor_q
|
73
|
+
@d_p = d_p
|
74
|
+
@d_q = d_q
|
75
|
+
@q_inv = q_inv
|
23
76
|
end
|
24
77
|
end
|
25
78
|
|
79
|
+
def serialize
|
80
|
+
CBOR.encode(
|
81
|
+
Base::LABEL_KTY => KTY_RSA,
|
82
|
+
LABEL_N => modulus_n,
|
83
|
+
LABEL_E => public_exponent_e,
|
84
|
+
LABEL_D => private_exponent_d,
|
85
|
+
LABEL_P => prime_factor_p,
|
86
|
+
LABEL_Q => prime_factor_q,
|
87
|
+
LABEL_D_P => d_p,
|
88
|
+
LABEL_D_Q => d_q,
|
89
|
+
LABEL_Q_INV => q_inv
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_pkey
|
94
|
+
pkey = OpenSSL::PKey::RSA.new
|
95
|
+
|
96
|
+
pkey.set_key(bn(modulus_n), bn(public_exponent_e), bn(private_exponent_d))
|
97
|
+
pkey.set_factors(bn(prime_factor_p), bn(prime_factor_q))
|
98
|
+
pkey.set_crt_params(bn(d_p), bn(d_q), bn(q_inv))
|
99
|
+
|
100
|
+
pkey
|
101
|
+
end
|
102
|
+
|
26
103
|
def self.from_map(map)
|
27
104
|
enforce_type(map, KTY_RSA, "Not an RSA key")
|
28
105
|
|
29
106
|
new(modulus_n: map[LABEL_N], public_exponent_e: map[LABEL_E])
|
30
107
|
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def bn(data)
|
112
|
+
OpenSSL::BN.new(data, 2)
|
113
|
+
end
|
31
114
|
end
|
32
115
|
end
|
33
116
|
end
|
data/lib/cose/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gonzalo Rodriguez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-03-
|
12
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cbor
|
@@ -25,6 +25,20 @@ dependencies:
|
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 0.5.9.2
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: appraisal
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.2.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 2.2.0
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: bundler
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,6 +127,7 @@ files:
|
|
113
127
|
- ".rspec"
|
114
128
|
- ".rubocop.yml"
|
115
129
|
- ".travis.yml"
|
130
|
+
- Appraisals
|
116
131
|
- CHANGELOG.md
|
117
132
|
- Gemfile
|
118
133
|
- LICENSE.txt
|
@@ -121,6 +136,8 @@ files:
|
|
121
136
|
- bin/console
|
122
137
|
- bin/setup
|
123
138
|
- cose.gemspec
|
139
|
+
- gemfiles/openssl_2_0.gemfile
|
140
|
+
- gemfiles/openssl_2_1.gemfile
|
124
141
|
- lib/cose.rb
|
125
142
|
- lib/cose/encrypt.rb
|
126
143
|
- lib/cose/encrypt0.rb
|