pkcs7-cryptographer 0.1.0 → 1.0.1

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: c3b2d20fdc0a9804d2e748fbb952795720231ac668903f8e7bc3843194147c5f
4
- data.tar.gz: 8fe66251f456e340ef033201d4e865920780c89d5c46fc16af49095eb9a373b9
3
+ metadata.gz: a02040b2706a005f695860704e338946e5cb68c6dcbf92fc7a2bb9c17b9425b2
4
+ data.tar.gz: 52a840fb9394002e9400e31a0d4960b0fefcfcab4466ce2535c3afcd2915932a
5
5
  SHA512:
6
- metadata.gz: e7285b506e68a68533b7623d83d54a8ab2335505c10fe161784ea6040207fe935890f02e44745b49568605d8fb81653a5ab2b6db1dea59374f666b0103e0076c
7
- data.tar.gz: 89710d821aa0f16cc5e695d2506718738b5c8c05f3a7bbfb76eb7ef333cbe4abf604016616ca09487150fb8827aad1c0cf0670c4164f659666576b2dd73402a1
6
+ metadata.gz: 83d51e4785b3eff57409208a09956c29826e2dde08c75a7b87e340f70b129f2f80614b4c5792e159618354ae97059eff2febd58a01ce08c460758fba0feb9e52
7
+ data.tar.gz: 139e5b0e31cdfeed9c67468f92a21dc2f9f36bc3f207fe941df54194e199f43b2681e79072b5e1ea67f33696dd5422c4bf34595377845ea579cccb22487f85fe
data/.rubocop.yml CHANGED
@@ -1,6 +1,9 @@
1
+ require:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
1
5
  AllCops:
2
6
  NewCops: enable
3
- SuggestExtensions: false
4
7
  Style/StringLiterals:
5
8
  Enabled: true
6
9
  EnforcedStyle: double_quotes
@@ -13,4 +16,13 @@ Layout/LineLength:
13
16
  Max: 80
14
17
 
15
18
  Metrics/BlockLength:
