r509 0.8
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.
- data/README.md +447 -0
- data/Rakefile +38 -0
- data/bin/r509 +96 -0
- data/bin/r509-parse +35 -0
- data/doc/R509.html +154 -0
- data/doc/R509/Cert.html +3954 -0
- data/doc/R509/Cert/Extensions.html +360 -0
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +391 -0
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +148 -0
- data/doc/R509/Cert/Extensions/BasicConstraints.html +482 -0
- data/doc/R509/Cert/Extensions/CrlDistributionPoints.html +316 -0
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +780 -0
- data/doc/R509/Cert/Extensions/KeyUsage.html +1230 -0
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +467 -0
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +216 -0
- data/doc/R509/CertificateAuthority.html +126 -0
- data/doc/R509/CertificateAuthority/Signer.html +855 -0
- data/doc/R509/Config.html +127 -0
- data/doc/R509/Config/CaConfig.html +2144 -0
- data/doc/R509/Config/CaConfigPool.html +599 -0
- data/doc/R509/Config/CaProfile.html +656 -0
- data/doc/R509/Config/SubjectItemPolicy.html +578 -0
- data/doc/R509/Crl.html +126 -0
- data/doc/R509/Crl/Administrator.html +2077 -0
- data/doc/R509/Crl/Parser.html +1224 -0
- data/doc/R509/Csr.html +2248 -0
- data/doc/R509/IOHelpers.html +564 -0
- data/doc/R509/MessageDigest.html +396 -0
- data/doc/R509/NameSanitizer.html +319 -0
- data/doc/R509/Ocsp.html +128 -0
- data/doc/R509/Ocsp/Request.html +126 -0
- data/doc/R509/Ocsp/Request/Nonce.html +160 -0
- data/doc/R509/Ocsp/Response.html +837 -0
- data/doc/R509/OidMapper.html +393 -0
- data/doc/R509/PrivateKey.html +1647 -0
- data/doc/R509/R509Error.html +134 -0
- data/doc/R509/Spki.html +1424 -0
- data/doc/R509/Subject.html +836 -0
- data/doc/R509/Validity.html +160 -0
- data/doc/R509/Validity/Checker.html +320 -0
- data/doc/R509/Validity/DefaultChecker.html +283 -0
- data/doc/R509/Validity/DefaultWriter.html +330 -0
- data/doc/R509/Validity/Status.html +561 -0
- data/doc/R509/Validity/Writer.html +394 -0
- data/doc/_index.html +501 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +534 -0
- data/doc/file.r509.html +149 -0
- data/doc/file_list.html +58 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +534 -0
- data/doc/js/app.js +208 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/methods_list.html +1932 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/r509.rb +22 -0
- data/lib/r509/cert.rb +414 -0
- data/lib/r509/cert/extensions.rb +309 -0
- data/lib/r509/certificateauthority.rb +290 -0
- data/lib/r509/config.rb +407 -0
- data/lib/r509/crl.rb +379 -0
- data/lib/r509/csr.rb +324 -0
- data/lib/r509/exceptions.rb +5 -0
- data/lib/r509/io_helpers.rb +52 -0
- data/lib/r509/messagedigest.rb +49 -0
- data/lib/r509/ocsp.rb +85 -0
- data/lib/r509/oidmapper.rb +32 -0
- data/lib/r509/privatekey.rb +185 -0
- data/lib/r509/spki.rb +112 -0
- data/lib/r509/subject.rb +133 -0
- data/lib/r509/validity.rb +92 -0
- data/lib/r509/version.rb +4 -0
- data/r509.yaml +73 -0
- data/spec/cert/extensions_spec.rb +632 -0
- data/spec/cert_spec.rb +321 -0
- data/spec/certificate_authority_spec.rb +260 -0
- data/spec/config_spec.rb +349 -0
- data/spec/crl_spec.rb +215 -0
- data/spec/csr_spec.rb +302 -0
- data/spec/fixtures.rb +233 -0
- data/spec/fixtures/cert1.der +0 -0
- data/spec/fixtures/cert1.pem +24 -0
- data/spec/fixtures/cert1_public_key_modulus.txt +1 -0
- data/spec/fixtures/cert3.p12 +0 -0
- data/spec/fixtures/cert3.pem +28 -0
- data/spec/fixtures/cert3_key.pem +27 -0
- data/spec/fixtures/cert3_key_des3.pem +30 -0
- data/spec/fixtures/cert4.pem +14 -0
- data/spec/fixtures/cert5.pem +30 -0
- data/spec/fixtures/cert6.pem +26 -0
- data/spec/fixtures/cert_expired.pem +26 -0
- data/spec/fixtures/cert_not_yet_valid.pem +26 -0
- data/spec/fixtures/cert_san.pem +27 -0
- data/spec/fixtures/cert_san2.pem +22 -0
- data/spec/fixtures/config_pool_test_minimal.yaml +15 -0
- data/spec/fixtures/config_test.yaml +41 -0
- data/spec/fixtures/config_test_engine_key.yaml +7 -0
- data/spec/fixtures/config_test_engine_no_key_name.yaml +6 -0
- data/spec/fixtures/config_test_minimal.yaml +7 -0
- data/spec/fixtures/config_test_password.yaml +7 -0
- data/spec/fixtures/config_test_various.yaml +100 -0
- data/spec/fixtures/crl_list_file.txt +1 -0
- data/spec/fixtures/crl_with_reason.pem +17 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +17 -0
- data/spec/fixtures/csr1_key.der +0 -0
- data/spec/fixtures/csr1_key.pem +27 -0
- data/spec/fixtures/csr1_key_encrypted_des3.pem +30 -0
- data/spec/fixtures/csr1_newlines.pem +32 -0
- data/spec/fixtures/csr1_no_begin_end.pem +15 -0
- data/spec/fixtures/csr1_public_key_modulus.txt +1 -0
- data/spec/fixtures/csr2.pem +15 -0
- data/spec/fixtures/csr2_key.pem +27 -0
- data/spec/fixtures/csr3.pem +16 -0
- data/spec/fixtures/csr4.pem +25 -0
- data/spec/fixtures/csr_dsa.pem +15 -0
- data/spec/fixtures/csr_invalid_signature.pem +13 -0
- data/spec/fixtures/dsa_key.pem +20 -0
- data/spec/fixtures/key4.pem +27 -0
- data/spec/fixtures/key4_encrypted_des3.pem +30 -0
- data/spec/fixtures/missing_key_identifier_ca.cer +21 -0
- data/spec/fixtures/missing_key_identifier_ca.key +27 -0
- data/spec/fixtures/ocsptest.r509.local.pem +27 -0
- data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
- data/spec/fixtures/ocsptest2.r509.local.pem +27 -0
- data/spec/fixtures/second_ca.cer +26 -0
- data/spec/fixtures/second_ca.key +27 -0
- data/spec/fixtures/spkac.der +0 -0
- data/spec/fixtures/spkac.txt +1 -0
- data/spec/fixtures/spkac_dsa.txt +1 -0
- data/spec/fixtures/stca.pem +22 -0
- data/spec/fixtures/stca_ocsp_request.der +0 -0
- data/spec/fixtures/stca_ocsp_response.der +0 -0
- data/spec/fixtures/test1.csr +17 -0
- data/spec/fixtures/test_ca.cer +22 -0
- data/spec/fixtures/test_ca.key +28 -0
- data/spec/fixtures/test_ca.p12 +0 -0
- data/spec/fixtures/test_ca_des3.key +30 -0
- data/spec/fixtures/test_ca_ocsp.cer +26 -0
- data/spec/fixtures/test_ca_ocsp.key +27 -0
- data/spec/fixtures/test_ca_ocsp.p12 +0 -0
- data/spec/fixtures/test_ca_ocsp_chain.txt +48 -0
- data/spec/fixtures/test_ca_ocsp_response.der +0 -0
- data/spec/fixtures/test_ca_subroot.cer +26 -0
- data/spec/fixtures/test_ca_subroot.key +27 -0
- data/spec/fixtures/test_ca_subroot_ocsp.cer +25 -0
- data/spec/fixtures/test_ca_subroot_ocsp.key +27 -0
- data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
- data/spec/fixtures/unknown_oid.csr +17 -0
- data/spec/message_digest_spec.rb +89 -0
- data/spec/ocsp_spec.rb +111 -0
- data/spec/oid_mapper_spec.rb +31 -0
- data/spec/privatekey_spec.rb +198 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/spki_spec.rb +157 -0
- data/spec/subject_spec.rb +203 -0
- data/spec/validity_spec.rb +98 -0
- metadata +257 -0
data/spec/cert_spec.rb
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe R509::Cert do
|
|
4
|
+
before :all do
|
|
5
|
+
@cert = TestFixtures::CERT
|
|
6
|
+
@cert_public_key_modulus = TestFixtures::CERT_PUBLIC_KEY_MODULUS
|
|
7
|
+
@cert3 = TestFixtures::CERT3
|
|
8
|
+
@cert_der = TestFixtures::CERT_DER
|
|
9
|
+
@cert_san = TestFixtures::CERT_SAN
|
|
10
|
+
@cert_san2 = TestFixtures::CERT_SAN2
|
|
11
|
+
@key3 = TestFixtures::KEY3
|
|
12
|
+
@cert3_p12 = TestFixtures::CERT3_P12
|
|
13
|
+
@cert4 = TestFixtures::CERT4
|
|
14
|
+
@key3_encrypted = TestFixtures::KEY3_ENCRYPTED
|
|
15
|
+
@cert5 = TestFixtures::CERT5
|
|
16
|
+
@cert6 = TestFixtures::CERT6
|
|
17
|
+
@test_ca_cert = TestFixtures::TEST_CA_CERT
|
|
18
|
+
@cert_expired = TestFixtures::CERT_EXPIRED
|
|
19
|
+
@cert_not_yet_valid = TestFixtures::CERT_NOT_YET_VALID
|
|
20
|
+
end
|
|
21
|
+
it "raises error when no hash supplied" do
|
|
22
|
+
expect { R509::Cert.new('no hash')}.to raise_error(ArgumentError, 'Must provide a hash of options')
|
|
23
|
+
end
|
|
24
|
+
it "raises error when no :cert supplied" do
|
|
25
|
+
expect { R509::Cert.new(:key => "random")}.to raise_error(ArgumentError, 'Must provide :cert or :pkcs12')
|
|
26
|
+
end
|
|
27
|
+
it "raises error when a csr is supplied to :cert" do
|
|
28
|
+
expect { R509::Cert.new(:cert => TestFixtures::CSR)}.to raise_error(R509::R509Error, "Cert provided is actually a certificate signing request.")
|
|
29
|
+
end
|
|
30
|
+
it "raises error when :cert and :pkcs12 are both provided" do
|
|
31
|
+
expect { R509::Cert.new(
|
|
32
|
+
:key => @key3,
|
|
33
|
+
:pkcs12 => @cert3_p12,
|
|
34
|
+
:password => 'whatever'
|
|
35
|
+
) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
|
|
36
|
+
end
|
|
37
|
+
it "raises error when :key and :pkcs12 are both provided" do
|
|
38
|
+
expect { R509::Cert.new(
|
|
39
|
+
:cert => @cert,
|
|
40
|
+
:pkcs12 => @cert3_p12,
|
|
41
|
+
:password => 'whatever'
|
|
42
|
+
) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
|
|
43
|
+
end
|
|
44
|
+
it "has a public_key" do
|
|
45
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
46
|
+
#this is more complex than it should have to be. diff versions of openssl
|
|
47
|
+
#return subtly diff PEM encodings so we need to look at the modulus (n)
|
|
48
|
+
#but beware, because n is not present for DSA certificates
|
|
49
|
+
cert.public_key.n.to_i.should == @cert_public_key_modulus.to_i
|
|
50
|
+
end
|
|
51
|
+
it "returns bit strength" do
|
|
52
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
53
|
+
cert.bit_strength.should == 2048
|
|
54
|
+
end
|
|
55
|
+
it "has the right issuer" do
|
|
56
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
57
|
+
cert.issuer.to_s.should == "/C=US/O=SecureTrust Corporation/CN=SecureTrust CA"
|
|
58
|
+
end
|
|
59
|
+
it "has the right issuer CN" do
|
|
60
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
61
|
+
cert.issuer_cn.to_s.should == "SecureTrust CA"
|
|
62
|
+
end
|
|
63
|
+
it "generates certificate fingerprints" do
|
|
64
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
65
|
+
cert.fingerprint.should == '863bbb58877b426eb10ccfd34d3056b8c961f627'
|
|
66
|
+
cert.fingerprint('sha256').should == '65d624f5a6937c3005d78b3f4ff09164649dd5aeb3fd8a93d6fd420e8b587fa2'
|
|
67
|
+
cert.fingerprint('sha512').should == 'a07d87f04161f52ef671c9d616530d07ebadef9c93c0470091617363c9ce8618dcb7931414e599d25cb032d68597111719e76d7de4bb7a92bf5ca7c08c36cf12'
|
|
68
|
+
cert.fingerprint('md5').should == 'aa78501c41b19252dfbe8ba509cc21f4'
|
|
69
|
+
end
|
|
70
|
+
it "returns true from has_private_key? when a key is present" do
|
|
71
|
+
cert = R509::Cert.new(:cert => @cert3, :key => @key3)
|
|
72
|
+
cert.has_private_key?.should == true
|
|
73
|
+
end
|
|
74
|
+
it "returns false from has_private_key? when a key is not present" do
|
|
75
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
76
|
+
cert.has_private_key?.should == false
|
|
77
|
+
end
|
|
78
|
+
it "loads encrypted private key with cert" do
|
|
79
|
+
expect { R509::Cert.new(:cert => @cert3, :key => @key3_encrypted, :password => "r509") }.to_not raise_error
|
|
80
|
+
end
|
|
81
|
+
it "loads pkcs12" do
|
|
82
|
+
cert = R509::Cert.new(:pkcs12 => @cert3_p12, :password => "r509")
|
|
83
|
+
cert.has_private_key?.should == true
|
|
84
|
+
cert.subject.to_s.should == '/CN=futurama.com/O=Farnsworth Enterprises'
|
|
85
|
+
end
|
|
86
|
+
it "has the right not_before" do
|
|
87
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
88
|
+
cert.not_before.to_i.should == 1282659002
|
|
89
|
+
end
|
|
90
|
+
it "has the right not_after" do
|
|
91
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
92
|
+
cert.not_after.to_i.should == 1377267002
|
|
93
|
+
end
|
|
94
|
+
it "fetches a subject component" do
|
|
95
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
96
|
+
cert.subject_component('CN').should == 'langui.sh'
|
|
97
|
+
end
|
|
98
|
+
it "fetches a subject component for mixed-case components" do
|
|
99
|
+
cert4 = R509::Cert.new(:cert => @cert4)
|
|
100
|
+
cert4.subject_component('emailAddress').should == 'support@polycom.com'
|
|
101
|
+
|
|
102
|
+
cert6 = R509::Cert.new(:cert => @cert6)
|
|
103
|
+
cert6.subject_component('serialNumber').should == 'a/3ILmX9qynk8f3WafoTTkKgWj0LAGRL'
|
|
104
|
+
end
|
|
105
|
+
it "returns nil when subject component not found" do
|
|
106
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
107
|
+
cert.subject_component('OU').should be_nil
|
|
108
|
+
end
|
|
109
|
+
it "returns signature algorithm" do
|
|
110
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
111
|
+
cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
|
112
|
+
end
|
|
113
|
+
it "returns the RSA key algorithm" do
|
|
114
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
115
|
+
cert.key_algorithm.should == 'RSA'
|
|
116
|
+
end
|
|
117
|
+
it "returns the DSA key algorithm" do
|
|
118
|
+
cert = R509::Cert.new(:cert => @cert6)
|
|
119
|
+
cert.key_algorithm.should == 'DSA'
|
|
120
|
+
end
|
|
121
|
+
it "returns list of san_names when it is a san cert" do
|
|
122
|
+
cert = R509::Cert.new(:cert => @cert_san)
|
|
123
|
+
cert.san_names.should == ['langui.sh']
|
|
124
|
+
end
|
|
125
|
+
it "returns an empty list when it is not a san cert" do
|
|
126
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
127
|
+
cert.san_names.should == []
|
|
128
|
+
end
|
|
129
|
+
it "#subject_names should return a list of san_names in addition to the CN" do
|
|
130
|
+
cert = R509::Cert.new(:cert => @cert_san2)
|
|
131
|
+
cert.subject_names.should == ["cn.langui.sh", "san1.langui.sh",
|
|
132
|
+
"san2.langui.sh", "san3.langui.sh"]
|
|
133
|
+
end
|
|
134
|
+
it "#subject_names should not have duplicates" do
|
|
135
|
+
cert = R509::Cert.new(:cert => @cert_san)
|
|
136
|
+
cert.subject_names.should == ["langui.sh"]
|
|
137
|
+
end
|
|
138
|
+
it "#subject_names should return the CN in the array, if there are no SANs" do
|
|
139
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
140
|
+
cert.subject_names.should == ["langui.sh"]
|
|
141
|
+
end
|
|
142
|
+
it "raises exception when providing invalid cert" do
|
|
143
|
+
expect { R509::Cert.new(:cert => "invalid cert") }.to raise_error(OpenSSL::X509::CertificateError)
|
|
144
|
+
end
|
|
145
|
+
it "raises exception when providing invalid key" do
|
|
146
|
+
expect { R509::Cert.new(:cert => @cert, :key => 'invalid key') }.to raise_error(R509::R509Error, 'Failed to load private key. Invalid key or incorrect password.')
|
|
147
|
+
end
|
|
148
|
+
it "raises exception on non-matching key" do
|
|
149
|
+
expect { R509::Cert.new(:cert => @cert, :key => @key3) }.to raise_error(R509::R509Error, 'Key does not match cert.')
|
|
150
|
+
end
|
|
151
|
+
it "return normal object on matching key/cert pair" do
|
|
152
|
+
expect { R509::Cert.new(:cert => @cert3, :key => @key3) }.to_not raise_error
|
|
153
|
+
end
|
|
154
|
+
it "loads properly when an R509::PrivateKey is provided" do
|
|
155
|
+
key = R509::PrivateKey.new(:key => @key3)
|
|
156
|
+
expect { R509::Cert.new(:key => key, :cert => @cert3)}.to_not raise_error
|
|
157
|
+
end
|
|
158
|
+
it "writes to pem" do
|
|
159
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
160
|
+
sio = StringIO.new
|
|
161
|
+
sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
|
|
162
|
+
cert.write_pem(sio)
|
|
163
|
+
sio.string.should == @cert + "\n"
|
|
164
|
+
end
|
|
165
|
+
it "writes to der" do
|
|
166
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
167
|
+
sio = StringIO.new
|
|
168
|
+
sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
|
|
169
|
+
cert.write_der(sio)
|
|
170
|
+
sio.string.should == @cert_der
|
|
171
|
+
end
|
|
172
|
+
it "writes to pkcs12 when key/cert are present" do
|
|
173
|
+
cert = R509::Cert.new(:cert => @cert3, :key => @key3)
|
|
174
|
+
sio = StringIO.new
|
|
175
|
+
sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
|
|
176
|
+
cert.write_pkcs12(sio,'r509_password')
|
|
177
|
+
expect { R509::Cert.new(:pkcs12 => sio.string, :password => 'r509_password') }.to_not raise_error
|
|
178
|
+
end
|
|
179
|
+
it "raises error when writing to pkcs12 if key is not present" do
|
|
180
|
+
cert = R509::Cert.new(:cert => @cert3)
|
|
181
|
+
expect { cert.write_pkcs12('/dev/null','password') }.to raise_error(R509::R509Error, "Writing a PKCS12 requires both key and cert")
|
|
182
|
+
end
|
|
183
|
+
it "parses san extension" do
|
|
184
|
+
cert = R509::Cert.new(:cert => @cert_san)
|
|
185
|
+
cert.san_names.should == ["langui.sh"]
|
|
186
|
+
end
|
|
187
|
+
context "when initialized with an OpenSSL::X509::Certificate" do
|
|
188
|
+
it "returns pem on to_pem" do
|
|
189
|
+
test_cert = OpenSSL::X509::Certificate.new(@cert)
|
|
190
|
+
cert = R509::Cert.new(:cert => test_cert)
|
|
191
|
+
cert.to_pem.should == @cert
|
|
192
|
+
end
|
|
193
|
+
it "returns der on to_der" do
|
|
194
|
+
test_cert = OpenSSL::X509::Certificate.new(@cert)
|
|
195
|
+
cert = R509::Cert.new(:cert => test_cert)
|
|
196
|
+
cert.to_der.should == @cert_der
|
|
197
|
+
end
|
|
198
|
+
it "returns pem on to_s" do
|
|
199
|
+
test_cert = OpenSSL::X509::Certificate.new(@cert)
|
|
200
|
+
cert = R509::Cert.new(:cert => test_cert)
|
|
201
|
+
cert.to_s.should == @cert
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
context "when initialized with a pem" do
|
|
205
|
+
it "returns on to_pem" do
|
|
206
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
207
|
+
cert.to_pem.should == @cert
|
|
208
|
+
end
|
|
209
|
+
it "returns der on to_der" do
|
|
210
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
211
|
+
cert.to_der.should == @cert_der
|
|
212
|
+
end
|
|
213
|
+
it "returns pem on to_s" do
|
|
214
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
215
|
+
cert.to_s.should == @cert
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
it "gets key usage from the extensions array" do
|
|
219
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
220
|
+
cert.extensions["keyUsage"].nil?.should == false
|
|
221
|
+
cert.extensions["keyUsage"]["value"].should == "Digital Signature, Key Encipherment"
|
|
222
|
+
end
|
|
223
|
+
it "gets extended key usage from the extensions array" do
|
|
224
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
225
|
+
cert.extensions["extendedKeyUsage"].nil?.should == false
|
|
226
|
+
cert.extensions["extendedKeyUsage"]["value"].should == "TLS Web Server Authentication"
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "gets the right object from #basic_constraints" do
|
|
230
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
231
|
+
cert.basic_constraints.class.should == R509::Cert::Extensions::BasicConstraints
|
|
232
|
+
end
|
|
233
|
+
it "gets the right object from #key_usage" do
|
|
234
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
235
|
+
cert.key_usage.class.should == R509::Cert::Extensions::KeyUsage
|
|
236
|
+
end
|
|
237
|
+
it "gets the right object from #key_usage" do
|
|
238
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
239
|
+
cert.extended_key_usage.class.should == R509::Cert::Extensions::ExtendedKeyUsage
|
|
240
|
+
end
|
|
241
|
+
it "gets the right object from #subject_key_identifier" do
|
|
242
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
243
|
+
cert.subject_key_identifier.class.should == R509::Cert::Extensions::SubjectKeyIdentifier
|
|
244
|
+
end
|
|
245
|
+
it "gets the right object from #authority_key_identifier" do
|
|
246
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
247
|
+
cert.authority_key_identifier.class.should == R509::Cert::Extensions::AuthorityKeyIdentifier
|
|
248
|
+
end
|
|
249
|
+
it "gets the right object from #subject_alternative_name" do
|
|
250
|
+
cert = R509::Cert.new(:cert => @cert5)
|
|
251
|
+
cert.subject_alternative_name.class.should == R509::Cert::Extensions::SubjectAlternativeName
|
|
252
|
+
end
|
|
253
|
+
it "gets the right object from #authority_info_access" do
|
|
254
|
+
cert = R509::Cert.new(:cert => @cert5)
|
|
255
|
+
cert.authority_info_access.class.should == R509::Cert::Extensions::AuthorityInfoAccess
|
|
256
|
+
end
|
|
257
|
+
it "gets the right object from #crl_distribution_points" do
|
|
258
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
259
|
+
cert.crl_distribution_points.class.should == R509::Cert::Extensions::CrlDistributionPoints
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "checks rsa?" do
|
|
263
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
264
|
+
cert.rsa?.should == true
|
|
265
|
+
cert.dsa?.should == false
|
|
266
|
+
end
|
|
267
|
+
it "gets RSA bit strength" do
|
|
268
|
+
cert = R509::Cert.new(:cert => @cert)
|
|
269
|
+
cert.bit_strength.should == 2048
|
|
270
|
+
end
|
|
271
|
+
it "checks dsa?" do
|
|
272
|
+
cert = R509::Cert.new(:cert => @cert6)
|
|
273
|
+
cert.rsa?.should == false
|
|
274
|
+
cert.dsa?.should == true
|
|
275
|
+
end
|
|
276
|
+
it "gets DSA bit strength" do
|
|
277
|
+
cert = R509::Cert.new(:cert => @cert6)
|
|
278
|
+
cert.bit_strength.should == 1024
|
|
279
|
+
end
|
|
280
|
+
it "gets serial of cert" do
|
|
281
|
+
cert = R509::Cert.new(:cert => @cert6)
|
|
282
|
+
cert.serial.should == 951504
|
|
283
|
+
end
|
|
284
|
+
it "checks a cert that is not yet valid" do
|
|
285
|
+
cert = R509::Cert.new(:cert => @cert_not_yet_valid)
|
|
286
|
+
cert.valid?.should == false
|
|
287
|
+
end
|
|
288
|
+
it "checks a cert that is in validity range" do
|
|
289
|
+
cert = R509::Cert.new(:cert => @test_ca_cert)
|
|
290
|
+
cert.valid?.should == true
|
|
291
|
+
end
|
|
292
|
+
it "checks a cert that is expired" do
|
|
293
|
+
cert = R509::Cert.new(:cert => @cert_expired)
|
|
294
|
+
cert.valid?.should == false
|
|
295
|
+
end
|
|
296
|
+
it "checks expired_at?" do
|
|
297
|
+
cert = R509::Cert.new(:cert => @cert_expired)
|
|
298
|
+
cert.valid_at?(Time.utc(2009,1,1)).should == false
|
|
299
|
+
cert.valid_at?(Time.utc(2011,3,1)).should == true
|
|
300
|
+
cert.valid_at?(1298959200).should == true
|
|
301
|
+
cert.valid_at?(Time.utc(2012,1,1)).should == false
|
|
302
|
+
end
|
|
303
|
+
it "is revoked by crl" do
|
|
304
|
+
cert = R509::Cert.new(:cert => @cert3)
|
|
305
|
+
crl_admin = R509::Crl::Administrator.new(TestFixtures.test_ca_config)
|
|
306
|
+
crl_admin.revoke_cert(1425751142578902223005775172931960716533532010870)
|
|
307
|
+
crl = crl_admin.to_crl
|
|
308
|
+
cert.is_revoked_by_crl?(crl).should == true
|
|
309
|
+
end
|
|
310
|
+
it "is not revoked by crl" do
|
|
311
|
+
cert = R509::Cert.new(:cert => @cert3)
|
|
312
|
+
crl_admin = R509::Crl::Administrator.new(TestFixtures.test_ca_config)
|
|
313
|
+
crl = crl_admin.to_crl
|
|
314
|
+
cert.is_revoked_by_crl?(crl).should == false
|
|
315
|
+
end
|
|
316
|
+
it "loads a cert with load_from_file" do
|
|
317
|
+
path = File.dirname(__FILE__) + '/fixtures/cert1.pem'
|
|
318
|
+
cert = R509::Cert.load_from_file path
|
|
319
|
+
cert.serial.to_i.should == 211653423715
|
|
320
|
+
end
|
|
321
|
+
end
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe R509::CertificateAuthority::Signer do
|
|
4
|
+
before :each do
|
|
5
|
+
@cert = TestFixtures::CERT
|
|
6
|
+
@csr = TestFixtures::CSR
|
|
7
|
+
@csr_invalid_signature = TestFixtures::CSR_INVALID_SIGNATURE
|
|
8
|
+
@csr3 = TestFixtures::CSR3
|
|
9
|
+
@test_ca_config = TestFixtures.test_ca_config
|
|
10
|
+
@ca = R509::CertificateAuthority::Signer.new(@test_ca_config)
|
|
11
|
+
@ca_no_profile = R509::CertificateAuthority::Signer.new(TestFixtures.test_ca_no_profile_config)
|
|
12
|
+
@spki = TestFixtures::SPKI
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "raises an error if you don't pass csr or spki" do
|
|
16
|
+
expect { @ca.sign({ :profile_name => 'server' }) }.to raise_error(ArgumentError, "You must supply either :csr or :spki")
|
|
17
|
+
end
|
|
18
|
+
it "raises an error if you pass a config that has no private key for ca_cert" do
|
|
19
|
+
config = R509::Config::CaConfig.new( :ca_cert => R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT) )
|
|
20
|
+
profile = R509::Config::CaProfile.new
|
|
21
|
+
config.set_profile("some_profile",profile)
|
|
22
|
+
expect { R509::CertificateAuthority::Signer.new(config) }.to raise_error(R509::R509Error, "You must have a private key associated with your CA certificate to issue")
|
|
23
|
+
end
|
|
24
|
+
it "raises an error if you pass both csr and spki" do
|
|
25
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
26
|
+
spki = R509::Spki.new(:spki => @spki, :subject=>[['CN','test']])
|
|
27
|
+
expect { @ca.sign({ :spki => spki, :csr => csr, :profile_name => 'server' }) }.to raise_error(ArgumentError, "You can't pass both :csr and :spki")
|
|
28
|
+
end
|
|
29
|
+
it "raise an error if you don't pass an R509::Spki in :spki" do
|
|
30
|
+
spki = OpenSSL::Netscape::SPKI.new(@spki)
|
|
31
|
+
expect { @ca.sign({ :spki => spki, :profile_name => 'server' }) }.to raise_error(ArgumentError, 'You must pass an R509::Spki object for :spki')
|
|
32
|
+
end
|
|
33
|
+
it "raise an error if you don't pass an R509::Csr in :csr" do
|
|
34
|
+
csr = OpenSSL::X509::Request.new(@csr)
|
|
35
|
+
expect { @ca.sign({ :csr => csr, :profile_name => 'server' }) }.to raise_error(ArgumentError, 'You must pass an R509::Csr object for :csr')
|
|
36
|
+
end
|
|
37
|
+
it "raises an error if you have no CaProfiles with your CaConfig when attempting to issue a cert" do
|
|
38
|
+
config = R509::Config::CaConfig.new(
|
|
39
|
+
:ca_cert => TestFixtures.test_ca_cert
|
|
40
|
+
)
|
|
41
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
|
42
|
+
expect { ca.sign(:csr => @csr) }.to raise_error(R509::R509Error, 'You must have at least one CaProfile on your CaConfig to issue')
|
|
43
|
+
end
|
|
44
|
+
it "properly issues server cert using spki" do
|
|
45
|
+
spki = R509::Spki.new(:spki => @spki, :subject=>[['CN','test.local']])
|
|
46
|
+
cert = @ca.sign({ :spki => spki, :profile_name => 'server' })
|
|
47
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
|
48
|
+
cert.subject.to_s.should == '/CN=test.local'
|
|
49
|
+
extended_key_usage = cert.extensions['extendedKeyUsage']
|
|
50
|
+
extended_key_usage['value'].should == 'TLS Web Server Authentication'
|
|
51
|
+
end
|
|
52
|
+
it "properly issues server cert" do
|
|
53
|
+
csr = R509::Csr.new(:cert => @cert, :bit_strength => 1024)
|
|
54
|
+
cert = @ca.sign({ :csr => csr, :profile_name => 'server' })
|
|
55
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
|
56
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/L=Chicago/O=Paul Kehrer/CN=langui.sh'
|
|
57
|
+
extended_key_usage = cert.extensions['extendedKeyUsage']
|
|
58
|
+
extended_key_usage['value'].should == 'TLS Web Server Authentication'
|
|
59
|
+
end
|
|
60
|
+
it "when supplied, uses subject_item_policy to determine allowed subject" do
|
|
61
|
+
csr = R509::Csr.new(:cert => @cert, :bit_strength => 512)
|
|
62
|
+
cert = @ca.sign({ :csr => csr, :profile_name => 'server_with_subject_item_policy' })
|
|
63
|
+
#profile requires C, ST, CN. O and OU are optional
|
|
64
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/O=Paul Kehrer/CN=langui.sh'
|
|
65
|
+
end
|
|
66
|
+
it "raises error when issuing cert with csr that does not match subject_item_policy" do
|
|
67
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
68
|
+
expect { @ca.sign({ :csr => csr, :profile_name => 'server_with_subject_item_policy' }) }.to raise_error(R509::R509Error, /This profile requires you supply/)
|
|
69
|
+
end
|
|
70
|
+
it "issues with specified san domains" do
|
|
71
|
+
csr = R509::Csr.new(:cert => @cert, :bit_strength => 1024)
|
|
72
|
+
data_hash = csr.to_hash
|
|
73
|
+
data_hash[:san_names] = ['langui.sh','domain2.com']
|
|
74
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :data_hash => data_hash )
|
|
75
|
+
cert.san_names.should == ['langui.sh','domain2.com']
|
|
76
|
+
end
|
|
77
|
+
it "issues with san domains from csr" do
|
|
78
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
79
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
|
80
|
+
cert.san_names.should == ['test.local','additionaldomains.com','saniam.com']
|
|
81
|
+
end
|
|
82
|
+
it "issues a csr made via array" do
|
|
83
|
+
csr = R509::Csr.new(:subject => [['CN','langui.sh']], :bit_strength => 1024)
|
|
84
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
|
85
|
+
cert.subject.to_s.should == '/CN=langui.sh'
|
|
86
|
+
end
|
|
87
|
+
it "issues a cert with the subject array provided" do
|
|
88
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
89
|
+
data_hash = csr.to_hash
|
|
90
|
+
data_hash[:subject]['CN'] = "someotherdomain.com"
|
|
91
|
+
data_hash[:subject].delete("O")
|
|
92
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :data_hash => data_hash )
|
|
93
|
+
cert.subject.to_s.should == '/CN=someotherdomain.com'
|
|
94
|
+
end
|
|
95
|
+
it "tests that policy identifiers are properly encoded" do
|
|
96
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
97
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
|
98
|
+
cert.extensions['certificatePolicies']['value'].should == "Policy: 2.16.840.1.12345.1.2.3.4.1\n CPS: http://example.com/cps\n"
|
|
99
|
+
end
|
|
100
|
+
it "multiple policy identifiers are properly encoded" do
|
|
101
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
102
|
+
config = R509::Config::CaConfig.from_yaml("multi_policy_ca", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
|
103
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
|
104
|
+
cert = ca.sign(:csr => csr, :profile_name => 'server')
|
|
105
|
+
cert.extensions['certificatePolicies']['value'].should == "Policy: 2.16.840.1.9999999999.3.0\nPolicy: 2.16.840.1.9999999999.1.2.3.4.1\n CPS: http://example.com/cps\n"
|
|
106
|
+
end
|
|
107
|
+
it "tests basic constraints CA:TRUE and pathlen:0 on a subroot" do
|
|
108
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
109
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'subroot')
|
|
110
|
+
cert.extensions['basicConstraints']['value'].should == 'CA:TRUE, pathlen:0'
|
|
111
|
+
end
|
|
112
|
+
it "issues with md5" do
|
|
113
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
114
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'md5')
|
|
115
|
+
cert.cert.signature_algorithm.should == 'md5WithRSAEncryption'
|
|
116
|
+
end
|
|
117
|
+
it "issues with sha1" do
|
|
118
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
119
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha1')
|
|
120
|
+
cert.cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
|
121
|
+
end
|
|
122
|
+
it "issues with sha256" do
|
|
123
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
124
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha256')
|
|
125
|
+
cert.cert.signature_algorithm.should == 'sha256WithRSAEncryption'
|
|
126
|
+
end
|
|
127
|
+
it "issues with sha512" do
|
|
128
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
129
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha512')
|
|
130
|
+
cert.cert.signature_algorithm.should == 'sha512WithRSAEncryption'
|
|
131
|
+
end
|
|
132
|
+
it "issues with invalid hash (sha1 fallback)" do
|
|
133
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
134
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'invalid')
|
|
135
|
+
cert.cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
|
136
|
+
end
|
|
137
|
+
it "generates random serial when serial is not specified and uses microtime as part of the serial to prevent collision" do
|
|
138
|
+
now = Time.now
|
|
139
|
+
Time.stub!(:now).and_return(now)
|
|
140
|
+
time = now.to_i.to_s
|
|
141
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
142
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server")
|
|
143
|
+
cert.serial.to_s.size.should >= 45
|
|
144
|
+
cert.serial.to_s.index(time).should_not be_nil
|
|
145
|
+
end
|
|
146
|
+
it "accepts specified serial number" do
|
|
147
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
148
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server", :serial => 12345)
|
|
149
|
+
cert.serial.should == 12345
|
|
150
|
+
end
|
|
151
|
+
it "has default notBefore/notAfter dates" do
|
|
152
|
+
not_before = (Time.now - (6 * 60 * 60)).utc
|
|
153
|
+
not_after = (Time.now - (6 * 60 * 60) + (365 * 24 * 60 * 60)).utc
|
|
154
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
155
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server")
|
|
156
|
+
cert.cert.not_before.year.should == not_before.year
|
|
157
|
+
cert.cert.not_before.month.should == not_before.month
|
|
158
|
+
cert.cert.not_before.day.should == not_before.day
|
|
159
|
+
cert.cert.not_before.hour.should == not_before.hour
|
|
160
|
+
cert.cert.not_before.min.should == not_before.min
|
|
161
|
+
cert.cert.not_after.year.should == not_after.year
|
|
162
|
+
cert.cert.not_after.month.should == not_after.month
|
|
163
|
+
cert.cert.not_after.day.should == not_after.day
|
|
164
|
+
cert.cert.not_after.hour.should == not_after.hour
|
|
165
|
+
cert.cert.not_after.min.should == not_after.min
|
|
166
|
+
end
|
|
167
|
+
it "allows you to specify notBefore/notAfter dates" do
|
|
168
|
+
not_before = Time.now - 5 * 60 * 60
|
|
169
|
+
not_after = Time.now + 5 * 60 * 60
|
|
170
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
171
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server", :not_before => not_before, :not_after => not_after)
|
|
172
|
+
cert.cert.not_before.ctime.should == not_before.utc.ctime
|
|
173
|
+
cert.cert.not_after.ctime.should == not_after.utc.ctime
|
|
174
|
+
end
|
|
175
|
+
it "issues a certificate from a root that does not have a subjectKeyIdentifier" do
|
|
176
|
+
config = R509::Config::CaConfig.from_yaml("missing_key_identifier_ca", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
|
177
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
|
178
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
179
|
+
cert = ca.sign(:csr => csr, :profile_name => "server")
|
|
180
|
+
cert.extensions['authorityKeyIdentifier'].should == nil
|
|
181
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
|
182
|
+
end
|
|
183
|
+
it "raises error unless you provide a proper config (or nil)" do
|
|
184
|
+
expect { R509::CertificateAuthority::Signer.new('invalid') }.to raise_error(R509::R509Error, 'config must be a kind of R509::Config::CaConfig or nil (for self-sign only)')
|
|
185
|
+
end
|
|
186
|
+
it "raises error when providing invalid ca profile" do
|
|
187
|
+
csr = R509::Csr.new(:csr => @csr)
|
|
188
|
+
expect { @ca.sign(:csr => csr, :profile_name => 'invalid') }.to raise_error(R509::R509Error, "unknown profile 'invalid'")
|
|
189
|
+
end
|
|
190
|
+
it "raises error when attempting to issue CSR with invalid signature" do
|
|
191
|
+
csr = R509::Csr.new(:csr => @csr_invalid_signature)
|
|
192
|
+
expect { @ca.sign(:csr => csr, :profile_name => 'server') }.to raise_error(R509::R509Error, 'Certificate request signature is invalid.')
|
|
193
|
+
end
|
|
194
|
+
it "raises error when passing non-hash to selfsign method" do
|
|
195
|
+
expect { @ca.selfsign(@csr) }.to raise_error(ArgumentError, "You must pass a hash of options consisting of at minimum :csr")
|
|
196
|
+
end
|
|
197
|
+
it "issues a self-signed certificate with custom fields" do
|
|
198
|
+
not_before = Time.now.to_i
|
|
199
|
+
not_after = Time.now.to_i+3600*24*7300
|
|
200
|
+
csr = R509::Csr.new(
|
|
201
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
|
202
|
+
:bit_strength => 1024
|
|
203
|
+
)
|
|
204
|
+
cert = @ca.selfsign(
|
|
205
|
+
:csr => csr,
|
|
206
|
+
:serial => 3,
|
|
207
|
+
:not_before => not_before,
|
|
208
|
+
:not_after => not_after,
|
|
209
|
+
:message_digest => 'sha256',
|
|
210
|
+
:san_names => ['sanname1','sanname2']
|
|
211
|
+
)
|
|
212
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
|
213
|
+
cert.signature_algorithm.should == 'sha256WithRSAEncryption'
|
|
214
|
+
cert.serial.should == 3
|
|
215
|
+
cert.not_before.to_i.should == not_before
|
|
216
|
+
cert.not_after.to_i.should == not_after
|
|
217
|
+
cert.subject.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
|
218
|
+
cert.issuer.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
|
219
|
+
cert.extensions['basicConstraints']['value'].should == 'CA:TRUE'
|
|
220
|
+
cert.san_names.should include('sanname1','sanname2')
|
|
221
|
+
end
|
|
222
|
+
it "issues self-signed certificate with SAN in CSR" do
|
|
223
|
+
csr = R509::Csr.new(
|
|
224
|
+
:subject => [['CN','My Self Sign']],
|
|
225
|
+
:san_names => ['sanname1','sanname2'],
|
|
226
|
+
:bit_strength => 1024
|
|
227
|
+
)
|
|
228
|
+
cert = @ca.selfsign(
|
|
229
|
+
:csr => csr
|
|
230
|
+
)
|
|
231
|
+
cert.san_names.should include('sanname1','sanname2')
|
|
232
|
+
cert.subject.to_s.should == '/CN=My Self Sign'
|
|
233
|
+
cert.issuer.to_s.should == '/CN=My Self Sign'
|
|
234
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
|
235
|
+
end
|
|
236
|
+
it "issues a self-signed certificate with defaults" do
|
|
237
|
+
csr = R509::Csr.new(
|
|
238
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
|
239
|
+
:bit_strength => 1024
|
|
240
|
+
)
|
|
241
|
+
cert = @ca.selfsign(
|
|
242
|
+
:csr => csr
|
|
243
|
+
)
|
|
244
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
|
245
|
+
cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
|
246
|
+
(cert.not_after.to_i-cert.not_before.to_i).should == 31536000
|
|
247
|
+
cert.subject.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
|
248
|
+
cert.issuer.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
|
249
|
+
cert.extensions['basicConstraints']['value'].should == 'CA:TRUE'
|
|
250
|
+
end
|
|
251
|
+
it "raises an error if attempting to self-sign without a key" do
|
|
252
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
253
|
+
expect { @ca.selfsign( :csr => csr ) }.to raise_error(ArgumentError, "CSR must also have a private key to self sign")
|
|
254
|
+
end
|
|
255
|
+
it "raises an error if you call sign without passing a config to the object" do
|
|
256
|
+
ca_signer = R509::CertificateAuthority::Signer.new
|
|
257
|
+
csr = R509::Csr.new(:csr => @csr3)
|
|
258
|
+
expect { ca_signer.sign(:csr => csr, :profile_name => "server") }.to raise_error(R509::R509Error, "When instantiating the signer without a config you can only call #selfsign")
|
|
259
|
+
end
|
|
260
|
+
end
|