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.
Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +2 -8
  6. data/Gemfile.lock +71 -27
  7. data/README.rdoc +184 -89
  8. data/Rakefile +6 -41
  9. data/certificate_authority.gemspec +22 -81
  10. data/lib/certificate_authority.rb +7 -6
  11. data/lib/certificate_authority/certificate.rb +151 -71
  12. data/lib/certificate_authority/certificate_revocation_list.rb +46 -26
  13. data/lib/certificate_authority/core_extensions.rb +46 -0
  14. data/lib/certificate_authority/distinguished_name.rb +84 -17
  15. data/lib/certificate_authority/extensions.rb +483 -96
  16. data/lib/certificate_authority/key_material.rb +75 -21
  17. data/lib/certificate_authority/ocsp_handler.rb +99 -29
  18. data/lib/certificate_authority/pkcs11_key_material.rb +13 -15
  19. data/lib/certificate_authority/revocable.rb +14 -0
  20. data/lib/certificate_authority/serial_number.rb +18 -5
  21. data/lib/certificate_authority/signing_entity.rb +5 -7
  22. data/lib/certificate_authority/signing_request.rb +91 -0
  23. data/lib/certificate_authority/validations.rb +31 -0
  24. data/lib/certificate_authority/version.rb +3 -0
  25. metadata +96 -94
  26. data/VERSION.yml +0 -5
  27. data/spec/spec_helper.rb +0 -4
  28. data/spec/units/certificate_authority_spec.rb +0 -4
  29. data/spec/units/certificate_revocation_list_spec.rb +0 -68
  30. data/spec/units/certificate_spec.rb +0 -351
  31. data/spec/units/distinguished_name_spec.rb +0 -38
  32. data/spec/units/extensions_spec.rb +0 -53
  33. data/spec/units/key_material_spec.rb +0 -96
  34. data/spec/units/ocsp_handler_spec.rb +0 -104
  35. data/spec/units/serial_number_spec.rb +0 -20
  36. data/spec/units/signing_entity_spec.rb +0 -4
  37. 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
@@ -0,0 +1,3 @@
1
+ module CertificateAuthority
2
+ VERSION = '1.0.0'.freeze
3
+ 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
- prerelease:
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
- date: 2011-04-21 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: activemodel
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- none: false
19
- requirements:
20
- - - ~>
21
- - !ruby/object:Gem::Version
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: *id001
26
- - !ruby/object:Gem::Dependency
27
- name: rspec
28
- requirement: &id002 !ruby/object:Gem::Requirement
29
- none: false
30
- requirements:
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: "0"
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: *id002
37
- - !ruby/object:Gem::Dependency
38
- name: jeweler
39
- requirement: &id003 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ~>
43
- - !ruby/object:Gem::Version
44
- version: 1.5.2
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: *id003
48
- - !ruby/object:Gem::Dependency
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: "0"
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: *id004
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
59
83
  description:
60
- email: chris@flatterline.com
84
+ email:
85
+ - squanderingtime@gmail.com
61
86
  executables: []
62
-
63
87
  extensions: []
64
-
65
- extra_rdoc_files:
66
- - README.rdoc
67
- files:
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
- - spec/spec_helper.rb
86
- - spec/units/certificate_authority_spec.rb
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
- none: false
106
- requirements:
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
107
126
  - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: -4291817206657186993
110
- segments:
111
- - 0
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: "0"
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: 3
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: []
@@ -1,5 +0,0 @@
1
- ---
2
- :major: 0
3
- :minor: 1
4
- :patch: 2
5
- :build:
@@ -1,4 +0,0 @@
1
- require 'rubygems'
2
- require 'rspec'
3
-
4
- require File.dirname(__FILE__) + '/../lib/certificate_authority'
@@ -1,4 +0,0 @@
1
- require File.dirname(__FILE__) + '/units_helper'
2
-
3
- describe CertificateAuthority do
4
- end
@@ -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