certificate_authority 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ describe CertificateAuthority::DistinguishedName do
4
4
  before(:each) do
5
5
  @distinguished_name = CertificateAuthority::DistinguishedName.new
6
6
  end
7
-
7
+
8
8
  it "should provide the standard x.509 distinguished name common attributes" do
9
9
  @distinguished_name.respond_to?(:cn).should be_true
10
10
  @distinguished_name.respond_to?(:l).should be_true
@@ -13,7 +13,7 @@ describe CertificateAuthority::DistinguishedName do
13
13
  @distinguished_name.respond_to?(:ou).should be_true
14
14
  @distinguished_name.respond_to?(:c).should be_true
15
15
  end
16
-
16
+
17
17
  it "should provide human-readable equivalents to the distinguished name common attributes" do
18
18
  @distinguished_name.respond_to?(:common_name).should be_true
19
19
  @distinguished_name.respond_to?(:locality).should be_true
@@ -22,17 +22,38 @@ describe CertificateAuthority::DistinguishedName do
22
22
  @distinguished_name.respond_to?(:organizational_unit).should be_true
23
23
  @distinguished_name.respond_to?(:country).should be_true
24
24
  end
25
-
25
+
26
26
  it "should require a common name" do
27
27
  @distinguished_name.valid?.should be_false
28
28
  @distinguished_name.errors.size.should == 1
29
29
  @distinguished_name.common_name = "chrischandler.name"
30
30
  @distinguished_name.valid?.should be_true
31
31
  end
32
-
32
+
33
33
  it "should be convertible to an OpenSSL::X509::Name" do
34
34
  @distinguished_name.common_name = "chrischandler.name"
35
35
  @distinguished_name.to_x509_name
36
36
  end
37
-
37
+
38
+ describe "from_openssl" do
39
+ before do
40
+ subject = "/CN=justincummins.name/L=on my laptop/ST=relaxed/C=as/O=programmer/OU=using this code"
41
+ @name = OpenSSL::X509::Name.parse subject
42
+ @dn = CertificateAuthority::DistinguishedName.from_openssl @name
43
+ end
44
+
45
+ it "should reject non Name objects" do
46
+ lambda { CertificateAuthority::DistinguishedName.from_openssl "Not a OpenSSL::X509::Name" }.should raise_error
47
+ end
48
+
49
+ [:common_name, :locality, :state, :country, :organization, :organizational_unit].each do |field|
50
+ it "should set the #{field} attribute" do
51
+ @dn.send(field).should_not be_nil
52
+ end
53
+ end
54
+
55
+ it "should create an equivalent object" do
56
+ @dn.to_x509_name.to_s.split('/').should =~ @name.to_s.split('/')
57
+ end
58
+ end
38
59
  end
@@ -8,19 +8,19 @@ describe CertificateAuthority::Extensions do
8
8
  basic_constraints.ca = "moo"
9
9
  basic_constraints.valid?.should be_false
10
10
  end
11
-
11
+
12
12
  it "should respond to :path_len" do
13
13
  basic_constraints = CertificateAuthority::Extensions::BasicContraints.new
14
14
  basic_constraints.respond_to?(:path_len).should be_true
15
15
  end
16
-
16
+
17
17
  it "should raise an error if :path_len isn't a non-negative integer" do
18
18
  basic_constraints = CertificateAuthority::Extensions::BasicContraints.new
19
19
  lambda {basic_constraints.path_len = "moo"}.should raise_error
20
20
  lambda {basic_constraints.path_len = -1}.should raise_error
21
21
  lambda {basic_constraints.path_len = 1.5}.should raise_error
22
22
  end
23
-
23
+
24
24
  it "should generate a proper OpenSSL extension string" do
25
25
  basic_constraints = CertificateAuthority::Extensions::BasicContraints.new
26
26
  basic_constraints.ca = true
@@ -28,26 +28,88 @@ describe CertificateAuthority::Extensions do
28
28
  basic_constraints.to_s.should == "CA:true,pathlen:2"
29
29
  end
30
30
  end
31
-
31
+
32
32
  describe CertificateAuthority::Extensions::SubjectAlternativeName do
33
33
  it "should respond to :uris" do
34
34
  subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
35
35
  subjectAltName.respond_to?(:uris).should be_true
36
36
  end
