r509 0.8.1 → 0.9
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 +343 -151
- data/Rakefile +26 -23
- data/bin/r509 +126 -112
- data/bin/r509-parse +24 -24
- data/doc/R509.html +169 -7
- data/doc/R509/ASN1.html +370 -0
- data/doc/R509/ASN1/GeneralName.html +1121 -0
- data/doc/R509/ASN1/GeneralNames.html +843 -0
- data/doc/R509/ASN1/NoticeReference.html +392 -0
- data/doc/R509/ASN1/PolicyInformation.html +387 -0
- data/doc/R509/ASN1/PolicyQualifiers.html +455 -0
- data/doc/R509/ASN1/UserNotice.html +386 -0
- data/doc/R509/{Crl.html → CRL.html} +7 -7
- data/doc/R509/CRL/Administrator.html +1559 -0
- data/doc/R509/{Crl/Parser.html → CRL/SignedList.html} +501 -210
- data/doc/R509/{Csr.html → CSR.html} +444 -314
- data/doc/R509/Cert.html +866 -617
- data/doc/R509/Cert/Extensions.html +52 -41
- data/doc/R509/Cert/Extensions/AuthorityInfoAccess.html +70 -35
- data/doc/R509/Cert/Extensions/AuthorityKeyIdentifier.html +387 -4
- data/doc/R509/Cert/Extensions/BasicConstraints.html +61 -25
- data/doc/R509/Cert/Extensions/CRLDistributionPoints.html +354 -0
- data/doc/R509/Cert/Extensions/CertificatePolicies.html +340 -0
- data/doc/R509/Cert/Extensions/ExtendedKeyUsage.html +440 -49
- data/doc/R509/Cert/Extensions/{CrlDistributionPoints.html → InhibitAnyPolicy.html} +52 -35
- data/doc/R509/Cert/Extensions/KeyUsage.html +247 -121
- data/doc/R509/Cert/Extensions/NameConstraints.html +445 -0
- data/doc/R509/Cert/Extensions/OCSPNoCheck.html +239 -0
- data/doc/R509/Cert/Extensions/PolicyConstraints.html +424 -0
- data/doc/R509/Cert/Extensions/SubjectAlternativeName.html +437 -62
- data/doc/R509/Cert/Extensions/SubjectKeyIdentifier.html +52 -10
- data/doc/R509/CertificateAuthority.html +4 -4
- data/doc/R509/CertificateAuthority/Signer.html +154 -187
- data/doc/R509/Config.html +6 -6
- data/doc/R509/Config/{CaConfig.html → CAConfig.html} +451 -348
- data/doc/R509/Config/{CaConfigPool.html → CAConfigPool.html} +47 -47
- data/doc/R509/Config/CAProfile.html +1015 -0
- data/doc/R509/Config/SubjectItemPolicy.html +86 -86
- data/doc/R509/IOHelpers.html +22 -22
- data/doc/R509/MessageDigest.html +14 -14
- data/doc/R509/NameSanitizer.html +53 -53
- data/doc/R509/{Ocsp.html → OCSP.html} +9 -9
- data/doc/R509/{Ocsp → OCSP}/Request.html +7 -7
- data/doc/R509/{Ocsp → OCSP}/Request/Nonce.html +56 -11
- data/doc/R509/{Ocsp → OCSP}/Response.html +44 -44
- data/doc/R509/{OidMapper.html → OIDMapper.html} +23 -39
- data/doc/R509/PrivateKey.html +415 -168
- data/doc/R509/R509Error.html +3 -3
- data/doc/R509/{Spki.html → SPKI.html} +354 -192
- data/doc/R509/Subject.html +224 -113
- data/doc/R509/Validity.html +27 -5
- data/doc/R509/Validity/Checker.html +13 -13
- data/doc/R509/Validity/DefaultChecker.html +13 -13
- data/doc/R509/Validity/DefaultWriter.html +14 -14
- data/doc/R509/Validity/Status.html +39 -39
- data/doc/R509/Validity/Writer.html +18 -18
- data/doc/_index.html +138 -35
- data/doc/class_list.html +1 -1
- data/doc/css/style.css +10 -0
- data/doc/file.README.html +368 -171
- data/doc/file.r509.html +92 -69
- data/doc/frames.html +1 -1
- data/doc/index.html +368 -171
- data/doc/method_list.html +910 -390
- data/doc/top-level-namespace.html +3 -3
- data/lib/r509.rb +32 -16
- data/lib/r509/asn1.rb +375 -0
- data/lib/r509/cert.rb +381 -364
- data/lib/r509/cert/extensions.rb +443 -76
- data/lib/r509/certificate_authority.rb +407 -0
- data/lib/r509/config.rb +547 -351
- data/lib/r509/crl.rb +336 -366
- data/lib/r509/csr.rb +278 -289
- data/lib/r509/ec-hack.rb +37 -0
- data/lib/r509/exceptions.rb +3 -3
- data/lib/r509/io_helpers.rb +44 -44
- data/lib/r509/message_digest.rb +53 -0
- data/lib/r509/ocsp.rb +80 -70
- data/lib/r509/oid_mapper.rb +32 -0
- data/lib/r509/private_key.rb +228 -0
- data/lib/r509/spki.rb +145 -93
- data/lib/r509/subject.rb +203 -110
- data/lib/r509/validity.rb +70 -68
- data/lib/r509/version.rb +2 -2
- data/r509.yaml +92 -69
- data/spec/asn1_spec.rb +402 -0
- data/spec/cert/extensions_spec.rb +957 -494
- data/spec/cert_spec.rb +382 -307
- data/spec/certificate_authority_spec.rb +668 -250
- data/spec/config_spec.rb +515 -302
- data/spec/crl_spec.rb +197 -198
- data/spec/csr_spec.rb +334 -289
- data/spec/fixtures.rb +247 -171
- data/spec/fixtures/cert1.der +0 -0
- data/spec/fixtures/cert1.pem +0 -0
- data/spec/fixtures/cert1_public_key_modulus.txt +0 -0
- data/spec/fixtures/cert3.p12 +0 -0
- data/spec/fixtures/cert3.pem +0 -0
- data/spec/fixtures/cert3_key.pem +0 -0
- data/spec/fixtures/cert3_key_des3.pem +0 -0
- data/spec/fixtures/cert4.pem +0 -0
- data/spec/fixtures/cert5.pem +0 -0
- data/spec/fixtures/cert6.pem +0 -0
- data/spec/fixtures/cert_expired.pem +0 -0
- data/spec/fixtures/cert_inhibit.pem +24 -0
- data/spec/fixtures/cert_name_constraints.pem +29 -0
- data/spec/fixtures/cert_not_yet_valid.pem +0 -0
- data/spec/fixtures/cert_ocsp_no_check.pem +18 -0
- data/spec/fixtures/cert_policy_constraints.pem +31 -0
- data/spec/fixtures/cert_san.pem +0 -0
- data/spec/fixtures/cert_san2.pem +0 -0
- data/spec/fixtures/cert_unknown_extension.pem +28 -0
- data/spec/fixtures/config_pool_test_minimal.yaml +11 -11
- data/spec/fixtures/config_test.yaml +54 -36
- data/spec/fixtures/config_test_dsa.yaml +35 -0
- data/spec/fixtures/config_test_ec.yaml +35 -0
- data/spec/fixtures/config_test_engine_key.yaml +5 -5
- data/spec/fixtures/config_test_engine_no_key_name.yaml +4 -4
- data/spec/fixtures/config_test_minimal.yaml +4 -4
- data/spec/fixtures/config_test_password.yaml +5 -5
- data/spec/fixtures/config_test_various.yaml +111 -74
- data/spec/fixtures/crl_list_file.txt +0 -0
- data/spec/fixtures/crl_with_reason.pem +0 -0
- data/spec/fixtures/csr1.der +0 -0
- data/spec/fixtures/csr1.pem +0 -0
- data/spec/fixtures/csr1_key.der +0 -0
- data/spec/fixtures/csr1_key.pem +0 -0
- data/spec/fixtures/csr1_key_encrypted_des3.pem +0 -0
- data/spec/fixtures/csr1_newlines.pem +0 -0
- data/spec/fixtures/csr1_no_begin_end.pem +0 -0
- data/spec/fixtures/csr1_public_key_modulus.txt +0 -0
- data/spec/fixtures/csr2.pem +0 -0
- data/spec/fixtures/csr2_key.pem +0 -0
- data/spec/fixtures/csr3.pem +0 -0
- data/spec/fixtures/csr4.pem +0 -0
- data/spec/fixtures/csr_dsa.pem +0 -0
- data/spec/fixtures/csr_invalid_signature.pem +0 -0
- data/spec/fixtures/dsa_key.pem +0 -0
- data/spec/fixtures/dsa_root.cer +28 -0
- data/spec/fixtures/dsa_root.key +20 -0
- data/spec/fixtures/ec_csr2.der +0 -0
- data/spec/fixtures/ec_csr2.pem +8 -0
- data/spec/fixtures/ec_key1.der +0 -0
- data/spec/fixtures/ec_key1.pem +6 -0
- data/spec/fixtures/ec_key1_encrypted.pem +9 -0
- data/spec/fixtures/ec_key2.pem +6 -0
- data/spec/fixtures/hmacsha1.sig +1 -0
- data/spec/fixtures/hmacsha512.sig +1 -0
- data/spec/fixtures/key4.pem +0 -0
- data/spec/fixtures/key4_encrypted_des3.pem +0 -0
- data/spec/fixtures/missing_key_identifier_ca.cer +0 -0
- data/spec/fixtures/missing_key_identifier_ca.key +0 -0
- data/spec/fixtures/ocsptest.r509.local.pem +0 -0
- data/spec/fixtures/ocsptest.r509.local_ocsp_request.der +0 -0
- data/spec/fixtures/ocsptest2.r509.local.pem +0 -0
- data/spec/fixtures/second_ca.cer +0 -0
- data/spec/fixtures/second_ca.key +0 -0
- data/spec/fixtures/spkac.der +0 -0
- data/spec/fixtures/spkac.txt +0 -0
- data/spec/fixtures/spkac_dsa.txt +1 -1
- data/spec/fixtures/spkac_dsa_no_verify.txt +1 -0
- data/spec/fixtures/spkac_ec.txt +1 -0
- data/spec/fixtures/spkac_rsa_newlines.txt +13 -0
- data/spec/fixtures/stca.pem +0 -0
- data/spec/fixtures/stca_ocsp_request.der +0 -0
- data/spec/fixtures/stca_ocsp_response.der +0 -0
- data/spec/fixtures/test1.csr +0 -0
- data/spec/fixtures/test_ca.cer +0 -0
- data/spec/fixtures/test_ca.key +0 -0
- data/spec/fixtures/test_ca.p12 +0 -0
- data/spec/fixtures/test_ca_des3.key +0 -0
- data/spec/fixtures/test_ca_ec.cer +14 -0
- data/spec/fixtures/test_ca_ec.key +6 -0
- data/spec/fixtures/test_ca_ec_ee.cer +22 -0
- data/spec/fixtures/test_ca_ec_ee.key +6 -0
- data/spec/fixtures/test_ca_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_ocsp.key +0 -0
- data/spec/fixtures/test_ca_ocsp.p12 +0 -0
- data/spec/fixtures/test_ca_ocsp_chain.txt +0 -0
- data/spec/fixtures/test_ca_ocsp_response.der +0 -0
- data/spec/fixtures/test_ca_subroot.cer +0 -0
- data/spec/fixtures/test_ca_subroot.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.cer +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp.key +0 -0
- data/spec/fixtures/test_ca_subroot_ocsp_response.der +0 -0
- data/spec/fixtures/unknown_oid.csr +0 -0
- data/spec/message_digest_spec.rb +104 -84
- data/spec/ocsp_spec.rb +105 -105
- data/spec/oid_mapper_spec.rb +21 -21
- data/spec/private_key_spec.rb +275 -0
- data/spec/r509_spec.rb +35 -0
- data/spec/spec_helper.rb +15 -6
- data/spec/spki_spec.rb +221 -142
- data/spec/subject_spec.rb +232 -164
- data/spec/validity_spec.rb +91 -91
- metadata +79 -25
- data/doc/R509/Config/CaProfile.html +0 -651
- data/doc/R509/Crl/Administrator.html +0 -2073
- data/lib/r509/certificateauthority.rb +0 -290
- data/lib/r509/messagedigest.rb +0 -49
- data/lib/r509/oidmapper.rb +0 -32
- data/lib/r509/privatekey.rb +0 -185
- data/spec/privatekey_spec.rb +0 -198
@@ -1,260 +1,678 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe R509::CertificateAuthority::Signer do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
4
|
+
before :each do
|
5
|
+
@csr = TestFixtures::CSR
|
6
|
+
@csr_invalid_signature = TestFixtures::CSR_INVALID_SIGNATURE
|
7
|
+
@csr3 = TestFixtures::CSR3
|
8
|
+
@test_ca_config = TestFixtures.test_ca_config
|
9
|
+
@ca = R509::CertificateAuthority::Signer.new(@test_ca_config)
|
10
|
+
@ca_no_profile = R509::CertificateAuthority::Signer.new(TestFixtures.test_ca_no_profile_config)
|
11
|
+
@spki = TestFixtures::SPKI
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
14
|
+
it "raises an error if you don't pass csr or spki" do
|
15
|
+
expect { @ca.sign({ :profile_name => 'server' }) }.to raise_error(ArgumentError, "You must supply either :csr or :spki")
|
16
|
+
end
|
17
|
+
it "raises an error if you pass a config that has no private key for ca_cert" do
|
18
|
+
config = R509::Config::CAConfig.new( :ca_cert => R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT) )
|
19
|
+
profile = R509::Config::CAProfile.new
|
20
|
+
config.set_profile("some_profile",profile)
|
21
|
+
expect { R509::CertificateAuthority::Signer.new(config) }.to raise_error(R509::R509Error, "You must have a private key associated with your CA certificate to issue")
|
22
|
+
end
|
23
|
+
it "raises an error if you pass both csr and spki" do
|
24
|
+
csr = R509::CSR.new(:csr => @csr)
|
25
|
+
spki = R509::SPKI.new(:spki => @spki, :subject=>[['CN','test']])
|
26
|
+
expect { @ca.sign({ :spki => spki, :csr => csr, :profile_name => 'server' }) }.to raise_error(ArgumentError, "You can't pass both :csr and :spki")
|
27
|
+
end
|
28
|
+
it "raise an error if you don't pass an R509::SPKI in :spki" do
|
29
|
+
spki = OpenSSL::Netscape::SPKI.new(@spki)
|
30
|
+
expect { @ca.sign({ :spki => spki, :profile_name => 'server' }) }.to raise_error(ArgumentError, 'You must pass an R509::SPKI object for :spki')
|
31
|
+
end
|
32
|
+
it "raise an error if you pass :spki without :subject" do
|
33
|
+
spki = R509::SPKI.new(:spki => @spki)
|
34
|
+
expect { @ca.sign({ :spki => spki, :profile_name => 'server' }) }.to raise_error(ArgumentError, 'You must supply :subject when passing :spki')
|
35
|
+
end
|
36
|
+
it "raise an error if you don't pass an R509::CSR in :csr" do
|
37
|
+
csr = OpenSSL::X509::Request.new(@csr)
|
38
|
+
expect { @ca.sign({ :csr => csr, :profile_name => 'server' }) }.to raise_error(ArgumentError, 'You must pass an R509::CSR object for :csr')
|
39
|
+
end
|
40
|
+
it "raises an error if you have no CAProfile with your CAConfig when attempting to issue a cert" do
|
41
|
+
config = R509::Config::CAConfig.new(
|
42
|
+
:ca_cert => TestFixtures.test_ca_cert
|
43
|
+
)
|
44
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
45
|
+
expect { ca.sign(:csr => @csr) }.to raise_error(R509::R509Error, 'You must have at least one CAProfile on your CAConfig to issue')
|
46
|
+
end
|
47
|
+
it "properly issues a cert with the default CAProfile configuration" do
|
48
|
+
csr = R509::CSR.new(:subject => [["CN","testy.mctest"]], :bit_strength => 1024)
|
49
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
50
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
51
|
+
profile = R509::Config::CAProfile.new
|
52
|
+
config.set_profile("default",profile)
|
53
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
54
|
+
expect { ca.sign( :csr => csr, :profile_name => 'default') }.to_not raise_error
|
55
|
+
end
|
56
|
+
it "properly issues server cert using spki" do
|
57
|
+
spki = R509::SPKI.new(:spki => @spki)
|
58
|
+
cert = @ca.sign({ :spki => spki, :profile_name => 'server', :subject=>[['CN','test.local']]})
|
59
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
60
|
+
cert.subject.to_s.should == '/CN=test.local'
|
61
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
62
|
+
end
|
63
|
+
it "properly issues server cert" do
|
64
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
65
|
+
cert = @ca.sign({ :csr => csr, :profile_name => 'server' })
|
66
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
67
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/L=Chicago/O=Paul Kehrer/CN=langui.sh'
|
68
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
69
|
+
end
|
70
|
+
it "properly issues cert with all EKUs" do
|
71
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
72
|
+
config = R509::Config::CAConfig.from_yaml("all_eku_ca", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
73
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
74
|
+
cert = ca.sign({ :csr => csr, :profile_name => 'smorgasbord' })
|
75
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
76
|
+
cert.extended_key_usage.web_client_authentication?.should == true
|
77
|
+
cert.extended_key_usage.code_signing?.should == true
|
78
|
+
cert.extended_key_usage.email_protection?.should == true
|
79
|
+
cert.extended_key_usage.ocsp_signing?.should == true
|
80
|
+
cert.extended_key_usage.time_stamping?.should == true
|
81
|
+
end
|
82
|
+
it "properly issues cert with OCSP noCheck in profile" do
|
83
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
84
|
+
config = R509::Config::CAConfig.from_yaml("ocsp_no_check_ca", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_various.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
85
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
86
|
+
cert = ca.sign({ :csr => csr, :profile_name => 'ocsp_no_check_delegate' })
|
87
|
+
cert.ocsp_no_check?.should == true
|
88
|
+
cert.extended_key_usage.ocsp_signing?.should == true
|
89
|
+
end
|
90
|
+
it "does not encode noCheck if not specified by the profile" do
|
91
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
92
|
+
cert = @ca.sign({ :csr => csr, :profile_name => 'server' })
|
93
|
+
cert.ocsp_no_check?.should == false
|
94
|
+
end
|
95
|
+
it "when supplied, uses subject_item_policy to determine allowed subject" do
|
96
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
97
|
+
cert = @ca.sign({ :csr => csr, :profile_name => 'server_with_subject_item_policy' })
|
98
|
+
#profile requires C, ST, CN. O and OU are optional
|
99
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/O=Paul Kehrer/CN=langui.sh'
|
100
|
+
end
|
101
|
+
it "raises error when issuing cert with csr that does not match subject_item_policy" do
|
102
|
+
csr = R509::CSR.new(:csr => @csr)
|
103
|
+
expect { @ca.sign({ :csr => csr, :profile_name => 'server_with_subject_item_policy' }) }.to raise_error(R509::R509Error, /This profile requires you supply/)
|
104
|
+
end
|
105
|
+
it "issues with specified (dnsName) san domains in array" do
|
106
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
107
|
+
san_names = ['langui.sh','domain2.com']
|
108
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :subject => csr.subject, :san_names => san_names )
|
109
|
+
cert.san.dns_names.should == ['langui.sh','domain2.com']
|
110
|
+
end
|
111
|
+
it "issues with empty san_names array" do
|
112
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
113
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :subject => csr.subject, :san_names => [] )
|
114
|
+
cert.san.should be_nil
|
115
|
+
end
|
116
|
+
it "issues with specified (directoryName and dnsName) san domains in array" do
|
117
|
+
name = [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']]
|
118
|
+
csr = R509::CSR.new(:subject => name, :bit_strength => 1024)
|
119
|
+
san_names = ['langui.sh','domain2.com',name]
|
120
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :subject => csr.subject, :san_names => san_names )
|
121
|
+
cert.san.dns_names.should == ['langui.sh','domain2.com']
|
122
|
+
cert.san.directory_names.size.should == 1
|
123
|
+
cert.san.directory_names[0].to_s.should == "/C=US/ST=Illinois/L=Chicago/O=Paul Kehrer/CN=langui.sh"
|
124
|
+
end
|
125
|
+
it "issues with specified san domains in R509::ASN1::GeneralNames object" do
|
126
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :bit_strength => 1024)
|
127
|
+
san_names = R509::ASN1.general_name_parser(['langui.sh','domain2.com'])
|
128
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :subject => csr.subject, :san_names => san_names )
|
129
|
+
cert.san.dns_names.should == ['langui.sh','domain2.com']
|
130
|
+
end
|
131
|
+
it "issues with san domains from csr" do
|
132
|
+
csr = R509::CSR.new(:csr => @csr)
|
133
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
134
|
+
cert.san.dns_names.should == ['test.local','additionaldomains.com','saniam.com']
|
135
|
+
end
|
136
|
+
it "issues a csr made via array" do
|
137
|
+
csr = R509::CSR.new(:subject => [['CN','langui.sh']], :bit_strength => 1024)
|
138
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
139
|
+
cert.subject.to_s.should == '/CN=langui.sh'
|
140
|
+
end
|
141
|
+
it "overrides a CSR's subject with :subject" do
|
142
|
+
csr = R509::CSR.new(:csr => @csr)
|
143
|
+
subject = csr.subject
|
144
|
+
subject.CN = "someotherdomain.com"
|
145
|
+
subject.delete("O")
|
146
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :subject => subject )
|
147
|
+
cert.subject.to_s.should == '/CN=someotherdomain.com'
|
148
|
+
end
|
149
|
+
it "tests that policy identifiers are properly encoded" do
|
150
|
+
csr = R509::CSR.new(:csr => @csr)
|
151
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
152
|
+
cert.certificate_policies.should_not be_nil
|
153
|
+
cert.certificate_policies.policies.count.should == 1
|
154
|
+
cert.certificate_policies.policies[0].policy_identifier.should == "2.16.840.1.12345.1.2.3.4.1"
|
155
|
+
cert.certificate_policies.policies[0].policy_qualifiers.cps_uris.should == ["http://example.com/cps", "http://other.com/cps"]
|
156
|
+
cert.certificate_policies.policies[0].policy_qualifiers.user_notices.count.should == 1
|
157
|
+
un = cert.certificate_policies.policies[0].policy_qualifiers.user_notices[0]
|
158
|
+
un.notice_reference.notice_numbers.should == [1,2,3,4]
|
159
|
+
un.notice_reference.organization.should == 'my org'
|
160
|
+
un.explicit_text.should == "thing"
|
161
|
+
end
|
162
|
+
it "multiple policy identifiers are properly encoded" do
|
163
|
+
csr = R509::CSR.new(:csr => @csr)
|
164
|
+
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"})
|
165
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
166
|
+
cert = ca.sign(:csr => csr, :profile_name => 'server')
|
167
|
+
cert.certificate_policies.should_not be_nil
|
168
|
+
cert.certificate_policies.policies.count.should == 2
|
169
|
+
p0 = cert.certificate_policies.policies[0]
|
170
|
+
p0.policy_identifier.should == "2.16.840.1.99999.21.234"
|
171
|
+
p0.policy_qualifiers.cps_uris.should == ["http://example.com/cps", "http://haha.com"]
|
172
|
+
p0.policy_qualifiers.user_notices.count.should == 1
|
173
|
+
un0 = p0.policy_qualifiers.user_notices[0]
|
174
|
+
un0.notice_reference.notice_numbers.should == [1,2,3]
|
175
|
+
un0.notice_reference.organization.should == "my org"
|
176
|
+
un0.explicit_text.should == "this is a great thing"
|
177
|
+
p1 = cert.certificate_policies.policies[1]
|
178
|
+
p1.policy_identifier.should == "2.16.840.1.99999.21.235"
|
179
|
+
p1.policy_qualifiers.cps_uris.should == ["http://example.com/cps2"]
|
180
|
+
p1.policy_qualifiers.user_notices.count.should == 2
|
181
|
+
un1 = p1.policy_qualifiers.user_notices[0]
|
182
|
+
un1.notice_reference.notice_numbers.should == [3,2,1]
|
183
|
+
un1.notice_reference.organization.should == "another org"
|
184
|
+
un1.explicit_text.should == 'this is a bad thing'
|
185
|
+
un2 = p1.policy_qualifiers.user_notices[1]
|
186
|
+
un2.notice_reference.should be_nil
|
187
|
+
un2.explicit_text.should == "another user notice"
|
188
|
+
end
|
189
|
+
it "issues a certificate with an authority key identifier" do
|
190
|
+
csr = R509::CSR.new(:csr => @csr)
|
191
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server')
|
192
|
+
cert.authority_key_identifier.should_not be_nil
|
193
|
+
end
|
194
|
+
context "inhibitAnyPolicy" do
|
195
|
+
it "issues without inhibit any policy when not present" do
|
196
|
+
csr = R509::CSR.new(:csr => @csr)
|
197
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
198
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
199
|
+
profile = R509::Config::CAProfile.new
|
200
|
+
config.set_profile("default",profile)
|
201
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
202
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
203
|
+
cert.inhibit_any_policy.should == nil
|
204
|
+
end
|
205
|
+
it "issues with inhibit any policy when present" do
|
206
|
+
csr = R509::CSR.new(:csr => @csr)
|
207
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
208
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
209
|
+
profile = R509::Config::CAProfile.new(:inhibit_any_policy => 1)
|
210
|
+
config.set_profile("default",profile)
|
211
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
212
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
213
|
+
cert.inhibit_any_policy.skip_certs.should == 1
|
214
|
+
end
|
215
|
+
end
|
216
|
+
context "policyConstraints" do
|
217
|
+
it "issues without policy constraints when not present" do
|
218
|
+
csr = R509::CSR.new(:csr => @csr)
|
219
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
220
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
221
|
+
profile = R509::Config::CAProfile.new
|
222
|
+
config.set_profile("default",profile)
|
223
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
224
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
225
|
+
cert.policy_constraints.should == nil
|
226
|
+
end
|
227
|
+
it "issues with require_explicit_policy" do
|
228
|
+
csr = R509::CSR.new(:csr => @csr)
|
229
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
230
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
231
|
+
profile = R509::Config::CAProfile.new(:policy_constraints => {"require_explicit_policy" => 3})
|
232
|
+
config.set_profile("default",profile)
|
233
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
234
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
235
|
+
cert.policy_constraints.require_explicit_policy.should == 3
|
236
|
+
cert.policy_constraints.inhibit_policy_mapping.should == nil
|
237
|
+
end
|
238
|
+
it "issues with inhibit_policy_mapping" do
|
239
|
+
csr = R509::CSR.new(:csr => @csr)
|
240
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
241
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
242
|
+
profile = R509::Config::CAProfile.new(:policy_constraints => {"inhibit_policy_mapping" => 3})
|
243
|
+
config.set_profile("default",profile)
|
244
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
245
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
246
|
+
cert.policy_constraints.require_explicit_policy.should == nil
|
247
|
+
cert.policy_constraints.inhibit_policy_mapping.should == 3
|
248
|
+
end
|
249
|
+
it "issues with both require and inhibit" do
|
250
|
+
csr = R509::CSR.new(:csr => @csr)
|
251
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
252
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
253
|
+
profile = R509::Config::CAProfile.new(:policy_constraints => {"require_explicit_policy" => 3, "inhibit_policy_mapping" => 2})
|
254
|
+
config.set_profile("default",profile)
|
255
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
256
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
257
|
+
cert.policy_constraints.require_explicit_policy.should == 3
|
258
|
+
cert.policy_constraints.inhibit_policy_mapping.should == 2
|
259
|
+
end
|
260
|
+
end
|
261
|
+
context "nameConstraints" do
|
262
|
+
it "issues with no constraints if not present in profile" do
|
263
|
+
csr = R509::CSR.new(:csr => @csr)
|
264
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
265
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
266
|
+
profile = R509::Config::CAProfile.new
|
267
|
+
config.set_profile("default",profile)
|
268
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
269
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
270
|
+
cert.name_constraints.should be_nil
|
271
|
+
end
|
272
|
+
it "issues with permitted constraints" do
|
273
|
+
csr = R509::CSR.new(:csr => @csr)
|
274
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
275
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
276
|
+
profile = R509::Config::CAProfile.new(:name_constraints => { "permitted" => [ { "type" => "DNS", "value" => "domain.com" } , { "type" => "IP", "value" => "ff::/ff:ff:ff:ff:ff:ff:ff:ff" } ] } )
|
277
|
+
config.set_profile("default",profile)
|
278
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
279
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
280
|
+
cert.name_constraints.permitted_names[0].type.should == :dNSName
|
281
|
+
cert.name_constraints.permitted_names[0].value.should == 'domain.com'
|
282
|
+
cert.name_constraints.permitted_names[1].type.should == :iPAddress
|
283
|
+
cert.name_constraints.permitted_names[1].value.should == 'ff::/ff:ff:ff:ff:ff:ff:ff:ff'
|
284
|
+
end
|
285
|
+
it "issues with excluded constraints" do
|
286
|
+
csr = R509::CSR.new(:csr => @csr)
|
287
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
288
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
289
|
+
profile = R509::Config::CAProfile.new(:name_constraints => { "excluded" => [ { "type" => "dirName", "value" => [["CN","domain.com"]] }, { "type" => "URI", "value" => ".domain.com" } ] } )
|
290
|
+
config.set_profile("default",profile)
|
291
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
292
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
293
|
+
cert.name_constraints.excluded_names[0].type.should == :directoryName
|
294
|
+
cert.name_constraints.excluded_names[0].value.to_s.should == '/CN=domain.com'
|
295
|
+
cert.name_constraints.excluded_names[1].type.should == :uniformResourceIdentifier
|
296
|
+
cert.name_constraints.excluded_names[1].value.to_s.should == '.domain.com'
|
297
|
+
end
|
298
|
+
it "issues with both constraints" do
|
299
|
+
csr = R509::CSR.new(:csr => @csr)
|
300
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
301
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
302
|
+
profile = R509::Config::CAProfile.new(:name_constraints => { "permitted" => [ { "type" => "DNS", "value" => "domain.com" } ], "excluded" => [ { "type" => "dirName", "value" => [["CN","domain.com"]] } ] } )
|
303
|
+
config.set_profile("default",profile)
|
304
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
305
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
306
|
+
cert.name_constraints.permitted_names[0].type.should == :dNSName
|
307
|
+
cert.name_constraints.permitted_names[0].value.should == 'domain.com'
|
308
|
+
cert.name_constraints.excluded_names[0].type.should == :directoryName
|
309
|
+
cert.name_constraints.excluded_names[0].value.to_s.should == '/CN=domain.com'
|
310
|
+
end
|
311
|
+
end
|
312
|
+
context "authorityInfoAccess" do
|
313
|
+
it "issues a certificate with a ca_issuers_location and ocsp_location" do
|
314
|
+
csr = R509::CSR.new(:csr => @csr)
|
315
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
316
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
317
|
+
config.ca_issuers_location = ['http://domain.com/ca.html']
|
318
|
+
config.ocsp_location = ['http://ocsp.domain.com','http://ocsp.other.com']
|
319
|
+
profile = R509::Config::CAProfile.new
|
320
|
+
config.set_profile("default",profile)
|
321
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
322
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
323
|
+
cert.authority_info_access.ca_issuers.uris.should == ["http://domain.com/ca.html"]
|
324
|
+
cert.authority_info_access.ocsp.uris.should == ["http://ocsp.domain.com","http://ocsp.other.com"]
|
325
|
+
end
|
326
|
+
it "issues a certificate with a ca_issuers_location and ocsp_location (dirName,URI,DNS)" do
|
327
|
+
csr = R509::CSR.new(:csr => @csr)
|
328
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
329
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
330
|
+
config.ca_issuers_location = ['http://domain.com/ca.html','domain.com',R509::Subject.new([['CN','myDir'],['C','US']])]
|
331
|
+
config.ocsp_location = ['http://ocsp.domain.com/','ocsp.domain.com',R509::Subject.new([['CN','ocsp'],['L','Locality']])]
|
332
|
+
profile = R509::Config::CAProfile.new
|
333
|
+
config.set_profile("default",profile)
|
334
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
335
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
336
|
+
cert.authority_info_access.ca_issuers.uris.should == ["http://domain.com/ca.html"]
|
337
|
+
cert.authority_info_access.ca_issuers.dns_names.should == ['domain.com']
|
338
|
+
cert.authority_info_access.ca_issuers.directory_names[0].to_s.should == '/CN=myDir/C=US'
|
339
|
+
cert.authority_info_access.ocsp.uris.should == ["http://ocsp.domain.com/"]
|
340
|
+
cert.authority_info_access.ocsp.dns_names.should == ["ocsp.domain.com"]
|
341
|
+
cert.authority_info_access.ocsp.directory_names[0].to_s.should == '/CN=ocsp/L=Locality'
|
342
|
+
end
|
343
|
+
it "issues a certificate with a ca_issuers_location and no ocsp_location" do
|
344
|
+
csr = R509::CSR.new(:csr => @csr)
|
345
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
346
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
347
|
+
config.ca_issuers_location = ['http://domain.com/ca.html']
|
348
|
+
profile = R509::Config::CAProfile.new
|
349
|
+
config.set_profile("default",profile)
|
350
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
351
|
+
cert = ca.sign(:csr => csr, :profile_name => 'default')
|
352
|
+
cert.authority_info_access.ca_issuers.uris.should == ["http://domain.com/ca.html"]
|
353
|
+
cert.authority_info_access.ocsp.uris.should == []
|
354
|
+
end
|
355
|
+
it "issues a certificate with multiple ca_issuer_locations" do
|
356
|
+
csr = R509::CSR.new(:csr => @csr)
|
357
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
358
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
359
|
+
config.ca_issuers_location = ["http://somelocation.com/c.html","http://other.com/d.html"]
|
360
|
+
profile = R509::Config::CAProfile.new
|
361
|
+
config.set_profile("default",profile)
|
362
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
363
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
364
|
+
cert.authority_info_access.ocsp.uris.should == []
|
365
|
+
cert.authority_info_access.ca_issuers.uris.should == ["http://somelocation.com/c.html","http://other.com/d.html"]
|
366
|
+
end
|
367
|
+
it "issues a certificate with ocsp_location" do
|
368
|
+
csr = R509::CSR.new(:csr => @csr)
|
369
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
370
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
371
|
+
config.ocsp_location = ["http://myocsp.jb.net"]
|
372
|
+
profile = R509::Config::CAProfile.new
|
373
|
+
config.set_profile("default",profile)
|
374
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
375
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
376
|
+
cert.authority_info_access.ca_issuers.uris.should == []
|
377
|
+
cert.authority_info_access.ocsp.uris.should == ["http://myocsp.jb.net"]
|
378
|
+
end
|
379
|
+
it "issues a certificate with an empty array for ocsp_location" do
|
380
|
+
csr = R509::CSR.new(:csr => @csr)
|
381
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
382
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
383
|
+
config.ocsp_location = []
|
384
|
+
profile = R509::Config::CAProfile.new
|
385
|
+
config.set_profile("default",profile)
|
386
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
387
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
388
|
+
cert.authority_info_access.should be_nil
|
389
|
+
end
|
390
|
+
it "issues a certificate with an empty array for ca_issuers_location" do
|
391
|
+
csr = R509::CSR.new(:csr => @csr)
|
392
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
393
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
394
|
+
config.ca_issuers_location = []
|
395
|
+
profile = R509::Config::CAProfile.new
|
396
|
+
config.set_profile("default",profile)
|
397
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
398
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
399
|
+
cert.authority_info_access.should be_nil
|
400
|
+
end
|
401
|
+
end
|
402
|
+
it "issues a certificate with no CDP" do
|
403
|
+
csr = R509::CSR.new(:csr => @csr)
|
404
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
405
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
406
|
+
profile = R509::Config::CAProfile.new
|
407
|
+
config.set_profile("default",profile)
|
408
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
409
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
410
|
+
cert.crl_distribution_points.should == nil
|
411
|
+
end
|
412
|
+
it "issues a certificate with an empty array for CDP" do
|
413
|
+
csr = R509::CSR.new(:csr => @csr)
|
414
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
415
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
416
|
+
config.cdp_location = []
|
417
|
+
profile = R509::Config::CAProfile.new
|
418
|
+
config.set_profile("default",profile)
|
419
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
420
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
421
|
+
cert.crl_distribution_points.should be_nil
|
422
|
+
end
|
423
|
+
it "issues a certificate with a single CDP" do
|
424
|
+
csr = R509::CSR.new(:csr => @csr)
|
425
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
426
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
427
|
+
config.cdp_location = ["http://mycdp.com/x.crl"]
|
428
|
+
profile = R509::Config::CAProfile.new
|
429
|
+
config.set_profile("default",profile)
|
430
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
431
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
432
|
+
cert.crl_distribution_points.crl.uris.should == ["http://mycdp.com/x.crl"]
|
433
|
+
end
|
434
|
+
it "issues a certificate with multiple CDPs" do
|
435
|
+
csr = R509::CSR.new(:csr => @csr)
|
436
|
+
ca_cert = R509::Cert.new( :cert => TestFixtures::TEST_CA_CERT, :key => TestFixtures::TEST_CA_KEY )
|
437
|
+
config = R509::Config::CAConfig.new(:ca_cert => ca_cert)
|
438
|
+
config.cdp_location = ["http://mycdp.com/x.crl","http://anothercrl.com/x.crl"]
|
439
|
+
profile = R509::Config::CAProfile.new
|
440
|
+
config.set_profile("default",profile)
|
441
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
442
|
+
cert = ca.sign( :csr => csr, :profile_name => 'default')
|
443
|
+
cert.crl_distribution_points.crl.uris.should == ["http://mycdp.com/x.crl","http://anothercrl.com/x.crl"]
|
444
|
+
end
|
445
|
+
it "tests basic constraints CA:TRUE and pathlen:0 on a subroot" do
|
446
|
+
csr = R509::CSR.new(:csr => @csr)
|
447
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'subroot')
|
448
|
+
cert.basic_constraints.is_ca?.should == true
|
449
|
+
cert.basic_constraints.path_length.should == 0
|
450
|
+
end
|
451
|
+
it "issues with md5" do
|
452
|
+
csr = R509::CSR.new(:csr => @csr3)
|
453
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'md5')
|
454
|
+
cert.cert.signature_algorithm.should == 'md5WithRSAEncryption'
|
455
|
+
end
|
456
|
+
it "issues with sha1" do
|
457
|
+
csr = R509::CSR.new(:csr => @csr3)
|
458
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha1')
|
459
|
+
cert.cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
460
|
+
end
|
461
|
+
it "issues with sha224" do
|
462
|
+
csr = R509::CSR.new(:csr => @csr3)
|
463
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha224')
|
464
|
+
cert.cert.signature_algorithm.should == 'sha224WithRSAEncryption'
|
465
|
+
end
|
466
|
+
it "issues with sha256" do
|
467
|
+
csr = R509::CSR.new(:csr => @csr3)
|
468
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha256')
|
469
|
+
cert.cert.signature_algorithm.should == 'sha256WithRSAEncryption'
|
470
|
+
end
|
471
|
+
it "issues with sha384" do
|
472
|
+
csr = R509::CSR.new(:csr => @csr3)
|
473
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha384')
|
474
|
+
cert.cert.signature_algorithm.should == 'sha384WithRSAEncryption'
|
475
|
+
end
|
476
|
+
it "issues with sha512" do
|
477
|
+
csr = R509::CSR.new(:csr => @csr3)
|
478
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'sha512')
|
479
|
+
cert.cert.signature_algorithm.should == 'sha512WithRSAEncryption'
|
480
|
+
end
|
481
|
+
it "issues with invalid hash (sha1 fallback)" do
|
482
|
+
csr = R509::CSR.new(:csr => @csr3)
|
483
|
+
cert = @ca.sign(:csr => csr, :profile_name => 'server', :message_digest => 'invalid')
|
484
|
+
cert.cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
485
|
+
end
|
486
|
+
it "generates random serial when serial is not specified and uses microtime as part of the serial to prevent collision" do
|
487
|
+
now = Time.now
|
488
|
+
Time.stub!(:now).and_return(now)
|
489
|
+
time = now.to_i.to_s
|
490
|
+
csr = R509::CSR.new(:csr => @csr3)
|
491
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server")
|
492
|
+
cert.serial.to_s.size.should >= 45
|
493
|
+
cert.serial.to_s.index(time).should_not be_nil
|
494
|
+
end
|
495
|
+
it "accepts specified serial number" do
|
496
|
+
csr = R509::CSR.new(:csr => @csr3)
|
497
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server", :serial => 12345)
|
498
|
+
cert.serial.should == 12345
|
499
|
+
end
|
500
|
+
it "has default notBefore/notAfter dates" do
|
501
|
+
not_before = (Time.now - (6 * 60 * 60)).utc
|
502
|
+
not_after = (Time.now - (6 * 60 * 60) + (365 * 24 * 60 * 60)).utc
|
503
|
+
csr = R509::CSR.new(:csr => @csr3)
|
504
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server")
|
505
|
+
cert.cert.not_before.year.should == not_before.year
|
506
|
+
cert.cert.not_before.month.should == not_before.month
|
507
|
+
cert.cert.not_before.day.should == not_before.day
|
508
|
+
cert.cert.not_before.hour.should == not_before.hour
|
509
|
+
cert.cert.not_before.min.should == not_before.min
|
510
|
+
cert.cert.not_after.year.should == not_after.year
|
511
|
+
cert.cert.not_after.month.should == not_after.month
|
512
|
+
cert.cert.not_after.day.should == not_after.day
|
513
|
+
cert.cert.not_after.hour.should == not_after.hour
|
514
|
+
cert.cert.not_after.min.should == not_after.min
|
515
|
+
end
|
516
|
+
it "allows you to specify notBefore/notAfter dates" do
|
517
|
+
not_before = Time.now - 5 * 60 * 60
|
518
|
+
not_after = Time.now + 5 * 60 * 60
|
519
|
+
csr = R509::CSR.new(:csr => @csr3)
|
520
|
+
cert = @ca.sign(:csr => csr, :profile_name => "server", :not_before => not_before, :not_after => not_after)
|
521
|
+
cert.cert.not_before.ctime.should == not_before.utc.ctime
|
522
|
+
cert.cert.not_after.ctime.should == not_after.utc.ctime
|
523
|
+
end
|
524
|
+
it "issues a certificate from a root that does not have a subjectKeyIdentifier" do
|
525
|
+
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"})
|
526
|
+
ca = R509::CertificateAuthority::Signer.new(config)
|
527
|
+
csr = R509::CSR.new(:csr => @csr3)
|
528
|
+
cert = ca.sign(:csr => csr, :profile_name => "server")
|
529
|
+
cert.authority_key_identifier.should == nil
|
530
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
531
|
+
end
|
532
|
+
it "raises error unless you provide a proper config (or nil)" do
|
533
|
+
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)')
|
534
|
+
end
|
535
|
+
it "raises error when providing invalid ca profile" do
|
536
|
+
csr = R509::CSR.new(:csr => @csr)
|
537
|
+
expect { @ca.sign(:csr => csr, :profile_name => 'invalid') }.to raise_error(R509::R509Error, "unknown profile 'invalid'")
|
538
|
+
end
|
539
|
+
it "raises error when attempting to issue CSR with invalid signature" do
|
540
|
+
csr = R509::CSR.new(:csr => @csr_invalid_signature)
|
541
|
+
expect { @ca.sign(:csr => csr, :profile_name => 'server') }.to raise_error(R509::R509Error, 'Certificate request signature is invalid.')
|
542
|
+
end
|
543
|
+
it "raises error when passing non-hash to selfsign method" do
|
544
|
+
expect { @ca.selfsign(@csr) }.to raise_error(ArgumentError, "You must pass a hash of options consisting of at minimum :csr")
|
545
|
+
end
|
546
|
+
it "raises error when passing invalid data for san_names" do
|
547
|
+
csr = R509::CSR.new(
|
548
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
549
|
+
:bit_strength => 1024
|
550
|
+
)
|
551
|
+
san_names = "invalid"
|
552
|
+
expect { @ca.selfsign(:csr => csr, :san_names => san_names) }.to raise_error(ArgumentError,'When passing SAN names it must be provided as either an array of strings or an R509::ASN1::GeneralNames object')
|
553
|
+
end
|
554
|
+
it "issues a self-signed certificate with custom fields" do
|
555
|
+
not_before = Time.now.to_i
|
556
|
+
not_after = Time.now.to_i+3600*24*7300
|
557
|
+
csr = R509::CSR.new(
|
558
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
559
|
+
:bit_strength => 1024
|
560
|
+
)
|
561
|
+
san_names = R509::ASN1.general_name_parser(['sanname1','sanname2'])
|
562
|
+
cert = @ca.selfsign(
|
563
|
+
:csr => csr,
|
564
|
+
:serial => 3,
|
565
|
+
:not_before => not_before,
|
566
|
+
:not_after => not_after,
|
567
|
+
:message_digest => 'sha256',
|
568
|
+
:san_names => san_names
|
569
|
+
)
|
570
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
571
|
+
cert.signature_algorithm.should == 'sha256WithRSAEncryption'
|
572
|
+
cert.serial.should == 3
|
573
|
+
cert.not_before.to_i.should == not_before
|
574
|
+
cert.not_after.to_i.should == not_after
|
575
|
+
cert.subject.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
576
|
+
cert.issuer.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
577
|
+
cert.basic_constraints.is_ca?.should == true
|
578
|
+
cert.san.dns_names.should include('sanname1','sanname2')
|
579
|
+
end
|
580
|
+
it "issues a self-signed certificate with san names provided as an array" do
|
581
|
+
not_before = Time.now.to_i
|
582
|
+
not_after = Time.now.to_i+3600*24*7300
|
583
|
+
csr = R509::CSR.new(
|
584
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
585
|
+
:bit_strength => 1024
|
586
|
+
)
|
587
|
+
san_names = ['sanname1','sanname2']
|
588
|
+
cert = @ca.selfsign(
|
589
|
+
:csr => csr,
|
590
|
+
:not_before => not_before,
|
591
|
+
:not_after => not_after,
|
592
|
+
:message_digest => 'sha256',
|
593
|
+
:san_names => san_names
|
594
|
+
)
|
595
|
+
cert.san.dns_names.should include('sanname1','sanname2')
|
596
|
+
end
|
597
|
+
it "issues self-signed certificate with SAN in CSR" do
|
598
|
+
csr = R509::CSR.new(
|
599
|
+
:subject => [['CN','My Self Sign']],
|
600
|
+
:san_names => ['sanname1','sanname2'],
|
601
|
+
:bit_strength => 1024
|
602
|
+
)
|
603
|
+
cert = @ca.selfsign(
|
604
|
+
:csr => csr
|
605
|
+
)
|
606
|
+
cert.san.dns_names.should include('sanname1','sanname2')
|
607
|
+
cert.subject.to_s.should == '/CN=My Self Sign'
|
608
|
+
cert.issuer.to_s.should == '/CN=My Self Sign'
|
609
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
610
|
+
end
|
611
|
+
it "issues a self-signed certificate with defaults" do
|
612
|
+
csr = R509::CSR.new(
|
613
|
+
:subject => [['C','US'],['O','r509 LLC'],['CN','r509 Self-Signed CA Test']],
|
614
|
+
:bit_strength => 1024
|
615
|
+
)
|
616
|
+
cert = @ca.selfsign(
|
617
|
+
:csr => csr
|
618
|
+
)
|
619
|
+
cert.public_key.to_s.should == csr.public_key.to_s
|
620
|
+
cert.signature_algorithm.should == 'sha1WithRSAEncryption'
|
621
|
+
(cert.not_after.to_i-cert.not_before.to_i).should == 31536000
|
622
|
+
cert.subject.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
623
|
+
cert.issuer.to_s.should == '/C=US/O=r509 LLC/CN=r509 Self-Signed CA Test'
|
624
|
+
cert.basic_constraints.is_ca?.should == true
|
625
|
+
end
|
626
|
+
it "raises an error if attempting to self-sign without a key" do
|
627
|
+
csr = R509::CSR.new(:csr => @csr3)
|
628
|
+
expect { @ca.selfsign( :csr => csr ) }.to raise_error(ArgumentError, "CSR must also have a private key to self sign")
|
629
|
+
end
|
630
|
+
it "raises an error if you call sign without passing a config to the object" do
|
631
|
+
ca_signer = R509::CertificateAuthority::Signer.new
|
632
|
+
csr = R509::CSR.new(:csr => @csr3)
|
633
|
+
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")
|
634
|
+
end
|
635
|
+
|
636
|
+
context "issuing off an elliptic curve CA", :ec => true do
|
637
|
+
before :all do
|
638
|
+
@test_ca_ec = R509::Config::CAConfig.from_yaml("test_ca_ec", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_ec.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
639
|
+
@ca_ec = R509::CertificateAuthority::Signer.new(@test_ca_ec)
|
36
640
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
641
|
+
|
642
|
+
it "properly issues server cert" do
|
643
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :type => :ec)
|
644
|
+
cert = @ca_ec.sign( :csr => csr, :profile_name => 'server' )
|
645
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
646
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/L=Chicago/O=Paul Kehrer/CN=langui.sh'
|
647
|
+
cert.signature_algorithm.should == 'ecdsa-with-SHA384'
|
648
|
+
cert.key_algorithm.should == :ec
|
649
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
43
650
|
end
|
44
651
|
it "properly issues server cert using spki" do
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
652
|
+
spki = R509::SPKI.new(:spki => @spki)
|
653
|
+
cert = @ca_ec.sign( :spki => spki, :profile_name => 'server', :subject=>[['CN','test.local']] )
|
654
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
655
|
+
cert.subject.to_s.should == '/CN=test.local'
|
656
|
+
cert.signature_algorithm.should == 'ecdsa-with-SHA384'
|
657
|
+
cert.key_algorithm.should == :rsa #weird right?! it's because the spki is RSA even though the signature is from an EC root
|
658
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
context "issuing off a DSA CA" do
|
663
|
+
before :all do
|
664
|
+
@test_ca_dsa = R509::Config::CAConfig.from_yaml("test_ca_dsa", File.read("#{File.dirname(__FILE__)}/fixtures/config_test_dsa.yaml"), {:ca_root_path => "#{File.dirname(__FILE__)}/fixtures"})
|
665
|
+
@ca_dsa = R509::CertificateAuthority::Signer.new(@test_ca_dsa)
|
51
666
|
end
|
667
|
+
|
52
668
|
it "properly issues server cert" do
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
669
|
+
csr = R509::CSR.new(:subject => [['C','US'],['ST','Illinois'],['L','Chicago'],['O','Paul Kehrer'],['CN','langui.sh']], :type => :dsa, :bit_strength => 1024)
|
670
|
+
cert = @ca_dsa.sign( :csr => csr, :profile_name => 'server' )
|
671
|
+
cert.to_pem.should match(/BEGIN CERTIFICATE/)
|
672
|
+
cert.subject.to_s.should == '/C=US/ST=Illinois/L=Chicago/O=Paul Kehrer/CN=langui.sh'
|
673
|
+
cert.signature_algorithm.should == 'dsaWithSHA1'
|
674
|
+
cert.key_algorithm.should == :dsa
|
675
|
+
cert.extended_key_usage.web_server_authentication?.should == true
|
676
|
+
end
|
677
|
+
end
|
260
678
|
end
|