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
@@ -0,0 +1,91 @@
|
|
1
|
+
module CertificateAuthority
|
2
|
+
class SigningRequest
|
3
|
+
attr_accessor :distinguished_name
|
4
|
+
attr_accessor :key_material
|
5
|
+
attr_accessor :raw_body
|
6
|
+
attr_accessor :openssl_csr
|
7
|
+
attr_accessor :digest
|
8
|
+
attr_accessor :attributes
|
9
|
+
|
10
|
+
def initialize()
|
11
|
+
@attributes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
# Fake attribute for convenience because adding
|
15
|
+
# alternative names on a CSR is remarkably non-trivial.
|
16
|
+
def subject_alternative_names=(alt_names)
|
17
|
+
raise "alt_names must be an Array" unless alt_names.is_a?(Array)
|
18
|
+
|
19
|
+
factory = OpenSSL::X509::ExtensionFactory.new
|
20
|
+
name_list = alt_names.map{|m| "DNS:#{m}"}.join(",")
|
21
|
+
ext = factory.create_ext("subjectAltName",name_list,false)
|
22
|
+
ext_set = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence([ext])])
|
23
|
+
attr = OpenSSL::X509::Attribute.new("extReq", ext_set)
|
24
|
+
@attributes << attr
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_attributes_by_oid(*oids)
|
28
|
+
attributes.detect { |a| oids.include?(a.oid) }
|
29
|
+
end
|
30
|
+
protected :read_attributes_by_oid
|
31
|
+
|
32
|
+
def to_cert
|
33
|
+
cert = Certificate.new
|
34
|
+
if !@distinguished_name.nil?
|
35
|
+
cert.distinguished_name = @distinguished_name
|
36
|
+
end
|
37
|
+
cert.key_material = @key_material
|
38
|
+
if attribute = read_attributes_by_oid('extReq', 'msExtReq')
|
39
|
+
set = OpenSSL::ASN1.decode(attribute.value)
|
40
|
+
seq = set.value.first
|
41
|
+
seq.value.collect { |asn1ext| OpenSSL::X509::Extension.new(asn1ext).to_a }.each do |o, v, c|
|
42
|
+
Certificate::EXTENSIONS.each do |klass|
|
43
|
+
cert.extensions[klass::OPENSSL_IDENTIFIER] = klass.parse(v, c) if v && klass::OPENSSL_IDENTIFIER == o
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
cert
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_pem
|
51
|
+
to_x509_csr.to_pem
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_x509_csr
|
55
|
+
raise "Must specify a DN/subject on csr" if @distinguished_name.nil?
|
56
|
+
raise "Invalid DN in request" unless @distinguished_name.valid?
|
57
|
+
raise "CSR must have key material" if @key_material.nil?
|
58
|
+
raise "CSR must include a public key on key material" if @key_material.public_key.nil?
|
59
|
+
raise "Need a private key on key material for CSR generation" if @key_material.private_key.nil?
|
60
|
+
|
61
|
+
opensslcsr = OpenSSL::X509::Request.new
|
62
|
+
opensslcsr.subject = @distinguished_name.to_x509_name
|
63
|
+
opensslcsr.public_key = @key_material.public_key
|
64
|
+
opensslcsr.attributes = @attributes unless @attributes.nil?
|
65
|
+
opensslcsr.sign @key_material.private_key, OpenSSL::Digest.new(@digest || "SHA512")
|
66
|
+
opensslcsr
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.from_x509_csr(raw_csr)
|
70
|
+
csr = SigningRequest.new
|
71
|
+
openssl_csr = OpenSSL::X509::Request.new(raw_csr)
|
72
|
+
csr.distinguished_name = DistinguishedName.from_openssl openssl_csr.subject
|
73
|
+
csr.raw_body = raw_csr
|
74
|
+
csr.openssl_csr = openssl_csr
|
75
|
+
csr.attributes = openssl_csr.attributes
|
76
|
+
key_material = SigningRequestKeyMaterial.new
|
77
|
+
key_material.public_key = openssl_csr.public_key
|
78
|
+
csr.key_material = key_material
|
79
|
+
csr
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.from_netscape_spkac(raw_spkac)
|
83
|
+
openssl_spkac = OpenSSL::Netscape::SPKI.new raw_spkac
|
84
|
+
csr = SigningRequest.new
|
85
|
+
csr.raw_body = raw_spkac
|
86
|
+
key_material = SigningRequestKeyMaterial.new
|
87
|
+
key_material.public_key = openssl_spkac.public_key
|
88
|
+
csr
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# This is a super simple replacement for ActiveSupport::Validations
|
3
|
+
#
|
4
|
+
|
5
|
+
module CertificateAuthority
|
6
|
+
class Errors < Array
|
7
|
+
def add(symbol, msg)
|
8
|
+
self.push([symbol, msg])
|
9
|
+
end
|
10
|
+
def full_messages
|
11
|
+
self.map {|i| i[0].to_s + ": " + i[1]}.join("\n")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Validations
|
16
|
+
def valid?
|
17
|
+
@errors = Errors.new
|
18
|
+
validate
|
19
|
+
errors.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
# must be overridden
|
23
|
+
def validate
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
@errors ||= Errors.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,137 +1,139 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: certificate_authority
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.1.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- Chris Chandler
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
version: 3.0.6
|
23
|
-
type: :runtime
|
11
|
+
date: 2020-05-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: coveralls
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
24
21
|
prerelease: false
|
25
|
-
version_requirements:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
31
38
|
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version:
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
|
-
version_requirements:
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
45
62
|
type: :development
|
46
63
|
prerelease: false
|
47
|
-
version_requirements:
|
48
|
-
|
49
|
-
name: rcov
|
50
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
|
-
requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
53
66
|
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version:
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
56
76
|
type: :development
|
57
77
|
prerelease: false
|
58
|
-
version_requirements:
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
59
83
|
description:
|
60
|
-
email:
|
84
|
+
email:
|
85
|
+
- squanderingtime@gmail.com
|
61
86
|
executables: []
|
62
|
-
|
63
87
|
extensions: []
|
64
|
-
|
65
|
-
|
66
|
-
-
|
67
|
-
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
68
93
|
- Gemfile
|
69
94
|
- Gemfile.lock
|
70
95
|
- README.rdoc
|
71
96
|
- Rakefile
|
72
|
-
- VERSION.yml
|
73
97
|
- certificate_authority.gemspec
|
74
98
|
- lib/certificate_authority.rb
|
75
99
|
- lib/certificate_authority/certificate.rb
|
76
100
|
- lib/certificate_authority/certificate_revocation_list.rb
|
101
|
+
- lib/certificate_authority/core_extensions.rb
|
77
102
|
- lib/certificate_authority/distinguished_name.rb
|
78
103
|
- lib/certificate_authority/extensions.rb
|
79
104
|
- lib/certificate_authority/key_material.rb
|
80
105
|
- lib/certificate_authority/ocsp_handler.rb
|
81
106
|
- lib/certificate_authority/pkcs11_key_material.rb
|
107
|
+
- lib/certificate_authority/revocable.rb
|
82
108
|
- lib/certificate_authority/serial_number.rb
|
83
109
|
- lib/certificate_authority/signing_entity.rb
|
110
|
+
- lib/certificate_authority/signing_request.rb
|
111
|
+
- lib/certificate_authority/validations.rb
|
112
|
+
- lib/certificate_authority/version.rb
|
84
113
|
- lib/tasks/certificate_authority.rake
|
85
|
-
|
86
|
-
|
87
|
-
- spec/units/certificate_revocation_list_spec.rb
|
88
|
-
- spec/units/certificate_spec.rb
|
89
|
-
- spec/units/distinguished_name_spec.rb
|
90
|
-
- spec/units/extensions_spec.rb
|
91
|
-
- spec/units/key_material_spec.rb
|
92
|
-
- spec/units/ocsp_handler_spec.rb
|
93
|
-
- spec/units/serial_number_spec.rb
|
94
|
-
- spec/units/signing_entity_spec.rb
|
95
|
-
- spec/units/units_helper.rb
|
96
|
-
homepage: http://github.com/cchandler/certificate_authority
|
97
|
-
licenses:
|
114
|
+
homepage: https://github.com/cchandler/certificate_authority
|
115
|
+
licenses:
|
98
116
|
- MIT
|
117
|
+
metadata:
|
118
|
+
homepage_uri: https://github.com/cchandler/certificate_authority
|
119
|
+
source_code_uri: https://github.com/cchandler/certificate_authority
|
99
120
|
post_install_message:
|
100
121
|
rdoc_options: []
|
101
|
-
|
102
|
-
require_paths:
|
122
|
+
require_paths:
|
103
123
|
- lib
|
104
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
-
|
106
|
-
requirements:
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
107
126
|
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
version: "0"
|
113
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
|
-
requirements:
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '2.4'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
116
131
|
- - ">="
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
version:
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
119
134
|
requirements: []
|
120
|
-
|
121
|
-
rubyforge_project:
|
122
|
-
rubygems_version: 1.7.2
|
135
|
+
rubygems_version: 3.1.2
|
123
136
|
signing_key:
|
124
|
-
specification_version:
|
137
|
+
specification_version: 4
|
125
138
|
summary: Ruby gem for managing the core functions outlined in RFC-3280 for PKI
|
126
|
-
test_files:
|
127
|
-
- spec/spec_helper.rb
|
128
|
-
- spec/units/certificate_authority_spec.rb
|
129
|
-
- spec/units/certificate_revocation_list_spec.rb
|
130
|
-
- spec/units/certificate_spec.rb
|
131
|
-
- spec/units/distinguished_name_spec.rb
|
132
|
-
- spec/units/extensions_spec.rb
|
133
|
-
- spec/units/key_material_spec.rb
|
134
|
-
- spec/units/ocsp_handler_spec.rb
|
135
|
-
- spec/units/serial_number_spec.rb
|
136
|
-
- spec/units/signing_entity_spec.rb
|
137
|
-
- spec/units/units_helper.rb
|
139
|
+
test_files: []
|
data/VERSION.yml
DELETED
data/spec/spec_helper.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/units_helper'
|
2
|
-
|
3
|
-
describe CertificateAuthority::CertificateRevocationList do
|
4
|
-
before(:each) do
|
5
|
-
@crl = CertificateAuthority::CertificateRevocationList.new
|
6
|
-
|
7
|
-
@root_certificate = CertificateAuthority::Certificate.new
|
8
|
-
@root_certificate.signing_entity = true
|
9
|
-
@root_certificate.subject.common_name = "CRL Root"
|
10
|
-
@root_certificate.key_material.generate_key
|
11
|
-
@root_certificate.serial_number.number = 1
|
12
|
-
@root_certificate.sign!
|
13
|
-
|
14
|
-
@certificate = CertificateAuthority::Certificate.new
|
15
|
-
@certificate.key_material.generate_key
|
16
|
-
@certificate.subject.common_name = "http://bogusSite.com"
|
17
|
-
@certificate.parent = @root_certificate
|
18
|
-
@certificate.serial_number.number = 2
|
19
|
-
@certificate.sign!
|
20
|
-
|
21
|
-
@crl.parent = @root_certificate
|
22
|
-
@certificate.revoked_at = Time.now
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should accept a list of certificates" do
|
26
|
-
@crl << @certificate
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should complain if you add a certificate without a revocation time" do
|
30
|
-
@certificate.revoked_at = nil
|
31
|
-
lambda{ @crl << @certificate}.should raise_error
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should have a 'parent' that will be responsible for signing" do
|
35
|
-
@crl.parent = @root_certificate
|
36
|
-
@crl.parent.should_not be_nil
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should raise an error if you try and sign a CRL without attaching a parent" do
|
40
|
-
@crl.parent = nil
|
41
|
-
lambda { @crl.sign! }.should raise_error
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should be able to generate a proper CRL" do
|
45
|
-
@crl << @certificate
|
46
|
-
lambda {@crl.to_pem}.should raise_error
|
47
|
-
@crl.parent = @root_certificate
|
48
|
-
@crl.sign!
|
49
|
-
@crl.to_pem.should_not be_nil
|
50
|
-
OpenSSL::X509::CRL.new(@crl.to_pem).should_not be_nil
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "Next update" do
|
54
|
-
it "should be able to set a 'next_update' value" do
|
55
|
-
@crl.next_update = (60 * 60 * 10) # 10 Hours
|
56
|
-
@crl.next_update.should_not be_nil
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should throw an error if we try and sign up with a negative next_update" do
|
60
|
-
@crl.sign!
|
61
|
-
@crl.next_update = - (60 * 60 * 10)
|
62
|
-
lambda{@crl.sign!}.should raise_error
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
end
|