37
-
37
+
38
38
  it "should require 'uris' to be an Array" do
39
39
  subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
40
40
  lambda {subjectAltName.uris = "not an array"}.should raise_error
41
41
  end
42
-
43
- it "should generate a proper OpenSSL extension string" do
42
+
43
+ it "should generate a proper OpenSSL extension string for URIs" do
44
44
  subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
45
45
  subjectAltName.uris = ["http://localhost.altname.example.com"]
46
46
  subjectAltName.to_s.should == "URI:http://localhost.altname.example.com"
47
-
47
+
48
48
  subjectAltName.uris = ["http://localhost.altname.example.com", "http://other.example.com"]
49
49
  subjectAltName.to_s.should == "URI:http://localhost.altname.example.com,URI:http://other.example.com"
50
50
  end
51
-
51
+
52
+
53
+ it "should respond to :dns_names" do
54
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
55
+ subjectAltName.respond_to?(:dns_names).should be_true
56
+ end
57
+
58
+ it "should require 'dns_names' to be an Array" do
59
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
60
+ lambda {subjectAltName.dns_names = "not an array"}.should raise_error
61
+ end
62
+
63
+ it "should generate a proper OpenSSL extension string for DNS names" do
64
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
65
+ subjectAltName.dns_names = ["localhost.altname.example.com"]
66
+ subjectAltName.to_s.should == "DNS:localhost.altname.example.com"
67
+
68
+ subjectAltName.dns_names = ["localhost.altname.example.com", "other.example.com"]
69
+ subjectAltName.to_s.should == "DNS:localhost.altname.example.com,DNS:other.example.com"
70
+ end
71
+
72
+ it "should respond to :ips" do
73
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
74
+ subjectAltName.respond_to?(:ips).should be_true
75
+ end
76
+
77
+ it "should require 'ips' to be an Array" do
78
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
79
+ lambda {subjectAltName.ips = "not an array"}.should raise_error
80
+ end
81
+
82
+ it "should generate a proper OpenSSL extension string for IPs" do
83
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
84
+ subjectAltName.ips = ["1.2.3.4"]
85
+ subjectAltName.to_s.should == "IP:1.2.3.4"
86
+
87
+ subjectAltName.ips = ["1.2.3.4", "5.6.7.8"]
88
+ subjectAltName.to_s.should == "IP:1.2.3.4,IP:5.6.7.8"
89
+ end
90
+
91
+ it "should generate a proper OpenSSL extension string for URIs IPs and DNS names together" do
92
+ subjectAltName = CertificateAuthority::Extensions::SubjectAlternativeName.new
93
+ subjectAltName.ips = ["1.2.3.4"]
94
+ subjectAltName.to_s.should == "IP:1.2.3.4"
95
+
96
+ subjectAltName.dns_names = ["localhost.altname.example.com"]
97
+ subjectAltName.to_s.should == "DNS:localhost.altname.example.com,IP:1.2.3.4"
98
+
99
+ subjectAltName.dns_names = ["localhost.altname.example.com", "other.example.com"]
100
+ subjectAltName.to_s.should == "DNS:localhost.altname.example.com,DNS:other.example.com,IP:1.2.3.4"
101
+
102
+ subjectAltName.ips = ["1.2.3.4", "5.6.7.8"]
103
+ subjectAltName.to_s.should == "DNS:localhost.altname.example.com,DNS:other.example.com,IP:1.2.3.4,IP:5.6.7.8"
104
+
105
+ subjectAltName.uris = ["http://localhost.altname.example.com"]
106
+ subjectAltName.to_s.should == "URI:http://localhost.altname.example.com,DNS:localhost.altname.example.com,DNS:other.example.com,IP:1.2.3.4,IP:5.6.7.8"
107
+
108
+ subjectAltName.uris = ["http://localhost.altname.example.com", "http://other.altname.example.com"]
109
+ subjectAltName.to_s.should == "URI:http://localhost.altname.example.com,URI:http://other.altname.example.com,DNS:localhost.altname.example.com,DNS:other.example.com,IP:1.2.3.4,IP:5.6.7.8"
110
+
111
+ end
112
+
113
+
52
114
  end
53
- end
115
+ end
@@ -1,89 +1,57 @@
1
1
  require File.dirname(__FILE__) + '/units_helper'
2
2
 
