certificate_authority 0.1.2 → 1.0.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 +7 -0
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -8
- data/Gemfile.lock +71 -27
- data/README.rdoc +184 -89
- data/Rakefile +6 -41
- data/certificate_authority.gemspec +22 -81
- data/lib/certificate_authority.rb +7 -6
- data/lib/certificate_authority/certificate.rb +151 -71
- data/lib/certificate_authority/certificate_revocation_list.rb +46 -26
- data/lib/certificate_authority/core_extensions.rb +46 -0
- data/lib/certificate_authority/distinguished_name.rb +84 -17
- data/lib/certificate_authority/extensions.rb +483 -96
- data/lib/certificate_authority/key_material.rb +75 -21
- data/lib/certificate_authority/ocsp_handler.rb +99 -29
- data/lib/certificate_authority/pkcs11_key_material.rb +13 -15
- data/lib/certificate_authority/revocable.rb +14 -0
- data/lib/certificate_authority/serial_number.rb +18 -5
- data/lib/certificate_authority/signing_entity.rb +5 -7
- data/lib/certificate_authority/signing_request.rb +91 -0
- data/lib/certificate_authority/validations.rb +31 -0
- data/lib/certificate_authority/version.rb +3 -0
- metadata +96 -94
- data/VERSION.yml +0 -5
- data/spec/spec_helper.rb +0 -4
- data/spec/units/certificate_authority_spec.rb +0 -4
- data/spec/units/certificate_revocation_list_spec.rb +0 -68
- data/spec/units/certificate_spec.rb +0 -351
- data/spec/units/distinguished_name_spec.rb +0 -38
- data/spec/units/extensions_spec.rb +0 -53
- data/spec/units/key_material_spec.rb +0 -96
- data/spec/units/ocsp_handler_spec.rb +0 -104
- data/spec/units/serial_number_spec.rb +0 -20
- data/spec/units/signing_entity_spec.rb +0 -4
- data/spec/units/units_helper.rb +0 -1
data/Rakefile
CHANGED
@@ -1,35 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require 'rspec/core/rake_task'
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "rubocop/rake_task"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
rescue Bundler::BundlerError => e
|
9
|
-
$stderr.puts e.message
|
10
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
-
exit e.status_code
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'rake'
|
15
|
-
|
16
|
-
desc 'Default: run specs.'
|
17
|
-
task :default => :spec
|
18
|
-
|
19
|
-
require 'jeweler'
|
20
|
-
Jeweler::Tasks.new do |gem|
|
21
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
22
|
-
gem.name = "certificate_authority"
|
23
|
-
gem.homepage = "http://github.com/cchandler/certificate_authority"
|
24
|
-
gem.license = "MIT"
|
25
|
-
gem.summary = 'Ruby gem for managing the core functions outlined in RFC-3280 for PKI'
|
26
|
-
# gem.description = ''
|
27
|
-
gem.email = "chris@flatterline.com"
|
28
|
-
gem.authors = ["Chris Chandler"]
|
29
|
-
|
30
|
-
# gem.add_dependency('activemodel', '3.0.6')
|
31
|
-
end
|
32
|
-
Jeweler::RubygemsDotOrgTasks.new
|
5
|
+
desc "Default: run specs."
|
6
|
+
task default: %i[spec]
|
33
7
|
|
34
8
|
task :spec do
|
35
9
|
Rake::Task["spec:units"].invoke
|
@@ -38,15 +12,6 @@ end
|
|
38
12
|
namespace :spec do
|
39
13
|
desc "Run unit specs."
|
40
14
|
RSpec::Core::RakeTask.new(:units) do |t|
|
41
|
-
t.rspec_opts = [
|
15
|
+
t.rspec_opts = ["--colour --format progress --tag ~pkcs11"]
|
42
16
|
end
|
43
|
-
|
44
|
-
desc "Run integration specs."
|
45
|
-
RSpec::Core::RakeTask.new(:integrations) do |t|
|
46
|
-
t.rspec_opts = ['--colour --format progress']
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
RSpec::Core::RakeTask.new(:doc) do |t|
|
51
|
-
t.rspec_opts = ['--format specdoc ']
|
52
17
|
end
|
@@ -1,87 +1,28 @@
|
|
1
|
-
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
1
|
+
require File.expand_path("lib/certificate_authority/version", __dir__)
|
5
2
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "certificate_authority"
|
5
|
+
spec.version = CertificateAuthority::VERSION
|
6
|
+
spec.authors = ["Chris Chandler"]
|
7
|
+
spec.email = ["squanderingtime@gmail.com"]
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
s.email = %q{chris@flatterline.com}
|
14
|
-
s.extra_rdoc_files = [
|
15
|
-
"README.rdoc"
|
16
|
-
]
|
17
|
-
s.files = [
|
18
|
-
"Gemfile",
|
19
|
-
"Gemfile.lock",
|
20
|
-
"README.rdoc",
|
21
|
-
"Rakefile",
|
22
|
-
"VERSION.yml",
|
23
|
-
"certificate_authority.gemspec",
|
24
|
-
"lib/certificate_authority.rb",
|
25
|
-
"lib/certificate_authority/certificate.rb",
|
26
|
-
"lib/certificate_authority/certificate_revocation_list.rb",
|
27
|
-
"lib/certificate_authority/distinguished_name.rb",
|
28
|
-
"lib/certificate_authority/extensions.rb",
|
29
|
-
"lib/certificate_authority/key_material.rb",
|
30
|
-
"lib/certificate_authority/ocsp_handler.rb",
|
31
|
-
"lib/certificate_authority/pkcs11_key_material.rb",
|
32
|
-
"lib/certificate_authority/serial_number.rb",
|
33
|
-
"lib/certificate_authority/signing_entity.rb",
|
34
|
-
"lib/tasks/certificate_authority.rake",
|
35
|
-
"spec/spec_helper.rb",
|
36
|
-
"spec/units/certificate_authority_spec.rb",
|
37
|
-
"spec/units/certificate_revocation_list_spec.rb",
|
38
|
-
"spec/units/certificate_spec.rb",
|
39
|
-
"spec/units/distinguished_name_spec.rb",
|
40
|
-
"spec/units/extensions_spec.rb",
|
41
|
-
"spec/units/key_material_spec.rb",
|
42
|
-
"spec/units/ocsp_handler_spec.rb",
|
43
|
-
"spec/units/serial_number_spec.rb",
|
44
|
-
"spec/units/signing_entity_spec.rb",
|
45
|
-
"spec/units/units_helper.rb"
|
46
|
-
]
|
47
|
-
s.homepage = %q{http://github.com/cchandler/certificate_authority}
|
48
|
-
s.licenses = ["MIT"]
|
49
|
-
s.require_paths = ["lib"]
|
50
|
-
s.rubygems_version = %q{1.7.2}
|
51
|
-
s.summary = %q{Ruby gem for managing the core functions outlined in RFC-3280 for PKI}
|
52
|
-
s.test_files = [
|
53
|
-
"spec/spec_helper.rb",
|
54
|
-
"spec/units/certificate_authority_spec.rb",
|
55
|
-
"spec/units/certificate_revocation_list_spec.rb",
|
56
|
-
"spec/units/certificate_spec.rb",
|
57
|
-
"spec/units/distinguished_name_spec.rb",
|
58
|
-
"spec/units/extensions_spec.rb",
|
59
|
-
"spec/units/key_material_spec.rb",
|
60
|
-
"spec/units/ocsp_handler_spec.rb",
|
61
|
-
"spec/units/serial_number_spec.rb",
|
62
|
-
"spec/units/signing_entity_spec.rb",
|
63
|
-
"spec/units/units_helper.rb"
|
64
|
-
]
|
9
|
+
spec.summary = "Ruby gem for managing the core functions outlined in RFC-3280 for PKI"
|
10
|
+
spec.homepage = "https://github.com/cchandler/certificate_authority"
|
11
|
+
spec.license = "MIT"
|
65
12
|
|
66
|
-
|
67
|
-
|
13
|
+
spec.metadata["homepage_uri"] = "https://github.com/cchandler/certificate_authority"
|
14
|
+
spec.metadata["source_code_uri"] = "https://github.com/cchandler/certificate_authority"
|
68
15
|
|
69
|
-
|
70
|
-
|
71
|
-
s.add_development_dependency(%q<rspec>, [">= 0"])
|
72
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
73
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
74
|
-
else
|
75
|
-
s.add_dependency(%q<activemodel>, ["~> 3.0.6"])
|
76
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
77
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
78
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
79
|
-
end
|
80
|
-
else
|
81
|
-
s.add_dependency(%q<activemodel>, ["~> 3.0.6"])
|
82
|
-
s.add_dependency(%q<rspec>, [">= 0"])
|
83
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
84
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
16
|
+
spec.files = Dir.chdir(__dir__) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec/)}) }
|
85
18
|
end
|
86
|
-
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = ">= 2.4"
|
87
22
|
|
23
|
+
spec.add_development_dependency "coveralls"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "rubocop"
|
28
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#Exterior requirements
|
1
|
+
# Exterior requirements
|
4
2
|
require 'openssl'
|
5
|
-
require 'active_model'
|
6
3
|
|
7
|
-
#Internal modules
|
4
|
+
# Internal modules
|
5
|
+
require 'certificate_authority/core_extensions'
|
8
6
|
require 'certificate_authority/signing_entity'
|
7
|
+
require 'certificate_authority/revocable'
|
8
|
+
require 'certificate_authority/validations'
|
9
9
|
require 'certificate_authority/distinguished_name'
|
10
10
|
require 'certificate_authority/serial_number'
|
11
11
|
require 'certificate_authority/key_material'
|
@@ -14,6 +14,7 @@ require 'certificate_authority/extensions'
|
|
14
14
|
require 'certificate_authority/certificate'
|
15
15
|
require 'certificate_authority/certificate_revocation_list'
|
16
16
|
require 'certificate_authority/ocsp_handler'
|
17
|
+
require 'certificate_authority/signing_request'
|
17
18
|
|
18
19
|
module CertificateAuthority
|
19
|
-
end
|
20
|
+
end
|
@@ -1,68 +1,88 @@
|
|
1
1
|
module CertificateAuthority
|
2
2
|
class Certificate
|
3
|
-
|
4
|
-
include
|
5
|
-
|
3
|
+
include Validations
|
4
|
+
include Revocable
|
5
|
+
|
6
6
|
attr_accessor :distinguished_name
|
7
7
|
attr_accessor :serial_number
|
8
8
|
attr_accessor :key_material
|
9
9
|
attr_accessor :not_before
|
10
10
|
attr_accessor :not_after
|
11
|
-
attr_accessor :revoked_at
|
12
11
|
attr_accessor :extensions
|
13
12
|
attr_accessor :openssl_body
|
14
|
-
|
13
|
+
|
15
14
|
alias :subject :distinguished_name #Same thing as the DN
|
16
|
-
|
15
|
+
|
17
16
|
attr_accessor :parent
|
18
|
-
|
19
|
-
validate
|
17
|
+
|
18
|
+
def validate
|
20
19
|
errors.add :base, "Distinguished name must be valid" unless distinguished_name.valid?
|
21
|
-
errors.add :base, "Key material
|
20
|
+
errors.add :base, "Key material must be valid" unless key_material.valid?
|
22
21
|
errors.add :base, "Serial number must be valid" unless serial_number.valid?
|
23
22
|
errors.add :base, "Extensions must be valid" unless extensions.each do |item|
|
24
|
-
|
25
|
-
|
23
|
+
unless item.respond_to?(:valid?)
|
24
|
+
true
|
25
|
+
else
|
26
|
+
item.valid?
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
|
-
|
30
|
+
|
29
31
|
def initialize
|
30
32
|
self.distinguished_name = DistinguishedName.new
|
31
33
|
self.serial_number = SerialNumber.new
|
32
34
|
self.key_material = MemoryKeyMaterial.new
|
33
|
-
self.not_before =
|
34
|
-
self.not_after =
|
35
|
+
self.not_before = Date.today.utc
|
36
|
+
self.not_after = Date.today.advance(:years => 1).utc
|
35
37
|
self.parent = self
|
36
38
|
self.extensions = load_extensions()
|
37
|
-
|
39
|
+
|
38
40
|
self.signing_entity = false
|
39
|
-
|
41
|
+
|
40
42
|
end
|
41
|
-
|
43
|
+
|
44
|
+
=begin
|
45
|
+
def self.from_openssl openssl_cert
|
46
|
+
unless openssl_cert.is_a? OpenSSL::X509::Certificate
|
47
|
+
raise "Can only construct from an OpenSSL::X509::Certificate"
|
48
|
+
end
|
49
|
+
|
50
|
+
certificate = Certificate.new
|
51
|
+
# Only subject, key_material, and body are used for signing
|
52
|
+
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
|
53
|
+
certificate.key_material.public_key = openssl_cert.public_key
|
54
|
+
certificate.openssl_body = openssl_cert
|
55
|
+
certificate.serial_number.number = openssl_cert.serial.to_i
|
56
|
+
certificate.not_before = openssl_cert.not_before
|
57
|
+
certificate.not_after = openssl_cert.not_after
|
58
|
+
# TODO extensions
|
59
|
+
certificate
|
60
|
+
end
|
61
|
+
=end
|
62
|
+
|
42
63
|
def sign!(signing_profile={})
|
43
64
|
raise "Invalid certificate #{self.errors.full_messages}" unless valid?
|
44
65
|
merge_profile_with_extensions(signing_profile)
|
45
|
-
|
66
|
+
|
46
67
|
openssl_cert = OpenSSL::X509::Certificate.new
|
47
|
-
openssl_cert.version
|
68
|
+
openssl_cert.version = 2
|
48
69
|
openssl_cert.not_before = self.not_before
|
49
70
|
openssl_cert.not_after = self.not_after
|
50
71
|
openssl_cert.public_key = self.key_material.public_key
|
51
|
-
|
72
|
+
|
52
73
|
openssl_cert.serial = self.serial_number.number
|
53
|
-
|
74
|
+
|
54
75
|
openssl_cert.subject = self.distinguished_name.to_x509_name
|
55
76
|
openssl_cert.issuer = parent.distinguished_name.to_x509_name
|
56
|
-
|
77
|
+
|
57
78
|
require 'tempfile'
|
58
79
|
t = Tempfile.new("bullshit_conf")
|
59
|
-
# t = File.new("/tmp/openssl.cnf")
|
60
80
|
## The config requires a file even though we won't use it
|
61
81
|
openssl_config = OpenSSL::Config.new(t.path)
|
62
|
-
|
82
|
+
|
63
83
|
factory = OpenSSL::X509::ExtensionFactory.new
|
64
84
|
factory.subject_certificate = openssl_cert
|
65
|
-
|
85
|
+
|
66
86
|
#NB: If the parent doesn't have an SSL body we're making this a self-signed cert
|
67
87
|
if parent.openssl_body.nil?
|
68
88
|
factory.issuer_certificate = openssl_cert
|
@@ -74,51 +94,85 @@ module CertificateAuthority
|
|
74
94
|
config_extensions = extensions[k].config_extensions
|
75
95
|
openssl_config = merge_options(openssl_config,config_extensions)
|
76
96
|
end
|
77
|
-
|
97
|
+
|
78
98
|
# p openssl_config.sections
|
79
|
-
|
99
|
+
|
80
100
|
factory.config = openssl_config
|
81
|
-
|
82
|
-
|
101
|
+
|
102
|
+
# Order matters: e.g. for self-signed, subjectKeyIdentifier must come before authorityKeyIdentifier
|
103
|
+
self.extensions.keys.sort{|a,b| b<=>a}.each do |k|
|
83
104
|
e = extensions[k]
|
84
105
|
next if e.to_s.nil? or e.to_s == "" ## If the extension returns an empty string we won't include it
|
85
|
-
ext = factory.create_ext(e.openssl_identifier, e.to_s)
|
106
|
+
ext = factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
86
107
|
openssl_cert.add_extension(ext)
|
87
108
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
109
|
+
|
110
|
+
if signing_profile["digest"].nil?
|
111
|
+
digest = OpenSSL::Digest.new("SHA512")
|
112
|
+
else
|
113
|
+
digest = OpenSSL::Digest.new(signing_profile["digest"])
|
114
|
+
end
|
115
|
+
|
116
|
+
self.openssl_body = openssl_cert.sign(parent.key_material.private_key, digest)
|
117
|
+
ensure
|
118
|
+
t.close! if t # We can get rid of the ridiculous temp file
|
93
119
|
end
|
94
|
-
|
120
|
+
|
95
121
|
def is_signing_entity?
|
96
122
|
self.extensions["basicConstraints"].ca
|
97
123
|
end
|
98
|
-
|
124
|
+
|
99
125
|
def signing_entity=(signing)
|
100
126
|
self.extensions["basicConstraints"].ca = signing
|
101
127
|
end
|
102
|
-
|
128
|
+
|
103
129
|
def revoked?
|
104
130
|
!self.revoked_at.nil?
|
105
131
|
end
|
106
|
-
|
132
|
+
|
107
133
|
def to_pem
|
108
134
|
raise "Certificate has no signed body" if self.openssl_body.nil?
|
109
135
|
self.openssl_body.to_pem
|
110
136
|
end
|
111
|
-
|
137
|
+
|
138
|
+
def to_csr
|
139
|
+
csr = SigningRequest.new
|
140
|
+
csr.distinguished_name = self.distinguished_name
|
141
|
+
csr.key_material = self.key_material
|
142
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
143
|
+
exts = []
|
144
|
+
self.extensions.keys.each do |k|
|
145
|
+
## Don't copy over key identifiers for CSRs
|
146
|
+
next if k == "subjectKeyIdentifier" || k == "authorityKeyIdentifier"
|
147
|
+
e = extensions[k]
|
148
|
+
## If the extension returns an empty string we won't include it
|
149
|
+
next if e.to_s.nil? or e.to_s == ""
|
150
|
+
exts << factory.create_ext(e.openssl_identifier, e.to_s, e.critical)
|
151
|
+
end
|
152
|
+
attrval = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(exts)])
|
153
|
+
attrs = [
|
154
|
+
OpenSSL::X509::Attribute.new("extReq", attrval),
|
155
|
+
OpenSSL::X509::Attribute.new("msExtReq", attrval)
|
156
|
+
]
|
157
|
+
csr.attributes = attrs
|
158
|
+
csr
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.from_x509_cert(raw_cert)
|
162
|
+
openssl_cert = OpenSSL::X509::Certificate.new(raw_cert)
|
163
|
+
Certificate.from_openssl(openssl_cert)
|
164
|
+
end
|
165
|
+
|
112
166
|
def is_root_entity?
|
113
167
|
self.parent == self && is_signing_entity?
|
114
168
|
end
|
115
|
-
|
169
|
+
|
116
170
|
def is_intermediate_entity?
|
117
171
|
(self.parent != self) && is_signing_entity?
|
118
172
|
end
|
119
|
-
|
173
|
+
|
120
174
|
private
|
121
|
-
|
175
|
+
|
122
176
|
def merge_profile_with_extensions(signing_profile={})
|
123
177
|
return self.extensions if signing_profile["extensions"].nil?
|
124
178
|
signing_config = signing_profile["extensions"]
|
@@ -127,50 +181,76 @@ module CertificateAuthority
|
|
127
181
|
items = signing_config[k]
|
128
182
|
items.keys.each do |profile_item_key|
|
129
183
|
if extension.respond_to?("#{profile_item_key}=".to_sym)
|
130
|
-
|
184
|
+
if k == 'subjectAltName' && profile_item_key == 'emails'
|
185
|
+
items[profile_item_key].map do |email|
|
186
|
+
if email == 'email:copy'
|
187
|
+
fail "no email address provided for subject: #{subject.to_x509_name}" unless subject.email_address
|
188
|
+
"email:#{subject.email_address}"
|
189
|
+
else
|
190
|
+
email
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
extension.send("#{profile_item_key}=".to_sym, items[profile_item_key] )
|
131
195
|
else
|
132
196
|
p "Tried applying '#{profile_item_key}' to #{extension.class} but it doesn't respond!"
|
133
197
|
end
|
134
198
|
end
|
135
199
|
end
|
136
200
|
end
|
137
|
-
|
201
|
+
|
202
|
+
# Enumeration of the extensions. Not the worst option since
|
203
|
+
# the likelihood of these needing to be updated is low at best.
|
204
|
+
EXTENSIONS = [
|
205
|
+
CertificateAuthority::Extensions::BasicConstraints,
|
206
|
+
CertificateAuthority::Extensions::CrlDistributionPoints,
|
207
|
+
CertificateAuthority::Extensions::SubjectKeyIdentifier,
|
208
|
+
CertificateAuthority::Extensions::AuthorityKeyIdentifier,
|
209
|
+
CertificateAuthority::Extensions::AuthorityInfoAccess,
|
210
|
+
CertificateAuthority::Extensions::KeyUsage,
|
211
|
+
CertificateAuthority::Extensions::ExtendedKeyUsage,
|
212
|
+
CertificateAuthority::Extensions::SubjectAlternativeName,
|
213
|
+
CertificateAuthority::Extensions::CertificatePolicies
|
214
|
+
]
|
215
|
+
|
138
216
|
def load_extensions
|
139
217
|
extension_hash = {}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
temp_extensions << basic_constraints
|
144
|
-
crl_distribution_points = CertificateAuthority::Extensions::CrlDistributionPoints.new
|
145
|
-
temp_extensions << crl_distribution_points
|
146
|
-
subject_key_identifier = CertificateAuthority::Extensions::SubjectKeyIdentifier.new
|
147
|
-
temp_extensions << subject_key_identifier
|
148
|
-
authority_key_identifier = CertificateAuthority::Extensions::AuthorityKeyIdentifier.new
|
149
|
-
temp_extensions << authority_key_identifier
|
150
|
-
authority_info_access = CertificateAuthority::Extensions::AuthorityInfoAccess.new
|
151
|
-
temp_extensions << authority_info_access
|
152
|
-
key_usage = CertificateAuthority::Extensions::KeyUsage.new
|
153
|
-
temp_extensions << key_usage
|
154
|
-
extended_key_usage = CertificateAuthority::Extensions::ExtendedKeyUsage.new
|
155
|
-
temp_extensions << extended_key_usage
|
156
|
-
subject_alternative_name = CertificateAuthority::Extensions::SubjectAlternativeName.new
|
157
|
-
temp_extensions << subject_alternative_name
|
158
|
-
certificate_policies = CertificateAuthority::Extensions::CertificatePolicies.new
|
159
|
-
temp_extensions << certificate_policies
|
160
|
-
|
161
|
-
temp_extensions.each do |extension|
|
218
|
+
|
219
|
+
EXTENSIONS.each do |klass|
|
220
|
+
extension = klass.new
|
162
221
|
extension_hash[extension.openssl_identifier] = extension
|
163
222
|
end
|
164
|
-
|
223
|
+
|
165
224
|
extension_hash
|
166
225
|
end
|
167
|
-
|
226
|
+
|
168
227
|
def merge_options(config,hash)
|
169
228
|
hash.keys.each do |k|
|
170
229
|
config[k] = hash[k]
|
171
230
|
end
|
172
231
|
config
|
173
232
|
end
|
174
|
-
|
233
|
+
|
234
|
+
def self.from_openssl openssl_cert
|
235
|
+
unless openssl_cert.is_a? OpenSSL::X509::Certificate
|
236
|
+
raise "Can only construct from an OpenSSL::X509::Certificate"
|
237
|
+
end
|
238
|
+
|
239
|
+
certificate = Certificate.new
|
240
|
+
# Only subject, key_material, and body are used for signing
|
241
|
+
certificate.distinguished_name = DistinguishedName.from_openssl openssl_cert.subject
|
242
|
+
certificate.key_material.public_key = openssl_cert.public_key
|
243
|
+
certificate.openssl_body = openssl_cert
|
244
|
+
certificate.serial_number.number = openssl_cert.serial.to_i
|
245
|
+
certificate.not_before = openssl_cert.not_before
|
246
|
+
certificate.not_after = openssl_cert.not_after
|
247
|
+
EXTENSIONS.each do |klass|
|
248
|
+
_,v,c = (openssl_cert.extensions.detect { |e| e.to_a.first == klass::OPENSSL_IDENTIFIER } || []).to_a
|
249
|
+
certificate.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v
|
250
|
+
end
|
251
|
+
|
252
|
+
certificate
|
253
|
+
end
|
254
|
+
|
175
255
|
end
|
176
|
-
end
|
256
|
+
end
|