16
- IgnoredMethods: ['describe', 'context']
19
+ IgnoredMethods: ['describe', 'context']
20
+
21
+ RSpec/MultipleMemoizedHelpers:
22
+ Enabled: false
23
+
24
+ RSpec/NestedGroups:
25
+ Max: 6
26
+
27
+ RSpec/ExampleLength:
28
+ Max: 10
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pkcs7-cryptographer (0.1.0)
4
+ pkcs7-cryptographer (1.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -33,19 +33,24 @@ GEM
33
33
  diff-lcs (>= 1.2.0, < 2.0)
34
34
  rspec-support (~> 3.10.0)
35
35
  rspec-support (3.10.2)
36
- rubocop (0.93.1)
36
+ rubocop (1.12.0)
37
37
  parallel (~> 1.10)
38
- parser (>= 2.7.1.5)
38
+ parser (>= 3.0.0.0)
39
39
  rainbow (>= 2.2.2, < 4.0)
40
- regexp_parser (>= 1.8)
40
+ regexp_parser (>= 1.8, < 3.0)
41
41
  rexml
42
- rubocop-ast (>= 0.6.0)
42
+ rubocop-ast (>= 1.2.0, < 2.0)
43
43
  ruby-progressbar (~> 1.7)
44
- unicode-display_width (>= 1.4.0, < 2.0)
44
+ unicode-display_width (>= 1.4.0, < 3.0)
45
45
  rubocop-ast (1.4.1)
46
46
  parser (>= 2.7.1.5)
47
+ rubocop-rake (0.5.1)
48
+ rubocop
49
+ rubocop-rspec (2.2.0)
50
+ rubocop (~> 1.0)
51
+ rubocop-ast (>= 1.1.0)
47
52
  ruby-progressbar (1.11.0)
48
- unicode-display_width (1.7.0)
53
+ unicode-display_width (2.0.0)
49
54
 
50
55
  PLATFORMS
51
56
  x86_64-darwin-19
@@ -56,7 +61,9 @@ DEPENDENCIES
56
61
  pry
57
62
  rake (~> 13.0)
58
63
  rspec (~> 3.2)
59
- rubocop (~> 0.80)
64
+ rubocop (= 1.12.0)
65
+ rubocop-rake (= 0.5.1)
66
+ rubocop-rspec (= 2.2.0)
60
67
 
61
68
  BUNDLED WITH
62
69
  2.2.3
data/README.md CHANGED
@@ -1,11 +1,16 @@
1
1
  # PKCS7::Cryptographer
2
2
 
3
- Cryptographer is an small utility that allows to encrypt and decrypt messages
3
+ [![Gem Version](https://badge.fury.io/rb/pkcs7-cryptographer.svg)](https://badge.fury.io/rb/pkcs7-cryptographer)
4
+ ![main workflow](https://github.com/dmuneras/pkcs7-cryptographer/actions/workflows/main.yml/badge.svg)
5
+
6
+
7
+ Cryptographer is an small utility to encrypt, sign and decrypt messages
4
8
  using PKCS7.
5
9
 
6
- PKCS7 is used to store signed and encrypted data.It uses aes-256-cbc
7
- as chipher in the encryption process. If you want to read more information about
8
- the involved data structures and theory around this, please visit:
10
+ PKCS7 is used to store signed and encrypted data.This specific implementation
11
+ uses `aes-256-cbc` as chipher in the encryption process. If you want to read
12
+ more information about the involved data structures and theory around this,
13
+ please visit:
9
14
 
10
15
  - https://ruby-doc.org/stdlib-3.0.0/libdoc/openssl/rdoc/OpenSSL.html
11
16
  - https://tools.ietf.org/html/rfc5652
@@ -20,30 +25,39 @@ gem 'pkcs7-cryptographer'
20
25
 
21
26
  And then execute:
22
27
 
28
+ ```sh
23
29
  $ bundle install
30
+ ```
24
31
 
25
32
  Or install it yourself as:
26
33
 
34
+ ```sh
27
35
  $ gem install pkcs7-cryptographer
28
-
36
+ ```
29
37
  ## Usage
30
38
 
39
+ ### Using bare PKCS7::Cryptographer
40
+
31
41
  After installing the gem you will have the `PKCS7::Cryptographer` available.
32
42
 
33
- `PKCS7::Cryptographer` is a class that provides to public methods:
43
+ `PKCS7::Cryptographer` is a class that provides two public methods:
34
44
 
35
45
  - `sign_and_encrypt`
36
46
  - `decrypt_and_verify`
37
47
 
38
- Read the following example to get a better undertanding:
48
+ If you want to use the barebones cryptographer, you can. Please look at the
49
+ following example:
50
+
51
+
39
52
 
40
53
  ```ruby
54
+ require 'pkcs7/cryptographer'
41
55
 
42
56
  # This script assumes you have a read_file method to read the certificates and
43
57
  # keys.
44
58
 
45
- # What we are going to do is sign an encrypt a message from the CA Authority
46
- # and read it from the Client:
59
+ # What we are going to do is signing an encrypting a message from the CA
60
+ # Authority and read it from the Client:
47
61
 
48
62
  # Certificate Authority PKI data
49
63
  CA_KEY = read_file("ca.key")
@@ -59,9 +73,11 @@ Read the following example to get a better undertanding:
59
73
  # Only the client can read the message since the required public
60
74
  # certificate to read it is the client certificate.
61
75
 
62
- # It could be read if the CA_STORE of the reader has certificate of the
76
+ # It could be read if the CA_STORE of the reader has the certificate of the
63
77
  # CA that signed the client certificate as trusted.
64
78
 
79
+ cryptographer = PKCS7::Cryptographer.new
80
+
65
81
  # Client <------------------------- CA Authority API
66
82
  encrypted_data = cryptographer.sign_and_encrypt(
67
83
  data: "Atletico Nacional de Medellin",
@@ -70,6 +86,8 @@ Read the following example to get a better undertanding:
70
86
  public_certificate: CLIENT_CERTIFICATE
71
87
  )
72
88
 
89
+ # encrypted_data is a PEM formatted string
90
+
73
91
  # READ MESSAGE IN CLIENT
74
92
  # ----------------------------------------------------------------------------
75
93
  # Store of trusted certificates
@@ -87,6 +105,98 @@ Read the following example to get a better undertanding:
87
105
  # decrypted_data returns: "Atletico Nacional de Medellin"
88
106
  ```
89
107
 
108
+ ### Using PKCS7::Cryptographer::Entity
109
+
110
+ There is a possibility to use entities to communicate using encrypted data. In
111
+ order to use it you have to import the entities implementation.
112
+
113
+ Please look at the following example:
114
+
115
+ ```ruby
116
+
117
+ require 'pkcs7/cryptographer'
118
+ require 'pkcs7/cryptographer/entity'
119
+
120
+ # This script assumes you have a read_file method to read the certificates and
121
+ # keys. If you have any question about how to generate the keys/certificates
122
+ # check this post: https://mariadb.com/kb/en/certificate-creation-with-openssl/
123
+
124
+ # What we are going to do is sending a message from the CA Authority and read
125
+ # it from the Client:
126
+
127
+ # Certificate Authority PKI data
128
+ CA_KEY = read_file("ca.key")
129
+ CA_CERTIFICATE = read_file("ca.crt")
130
+
131
+ # Client PKI data
132
+ CLIENT_CERTIFICATE = read_file("client.crt")
133
+
134
+ CA_STORE = OpenSSL::X509::Store.new
135
+ CA_STORE.add_cert(OpenSSL::X509::Certificate.new(CA_CERTIFICATE))
136
+
137
+ ca_entity = PKCS7::Cryptographer::Entity.new(
138
+ key: CA_KEY,
139
+ certificate: CA_CERTIFICATE,
140
+ ca_store: CA_STORE
141
+ )
142
+
143
+ client_entity = PKCS7::Cryptographer::Entity.new(
144
+ certificate: CLIENT_CERTIFICATE
145
+ )
146
+
147
+ # SEND MESSAGE TO THE CLIENT
148
+ # ----------------------------------------------------------------------------
149
+ data = "Victor Ibarbo"
150
+ encrypted_data = ca_entity.encrypt_data(data: data, receiver: client_entity)
151
+
152
+ # READ MESSAGE IN CLIENT
153
+ # ----------------------------------------------------------------------------
154
+ decrypted_data = client_entity.decrypt_data(
155
+ data: encrypted_data,
156
+ sender: ca_entity
157
+ )
158
+
159
+ # decrypted_data returns: "Victor Ibarbo"
160
+ ```
161
+
162
+ When using entities, all the complexity of knowing which PKI credentials to
163
+ send to the cryptographer dissapears. You only need to initialize the
164
+ entities and use the methods to indicate to whom the message will be sent.
165
+
166
+ If you want to verify if certain entity you defined "trust" another one, use the
167
+ `trustable_entity?(<the other entity>)`.
168
+
169
+ ```ruby
170
+ ca_entity = PKCS7::Cryptographer::Entity.new(
171
+ key: CA_KEY,
172
+ certificate: CA_CERTIFICATE,
173
+ ca_store: CA_STORE
174
+ )
175
+
176
+ client_entity = PKCS7::Cryptographer::Entity.new(
177
+ certificate: CLIENT_CERTIFICATE
178
+ )
179
+
180
+ ca_entity.trustable_entity?(client_entity)
181
+
182
+ # Returns true because the client certificate was signed by the root
183
+ # certificate of the ca_authority.
184
+ ```
185
+
186
+ When sending data to an entity, you will most of the time initialize the entity
187
+ only with the `certificate` keyword arguments. So, initializing a receiver will
188
+ most of the time looks like this:
189
+
190
+ ```ruby
191
+ client_entity = PKCS7::Cryptographer::Entity.new(
192
+ certificate: CLIENT_CERTIFICATE
193
+ )
194
+ ```
195
+
196
+ The entity above can't encrypt messages or decrypt them, if you want to decrypt
197
+ and encrypt the entity should have its the key (private key), certificate and
198
+ the list of trusted certificates of the entity (ca_store).
199
+
90
200
  ## Development
91
201
 
92
202
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
data/bin/console CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "bundler/setup"
5
5
  require "pkcs7/cryptographer"
6
+ require "pkcs7/cryptographer/entity"
6
7
 
7
8
  # You can add fixtures and/or initialization code here to make experimenting
8
9
  # with your gem easier. You can also use a different console, if you like.
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "openssl"
4
4
  require_relative "cryptographer/version"
5
+ require_relative "cryptographer/initializers"
5
6
 
6
7
  module PKCS7
7
8
  ###
@@ -14,6 +15,8 @@ module PKCS7
14
15
  # - https://tools.ietf.org/html/rfc5652
15
16
  ###
16
17
  class Cryptographer
18
+ include PKCS7::Cryptographer::Initializers
19
+
17
20
  # PUBLIC METHODS
18
21
  # --------------------------------------------------------------------------
19
22
 
@@ -36,12 +39,7 @@ module PKCS7
36
39
  certificate = x509_certificate(certificate)
37
40
  public_certificate = x509_certificate(public_certificate)
38
41
  signed_data = OpenSSL::PKCS7.sign(certificate, key, data)
39
-
40
- encrypted_data = OpenSSL::PKCS7.encrypt(
41
- [public_certificate],
42
- signed_data.to_pem,
43
- OpenSSL::Cipher.new("aes-256-cbc")
44
- )
42
+ encrypted_data = encrypt(public_certificate, signed_data)
45
43
 
46
44
  encrypted_data.to_pem
47
45
  end
@@ -69,31 +67,33 @@ module PKCS7
69
67
  public_certificate = x509_certificate(public_certificate)
70
68
  encrypted_data = pkcs7(data)
71
69
  decrypted_data = encrypted_data.decrypt(key, certificate)
70
+
72
71
  signed_data = OpenSSL::PKCS7.new(decrypted_data)
72
+ verified = verified_signature?(signed_data, public_certificate, ca_store)
73
73
 
74
- return false unless signed_data.verify([public_certificate], ca_store)
74
+ return false unless verified
75
75
 
76
76
  signed_data.data
77
77
  end
78
78
 
79
- # PRIVATE METHODS
80
- # --------------------------------------------------------------------------
81
79
  private
82
80
 
83
- def x509_certificate(certificate)
84
- wrap_in_class_or_return(certificate, OpenSSL::X509::Certificate)
85
- end
86
-
87
- def rsa_key(key)
88
- wrap_in_class_or_return(key, OpenSSL::PKey::RSA)
89
- end
90
-
91
- def pkcs7(pkcs7)
92
- wrap_in_class_or_return(pkcs7, OpenSSL::PKCS7)
81
+ def encrypt(public_certificate, signed_data)
82
+ OpenSSL::PKCS7.encrypt(
83
+ [public_certificate],
84
+ signed_data.to_der,
85
+ OpenSSL::Cipher.new("aes-256-cbc"),
86
+ OpenSSL::PKCS7::BINARY
87
+ )
93
88
  end
94
89
 
95
- def wrap_in_class_or_return(data, klass)
96
- data.instance_of?(klass) ? data : klass.new(data)
90
+ def verified_signature?(signed_data, public_certificate, ca_store)
91
+ signed_data.verify(
92
+ [public_certificate],
93
+ ca_store,
94
+ nil,
95
+ OpenSSL::PKCS7::NOINTERN | OpenSSL::PKCS7::NOCHAIN
96
+ )
97
97
  end
98
98
  end
99
99
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "initializers"
4
+
5
+ module PKCS7
6
+ class Cryptographer
7
+ ###
8
+ # Define an entity abel to decrypt or encrypt messages to send them to other
9
+ # entities. It uses a Cryptographer to do the dirty work and just provide a
10
+ # more human readable way to read an pass messages between trustable
11
+ # entities.
12
+ ###
13
+ class Entity
14
+ include PKCS7::Cryptographer::Initializers
15
+
16
+ attr_reader :certificate
17
+
18
+ # PUBLIC METHODS
19
+ # ------------------------------------------------------------------------
20
+ def initialize(
21
+ certificate:,
22
+ key: nil,
23
+ ca_store: OpenSSL::X509::Store.new
24
+ )
25
+ @key = key ? rsa_key(key) : nil
26
+ @certificate = x509_certificate(certificate)
27
+ @cryptographer = PKCS7::Cryptographer.new
28
+ @ca_store = ca_store
29
+ end
30
+
31
+ def trustable_entity?(entity)
32
+ @ca_store.verify(entity.certificate)
33
+ end
34
+
35
+ def encrypt_data(data:, receiver:)
36
+ perform_safely(receiver) do
37
+ @cryptographer.sign_and_encrypt(
38
+ data: data,
39
+ key: @key,
40
+ certificate: @certificate,
41
+ public_certificate: receiver.certificate
42
+ )
43
+ end
44
+ end
45
+
46
+ def decrypt_data(data:, sender:)
47
+ perform_safely(sender) do
48
+ @cryptographer.decrypt_and_verify(
49
+ data: data,
50
+ key: @key,
51
+ certificate: @certificate,
52
+ public_certificate: sender.certificate,
53
+ ca_store: @ca_store
54
+ )
55
+ end
56
+ end
57
+
58
+ # PRIVATE METHODS
59
+ # ------------------------------------------------------------------------
60
+ private
61
+
62
+ def perform_safely(entity)
63
+ return false unless trustable_entity?(entity)
64
+ return false unless @key
65
+
66
+ yield
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PKCS7
4
+ class Cryptographer
5
+ ###
6
+ # Provides a set of methods to initialize OpenSSL objects if necessary. It
7
+ # allow consumers to pass either the OpenSSL ruby objects or the
8
+ # certificate, key or encrypted message string.
9
+ ###
10
+ module Initializers
11
+ # PRIVATE METHODS
12
+ # ------------------------------------------------------------------------
13
+
14
+ private
15
+
16
+ def x509_certificate(certificate)
17
+ wrap_in_class_or_return(certificate, OpenSSL::X509::Certificate)
18
+ end
19
+
20
+ def rsa_key(key)
21
+ wrap_in_class_or_return(key, OpenSSL::PKey::RSA)
22
+ end
23
+
24
+ def pkcs7(pkcs7)
25
+ wrap_in_class_or_return(pkcs7, OpenSSL::PKCS7)
26
+ end
27
+
28
+ def wrap_in_class_or_return(data, klass)
29
+ data.instance_of?(klass) ? data : klass.new(data)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module PKCS7
4
4
  class Cryptographer
5
- VERSION = "0.1.0"
5
+ VERSION = "1.0.1"
6
6
  end
7
7
  end
@@ -31,5 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "pry"
32
32
  spec.add_development_dependency "rake", "~> 13.0"
33
33
  spec.add_development_dependency "rspec", "~> 3.2"
34
- spec.add_development_dependency "rubocop", "~> 0.80"
34
+ spec.add_development_dependency "rubocop", "1.12.0"
35
+ spec.add_development_dependency "rubocop-rake", "0.5.1"
36
+ spec.add_development_dependency "rubocop-rspec", "2.2.0"
35
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pkcs7-cryptographer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Munera Sanchez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-24 00:00:00.000000000 Z
11
+ date: 2021-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,16 +70,44 @@ dependencies:
70
70
  name: rubocop
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: '0.80'
75
+ version: 1.12.0
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.12.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.5.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.5.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 2.2.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
81
109
  - !ruby/object:Gem::Version
82
- version: '0.80'
110
+ version: 2.2.0
83
111
  description: Utility to encrypt and decrypt messages using OpenSSL::PKCS7
84
112
  email:
85
113
  - dmunera119@gmail.com
@@ -100,6 +128,8 @@ files:
100
128
  - bin/console
101
129
  - bin/setup
102
130
  - lib/pkcs7/cryptographer.rb
131
+ - lib/pkcs7/cryptographer/entity.rb
132
+ - lib/pkcs7/cryptographer/initializers.rb
103
133
  - lib/pkcs7/cryptographer/version.rb
104
134
  - pkcs7-cryptographer.gemspec
105
135
  homepage: https://github.com/dmuneras/pkcs7-cryptographer