3
+ describe CertificateAuthority::KeyMaterial do
4
+ [CertificateAuthority::MemoryKeyMaterial, CertificateAuthority::SigningRequestKeyMaterial].each do |key_material_class|
5
+ before do
6
+ @key_material = key_material_class.new
7
+ end
8
+
9
+ it "#{key_material_class} should know if a key is in memory or hardware" do
10
+ @key_material.is_in_hardware?.should_not be_nil
11
+ @key_material.is_in_memory?.should_not be_nil
12
+ end
13
+
14
+ it "should use memory by default" do
15
+ @key_material.is_in_memory?.should be_true
16
+ end
17
+ end
18
+ end
19
+
3
20
  describe CertificateAuthority::MemoryKeyMaterial do
4
21
  before(:each) do
5
22
  @key_material = CertificateAuthority::MemoryKeyMaterial.new
6
23
  end
7
-
8
- it "should know if a key is in memory or hardware" do
9
- @key_material.is_in_hardware?.should_not be_nil
10
- @key_material.is_in_memory?.should_not be_nil
11
- end
12
-
13
- it "should use memory by default" do
14
- @key_material.is_in_memory?.should be_true
15
- end
16
-
24
+
17
25
  it "should be able to generate an RSA key" do
18
- @key_material.generate_key.should_not be_nil
26
+ @key_material.generate_key(1024).should_not be_nil
19
27
  end
20
-
28
+
21
29
  it "should generate a proper OpenSSL::PKey::RSA" do
22
- @key_material.generate_key.class.should == OpenSSL::PKey::RSA
30
+ @key_material.generate_key(1024).class.should == OpenSSL::PKey::RSA
23
31
  end
24
-
32
+
25
33
  it "should be able to specify the size of the modulus to generate" do
26
- @key_material.generate_key(768).should_not be_nil
34
+ @key_material.generate_key(1024).should_not be_nil
27
35
  end
28
-
29
- describe "in memory" do
36
+
37
+ describe "with generated key" do
30
38
  before(:all) do
31
39
  @key_material_in_memory = CertificateAuthority::MemoryKeyMaterial.new
32
- @key_material_in_memory.generate_key
40
+ @key_material_in_memory.generate_key(1024)
33
41
  end
34
-
42
+
35
43
  it "should be able to retrieve the private key" do
36
44
  @key_material_in_memory.private_key.should_not be_nil
37
45
  end
38
-
46
+
39
47
  it "should be able to retrieve the public key" do
40
48
  @key_material_in_memory.public_key.should_not be_nil
41
49
  end
42
50
  end
43
-
44
- ## Anything that requires crypto hardware needs to be tagged as 'pkcs11'
45
- describe "in hardware", :pkcs11 => true do
46
- before(:each) do
47
- @key_material_in_hardware = CertificateAuthority::Pkcs11KeyMaterial.new
48
- @key_material_in_hardware.token_id = "46"
49
- @key_material_in_hardware.pkcs11_lib = "/usr/lib/libeTPkcs11.so"
50
- @key_material_in_hardware.openssl_pkcs11_engine_lib = "/usr/lib/engines/engine_pkcs11.so"
51
- @key_material_in_hardware.pin = "11111111"
52
- end
53
-
54
- it "should identify as being in hardware", :pkcs11 => true do
55
- @key_material_in_hardware.is_in_hardware?.should be_true
56
- end
57
-
58
- it "should return a Pkey ref if the private key is requested", :pkcs11 => true do
59
- @key_material_in_hardware.private_key.class.should == OpenSSL::PKey::RSA
60
- end
61
-
62
- it "should return a Pkey ref if the private key is requested", :pkcs11 => true do
63
- @key_material_in_hardware.public_key.class.should == OpenSSL::PKey::RSA
64
- end
65
-
66
- it "should accept an ID for on-token objects", :pkcs11 => true do
67
- @key_material_in_hardware.respond_to?(:token_id).should be_true
68
- end
69
-
70
- it "should accept a path to a shared library for a PKCS11 driver", :pkcs11 => true do
71
- @key_material_in_hardware.respond_to?(:pkcs11_lib).should be_true
72
- end
73
-
74
- it "should accept a path to OpenSSL's dynamic PKCS11 engine (provided by libengine-pkcs11-openssl)", :pkcs11 => true do
75
- @key_material_in_hardware.respond_to?(:openssl_pkcs11_engine_lib).should be_true
76
- end
77
-
78
- it "should accept an optional PIN to authenticate to the token", :pkcs11 => true do
79
- @key_material_in_hardware.respond_to?(:pin).should be_true
80
- end
81
-
82
- end
83
-
84
- it "not validate without public and private keys" do
51
+
52
+ it "should not validate without public and private keys" do
85
53
  @key_material.valid?.should be_false
86
- @key_material.generate_key
54
+ @key_material.generate_key(1024)
87
55
  @key_material.valid?.should be_true
88
56
  pub = @key_material.public_key
89
57
  @key_material.public_key = nil
@@ -92,5 +60,41 @@ describe CertificateAuthority::MemoryKeyMaterial do
92
60
  @key_material.private_key = nil
93
61
  @key_material.valid?.should be_false
94
62
  end
95
-
96
- end
63
+ end
64
+
65
+ describe CertificateAuthority::SigningRequestKeyMaterial do
66
+ before(:each) do
67
+ @request = OpenSSL::X509::Request.new <<CSR
68
+ -----BEGIN CERTIFICATE REQUEST-----
69
+ MIIBjTCB9wIBADBOMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEU
70
+ MBIGA1UEBxMLQmVyc2Vya2VsZXkxFDASBgNVBAoTC0NlcnRzICdSIFVzMIGfMA0G
71
+ CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaGiBcv++581KYt6y2NNcUaZNPPeNZ0UkX
72
+ ujzZQQllx7PlYmsKTE6ZzfTUc0AJvDBIuACg03eagaEaBZtUFbsLkSOLJyYiIfF5
73
+ f9PuXImz2RDzBJQ/+u82gQAcvPhm94xK8jeNPcn0Ege7Y7SRK4YYonX+0ZveP02L
74
+ FjuEfrZcZQIDAQABoAAwDQYJKoZIhvcNAQEFBQADgYEAecOQz0RfnmSxxzOyHZ1e
75
+ Wo2hQqPOmkfIbvL2l1Ml+HybJQJn6OpLmeveyU48SI2M7UqeNkHtsogMljy3re4L
76
+ QlwK7lNd6SymdfSCPjUcdoLOaHolZXYNvCHltTc5skRHG7ti5yv4cu0ItIcCS0yp
77
+ 7L3maDEbTLsDdouHeFfbLWA=
78
+ -----END CERTIFICATE REQUEST-----
79
+ CSR
80
+ @key_material = CertificateAuthority::SigningRequestKeyMaterial.new @request
81
+ end
82
+
83
+ it "should generate from a CSR" do
84
+ @key_material.should_not be_nil
85
+ end
86
+
87
+ it "should be able to expose a public key" do
88
+ @key_material.public_key.should_not be_nil
89
+ end
90
+
91
+ it "should not have a private key" do
92
+ @key_material.private_key.should be_nil
93
+ end
94
+
95
+ it "should raise when signature does not verify" do
96
+ invalid = @request
97
+ invalid.public_key = OpenSSL::PKey::RSA.new 512
98
+ lambda { CertificateAuthority::SigningRequestKeyMaterial.new invalid }.should raise_error
99
+ end
100
+ end
@@ -3,58 +3,58 @@ require File.dirname(__FILE__) + '/units_helper'
3
3
  describe CertificateAuthority::OCSPHandler do
4
4
  before(:each) do
5
5
  @ocsp_handler = CertificateAuthority::OCSPHandler.new
6
-
6
+
7
7
  @root_certificate = CertificateAuthority::Certificate.new
8
8
  @root_certificate.signing_entity = true
9
9
  @root_certificate.subject.common_name = "OCSP Root"
10
- @root_certificate.key_material.generate_key
10
+ @root_certificate.key_material.generate_key(1024)
11
11
  @root_certificate.serial_number.number = 1
12
12
  @root_certificate.sign!
13
-
13
+
14
14
  @certificate = CertificateAuthority::Certificate.new
15
- @certificate.key_material.generate_key
15
+ @certificate.key_material.generate_key(1024)
16
16
  @certificate.subject.common_name = "http://questionablesite.com"
17
17
  @certificate.parent = @root_certificate
18
18
  @certificate.serial_number.number = 2
19
19
  @certificate.sign!
20
-
20
+
21
21
  @ocsp_request = OpenSSL::OCSP::Request.new
22
22
  openssl_cert_issuer = OpenSSL::X509::Certificate.new(@root_certificate.to_pem)
23
23
  openssl_cert_subject = OpenSSL::X509::Certificate.new(@certificate.to_pem)
24
-
24
+
25
25
  cert_id = OpenSSL::OCSP::CertificateId.new(openssl_cert_subject, openssl_cert_issuer)
26
26
  @ocsp_request.add_certid(cert_id)
27
27
  @ocsp_handler.ocsp_request = @ocsp_request.to_der
28
28
  end
29
-
29
+
30
30
  it "should be able to accept an OCSP Request" do
31
31
  @ocsp_handler.ocsp_request = @ocsp_request
32
32
  @ocsp_handler.ocsp_request.should_not be_nil
33
33
  end
34
-
34
+
35
35
  it "should raise an error if you try and extract certificates without a raw request" do
36
36
  @ocsp_handler.extract_certificate_serials
37
37
  @ocsp_handler.ocsp_request = nil
38
38
  lambda {@ocsp_handler.extract_certificate_serials}.should raise_error
39
39
  end
40
-
40
+
41
41
  it "should return a hash of extracted certificates from OCSP requests" do
42
42
  result = @ocsp_handler.extract_certificate_serials
43
43
  result.size.should == 1
44
44
  end
45
-
45
+
46
46
  it "should be able to generate an OCSP response" do
47
47
  @ocsp_handler.extract_certificate_serials
48
48
  @ocsp_handler << @certificate
49
49
  @ocsp_handler.parent = @root_certificate
50
50
  @ocsp_handler.response
51
51
  end
52
-
52
+
53
53
  it "should require a 'parent' entity for signing" do
54
54
  @ocsp_handler.parent = @root_certificate
55
55
  @ocsp_handler.parent.should_not be_nil
56
56
  end
57
-
57
+
58
58
  it "should raise an error if you ask for the signed OCSP response without generating it" do
59
59
  @ocsp_handler.extract_certificate_serials
60
60
  @ocsp_handler << @certificate
@@ -63,42 +63,42 @@ describe CertificateAuthority::OCSPHandler do
63
63
  @ocsp_handler.response
64
64
  @ocsp_handler.to_der.should_not be_nil
65
65
  end
66
-
66
+
67
67
  it "should raise an error if you generate a response without adding all certificates in request" do
68
68
  @ocsp_handler.extract_certificate_serials
69
69
  @ocsp_handler.parent = @root_certificate
70
70
  lambda { @ocsp_handler.response }.should raise_error
71
71
  end
72
-
72
+
73
73
  it "should raise an error if you generate a response without adding a parent signing entity" do
74
74
  @ocsp_handler.extract_certificate_serials
75
75
  @ocsp_handler << @certificate
76
76
  lambda { @ocsp_handler.response }.should raise_error
77
77
  end
78
-
78
+
79
79
  describe "Response" do
80
80
  before(:each) do
81
81
  @ocsp_handler.extract_certificate_serials
82
82
  @ocsp_handler << @certificate
83
83
  @ocsp_handler.parent = @root_certificate
84
84
  @ocsp_handler.response
85
-
85
+
86
86
  @openssl_ocsp_response = OpenSSL::OCSP::Response.new(@ocsp_handler.to_der)
87
87
  end
88
-
88
+
89
89
  it "should have a correct status/status string" do
90
90
  @openssl_ocsp_response.status_string.should == "successful"
91
91
  @openssl_ocsp_response.status.should == 0
92
92
  end
93
-
93
+
94
94
  it "should have an embedded BasicResponse with certificate statuses" do
95
95
  # [#<OpenSSL::OCSP::CertificateId:0x000001020ecad8>, 0, 1, nil, 2011-04-15 23:29:47 UTC, 2011-04-15 23:30:17 UTC, []]
96
96
  @openssl_ocsp_response.basic.status.first[1].should == 0 # Everything is OK
97
97
  end
98
-
98
+
99
99
  it "should have a next_update time" do
100
100
  @openssl_ocsp_response.basic.status.first[5].should_not be_nil
101
101
  @openssl_ocsp_response.basic.status.first[5].class.should == Time
102
102
  end
103
103
  end
104
- end
104
+ end