spec/cert_spec.rb in r509-0.8.1 vs spec/cert_spec.rb in r509-0.9
- old
+ new
@@ -1,321 +1,396 @@
require 'spec_helper'
describe R509::Cert do
- before :all do
- @cert = TestFixtures::CERT
- @cert_public_key_modulus = TestFixtures::CERT_PUBLIC_KEY_MODULUS
- @cert3 = TestFixtures::CERT3
- @cert_der = TestFixtures::CERT_DER
- @cert_san = TestFixtures::CERT_SAN
- @cert_san2 = TestFixtures::CERT_SAN2
- @key3 = TestFixtures::KEY3
- @cert3_p12 = TestFixtures::CERT3_P12
- @cert4 = TestFixtures::CERT4
- @key3_encrypted = TestFixtures::KEY3_ENCRYPTED
- @cert5 = TestFixtures::CERT5
- @cert6 = TestFixtures::CERT6
- @test_ca_cert = TestFixtures::TEST_CA_CERT
- @cert_expired = TestFixtures::CERT_EXPIRED
- @cert_not_yet_valid = TestFixtures::CERT_NOT_YET_VALID
+ before :all do
+ @cert = TestFixtures::CERT
+ @cert_public_key_modulus = TestFixtures::CERT_PUBLIC_KEY_MODULUS
+ @cert3 = TestFixtures::CERT3
+ @cert_ocsp_no_check = TestFixtures::CERT_OCSP_NO_CHECK
+ @cert_der = TestFixtures::CERT_DER
+ @cert_san = TestFixtures::CERT_SAN
+ @cert_san2 = TestFixtures::CERT_SAN2
+ @key3 = TestFixtures::KEY3
+ @cert3_p12 = TestFixtures::CERT3_P12
+ @cert4 = TestFixtures::CERT4
+ @key3_encrypted = TestFixtures::KEY3_ENCRYPTED
+ @cert5 = TestFixtures::CERT5
+ @cert6 = TestFixtures::CERT6
+ @test_ca_cert = TestFixtures::TEST_CA_CERT
+ @cert_expired = TestFixtures::CERT_EXPIRED
+ @cert_not_yet_valid = TestFixtures::CERT_NOT_YET_VALID
+ @cert_inhibit = TestFixtures::CERT_INHIBIT
+ @cert_policy_constraints = TestFixtures::CERT_POLICY_CONSTRAINTS
+ @cert_name_constraints = TestFixtures::CERT_NAME_CONSTRAINTS
+ end
+ it "raises error when no hash supplied" do
+ expect { R509::Cert.new('no hash')}.to raise_error(ArgumentError, 'Must provide a hash of options')
+ end
+ it "raises error when no :cert supplied" do
+ expect { R509::Cert.new(:key => "random")}.to raise_error(ArgumentError, 'Must provide :cert or :pkcs12')
+ end
+ it "raises error when a csr is supplied to :cert" do
+ expect { R509::Cert.new(:cert => TestFixtures::CSR)}.to raise_error(ArgumentError, "Cert provided is actually a certificate signing request.")
+ end
+ it "raises error when :cert and :pkcs12 are both provided" do
+ expect { R509::Cert.new(
+ :key => @key3,
+ :pkcs12 => @cert3_p12,
+ :password => 'whatever'
+ ) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
+ end
+ it "raises error when :key and :pkcs12 are both provided" do
+ expect { R509::Cert.new(
+ :cert => @cert,
+ :pkcs12 => @cert3_p12,
+ :password => 'whatever'
+ ) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
+ end
+ it "has a public_key" do
+ cert = R509::Cert.new(:cert => @cert)
+ #this is more complex than it should have to be. diff versions of openssl
+ #return subtly diff PEM encodings so we need to look at the modulus (n)
+ #but beware, because n is not present for DSA certificates
+ cert.public_key.n.to_i.should == @cert_public_key_modulus.to_i
+ end
+ it "returns bit strength" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.bit_strength.should == 2048
+ end
+ it "has the right issuer" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.issuer.to_s.should == "/C=US/O=SecureTrust Corporation/CN=SecureTrust CA"
+ end
+ it "generates certificate fingerprints" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.fingerprint.should == '863bbb58877b426eb10ccfd34d3056b8c961f627'
+ cert.fingerprint('sha256').should == '65d624f5a6937c3005d78b3f4ff09164649dd5aeb3fd8a93d6fd420e8b587fa2'
+ cert.fingerprint('sha512').should == 'a07d87f04161f52ef671c9d616530d07ebadef9c93c0470091617363c9ce8618dcb7931414e599d25cb032d68597111719e76d7de4bb7a92bf5ca7c08c36cf12'
+ cert.fingerprint('md5').should == 'aa78501c41b19252dfbe8ba509cc21f4'
+ end
+ it "returns true from has_private_key? when a key is present" do
+ cert = R509::Cert.new(:cert => @cert3, :key => @key3)
+ cert.has_private_key?.should == true
+ end
+ it "returns false from has_private_key? when a key is not present" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.has_private_key?.should == false
+ end
+ it "loads encrypted private key with cert" do
+ expect { R509::Cert.new(:cert => @cert3, :key => @key3_encrypted, :password => "r509") }.to_not raise_error
+ end
+ it "loads pkcs12" do
+ cert = R509::Cert.new(:pkcs12 => @cert3_p12, :password => "r509")
+ cert.has_private_key?.should == true
+ cert.subject.to_s.should == '/CN=futurama.com/O=Farnsworth Enterprises'
+ end
+ it "has the right not_before" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.not_before.to_i.should == 1282659002
+ end
+ it "has the right not_after" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.not_after.to_i.should == 1377267002
+ end
+ it "returns signature algorithm" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.signature_algorithm.should == 'sha1WithRSAEncryption'
+ end
+ it "returns the RSA key algorithm" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.key_algorithm.should == :rsa
+ end
+ it "returns the DSA key algorithm" do
+ cert = R509::Cert.new(:cert => @cert6)
+ cert.key_algorithm.should == :dsa
+ end
+ it "returns list of san names when it is a san cert" do
+ cert = R509::Cert.new(:cert => @cert_san)
+ cert.san.dns_names.should == ['langui.sh']
+ end
+ it "#san returns nil when it is not a san cert" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.san.should be_nil
+ end
+ it "#all_names should return a list of san names in addition to the CN" do
+ cert = R509::Cert.new(:cert => @cert_san2)
+ cert.all_names.should == ["cn.langui.sh", "san1.langui.sh",
+ "san2.langui.sh", "san3.langui.sh"]
+ end
+ it "#all_names should not have duplicates" do
+ cert = R509::Cert.new(:cert => @cert_san)
+ cert.all_names.should == ["langui.sh"]
+ end
+ it "#all_names should return the CN in the array even if there are no SANs" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.all_names.should == ["langui.sh"]
+ end
+ it "raises exception when providing invalid cert" do
+ expect { R509::Cert.new(:cert => "invalid cert") }.to raise_error(OpenSSL::X509::CertificateError)
+ end
+ it "raises exception when providing invalid key" do
+ expect { R509::Cert.new(:cert => @cert, :key => 'invalid key') }.to raise_error(R509::R509Error, 'Failed to load private key. Invalid key or incorrect password.')
+ end
+ it "raises exception on non-matching key" do
+ expect { R509::Cert.new(:cert => @cert, :key => @key3) }.to raise_error(R509::R509Error, 'Key does not match cert.')
+ end
+ it "return normal object on matching key/cert pair" do
+ expect { R509::Cert.new(:cert => @cert3, :key => @key3) }.to_not raise_error
+ end
+ it "loads properly when an R509::PrivateKey is provided" do
+ key = R509::PrivateKey.new(:key => @key3)
+ expect { R509::Cert.new(:key => key, :cert => @cert3)}.to_not raise_error
+ end
+ it "writes to pem" do
+ cert = R509::Cert.new(:cert => @cert)
+ sio = StringIO.new
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
+ cert.write_pem(sio)
+ sio.string.should == @cert + "\n"
+ end
+ it "writes to der" do
+ cert = R509::Cert.new(:cert => @cert)
+ sio = StringIO.new
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
+ cert.write_der(sio)
+ sio.string.should == @cert_der
+ end
+ it "writes to pkcs12 when key/cert are present" do
+ cert = R509::Cert.new(:cert => @cert3, :key => @key3)
+ sio = StringIO.new
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
+ cert.write_pkcs12(sio,'r509_password')
+ expect { R509::Cert.new(:pkcs12 => sio.string, :password => 'r509_password') }.to_not raise_error
+ end
+ it "raises error when writing to pkcs12 if key is not present" do
+ cert = R509::Cert.new(:cert => @cert3)
+ expect { cert.write_pkcs12('/dev/null','password') }.to raise_error(R509::R509Error, "Writing a PKCS12 requires both key and cert")
+ end
+ it "parses san extension" do
+ cert = R509::Cert.new(:cert => @cert_san)
+ cert.san.dns_names.should == ["langui.sh"]
+ end
+ context "when initialized with an OpenSSL::X509::Certificate" do
+ it "returns pem on to_pem" do
+ test_cert = OpenSSL::X509::Certificate.new(@cert)
+ cert = R509::Cert.new(:cert => test_cert)
+ cert.to_pem.should == @cert
end
- it "raises error when no hash supplied" do
- expect { R509::Cert.new('no hash')}.to raise_error(ArgumentError, 'Must provide a hash of options')
+ it "returns der on to_der" do
+ test_cert = OpenSSL::X509::Certificate.new(@cert)
+ cert = R509::Cert.new(:cert => test_cert)
+ cert.to_der.should == @cert_der
end
- it "raises error when no :cert supplied" do
- expect { R509::Cert.new(:key => "random")}.to raise_error(ArgumentError, 'Must provide :cert or :pkcs12')
+ it "returns pem on to_s" do
+ test_cert = OpenSSL::X509::Certificate.new(@cert)
+ cert = R509::Cert.new(:cert => test_cert)
+ cert.to_s.should == @cert
end
- it "raises error when a csr is supplied to :cert" do
- expect { R509::Cert.new(:cert => TestFixtures::CSR)}.to raise_error(R509::R509Error, "Cert provided is actually a certificate signing request.")
+ end
+ context "when initialized with a pem" do
+ it "returns on to_pem" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.to_pem.should == @cert
end
- it "raises error when :cert and :pkcs12 are both provided" do
- expect { R509::Cert.new(
- :key => @key3,
- :pkcs12 => @cert3_p12,
- :password => 'whatever'
- ) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
+ it "returns der on to_der" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.to_der.should == @cert_der
end
- it "raises error when :key and :pkcs12 are both provided" do
- expect { R509::Cert.new(
- :cert => @cert,
- :pkcs12 => @cert3_p12,
- :password => 'whatever'
- ) }.to raise_error(ArgumentError, 'When providing pkcs12, do not pass cert or key')
- end
- it "has a public_key" do
- cert = R509::Cert.new(:cert => @cert)
- #this is more complex than it should have to be. diff versions of openssl
- #return subtly diff PEM encodings so we need to look at the modulus (n)
- #but beware, because n is not present for DSA certificates
- cert.public_key.n.to_i.should == @cert_public_key_modulus.to_i
- end
- it "returns bit strength" do
- cert = R509::Cert.new(:cert => @cert)
- cert.bit_strength.should == 2048
- end
- it "has the right issuer" do
- cert = R509::Cert.new(:cert => @cert)
- cert.issuer.to_s.should == "/C=US/O=SecureTrust Corporation/CN=SecureTrust CA"
- end
- it "has the right issuer CN" do
- cert = R509::Cert.new(:cert => @cert)
- cert.issuer_cn.to_s.should == "SecureTrust CA"
- end
- it "generates certificate fingerprints" do
- cert = R509::Cert.new(:cert => @cert)
- cert.fingerprint.should == '863bbb58877b426eb10ccfd34d3056b8c961f627'
- cert.fingerprint('sha256').should == '65d624f5a6937c3005d78b3f4ff09164649dd5aeb3fd8a93d6fd420e8b587fa2'
- cert.fingerprint('sha512').should == 'a07d87f04161f52ef671c9d616530d07ebadef9c93c0470091617363c9ce8618dcb7931414e599d25cb032d68597111719e76d7de4bb7a92bf5ca7c08c36cf12'
- cert.fingerprint('md5').should == 'aa78501c41b19252dfbe8ba509cc21f4'
- end
- it "returns true from has_private_key? when a key is present" do
- cert = R509::Cert.new(:cert => @cert3, :key => @key3)
- cert.has_private_key?.should == true
- end
- it "returns false from has_private_key? when a key is not present" do
- cert = R509::Cert.new(:cert => @cert)
- cert.has_private_key?.should == false
- end
- it "loads encrypted private key with cert" do
- expect { R509::Cert.new(:cert => @cert3, :key => @key3_encrypted, :password => "r509") }.to_not raise_error
- end
- it "loads pkcs12" do
- cert = R509::Cert.new(:pkcs12 => @cert3_p12, :password => "r509")
- cert.has_private_key?.should == true
- cert.subject.to_s.should == '/CN=futurama.com/O=Farnsworth Enterprises'
- end
- it "has the right not_before" do
- cert = R509::Cert.new(:cert => @cert)
- cert.not_before.to_i.should == 1282659002
- end
- it "has the right not_after" do
- cert = R509::Cert.new(:cert => @cert)
- cert.not_after.to_i.should == 1377267002
- end
- it "fetches a subject component" do
- cert = R509::Cert.new(:cert => @cert)
- cert.subject_component('CN').should == 'langui.sh'
- end
- it "fetches a subject component for mixed-case components" do
- cert4 = R509::Cert.new(:cert => @cert4)
- cert4.subject_component('emailAddress').should == 'support@polycom.com'
+ it "returns pem on to_s" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.to_s.should == @cert
+ end
+ end
+ it "gets the right object from #basic_constraints" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.basic_constraints.class.should == R509::Cert::Extensions::BasicConstraints
+ end
+ it "gets the right object from #key_usage" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.key_usage.class.should == R509::Cert::Extensions::KeyUsage
+ end
+ it "gets the right object from #key_usage" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.extended_key_usage.class.should == R509::Cert::Extensions::ExtendedKeyUsage
+ end
+ it "gets the right object from #subject_key_identifier" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.subject_key_identifier.class.should == R509::Cert::Extensions::SubjectKeyIdentifier
+ end
+ it "gets the right object from #authority_key_identifier" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.authority_key_identifier.class.should == R509::Cert::Extensions::AuthorityKeyIdentifier
+ end
+ it "gets the right object from #subject_alternative_name" do
+ cert = R509::Cert.new(:cert => @cert5)
+ cert.subject_alternative_name.class.should == R509::Cert::Extensions::SubjectAlternativeName
+ end
+ it "gets the right object from #authority_info_access" do
+ cert = R509::Cert.new(:cert => @cert5)
+ cert.authority_info_access.class.should == R509::Cert::Extensions::AuthorityInfoAccess
+ end
+ it "gets the right object from #crl_distribution_points" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.crl_distribution_points.class.should == R509::Cert::Extensions::CRLDistributionPoints
+ end
+ it "gets the right object from #certificate_policies" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.certificate_policies.class.should == R509::Cert::Extensions::CertificatePolicies
+ end
+ it "gets the right object from #inhibit_any_policy" do
+ cert = R509::Cert.new(:cert => @cert_inhibit)
+ cert.inhibit_any_policy.class.should == R509::Cert::Extensions::InhibitAnyPolicy
+ end
+ it "gets the right object from #policy_constraints" do
+ cert = R509::Cert.new(:cert => @cert_policy_constraints)
+ cert.policy_constraints.class.should == R509::Cert::Extensions::PolicyConstraints
+ end
+ it "gets the right object from #name_constraints" do
+ cert = R509::Cert.new(:cert => @cert_name_constraints)
+ cert.name_constraints.class.should == R509::Cert::Extensions::NameConstraints
+ end
+ it "returns true from #ocsp_no_check? when the extension is present" do
+ cert = R509::Cert.new(:cert => @cert_ocsp_no_check)
+ cert.ocsp_no_check?.should == true
+ end
+ it "returns false from #ocsp_no_check? when the extension is not present" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.ocsp_no_check?.should == false
+ end
- cert6 = R509::Cert.new(:cert => @cert6)
- cert6.subject_component('serialNumber').should == 'a/3ILmX9qynk8f3WafoTTkKgWj0LAGRL'
+ it "checks rsa?" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.rsa?.should == true
+ cert.ec?.should == false
+ cert.dsa?.should == false
+ end
+ it "gets RSA bit strength" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.bit_strength.should == 2048
+ end
+ it "returns an error for curve_name for DSA/RSA" do
+ cert = R509::Cert.new(:cert => @cert)
+ expect { cert.curve_name }.to raise_error(R509::R509Error, 'Curve name is only available with EC certs')
+ end
+ it "checks dsa?" do
+ cert = R509::Cert.new(:cert => @cert6)
+ cert.rsa?.should == false
+ cert.ec?.should == false
+ cert.dsa?.should == true
+ end
+ it "gets DSA bit strength" do
+ cert = R509::Cert.new(:cert => @cert6)
+ cert.bit_strength.should == 1024
+ end
+ it "gets serial of cert" do
+ cert = R509::Cert.new(:cert => @cert6)
+ cert.serial.should == 951504
+ end
+ it "gets hexserial of cert" do
+ cert = R509::Cert.new(:cert => @cert6)
+ cert.hexserial.should == "0E84D0"
+ end
+ it "checks a cert that is not yet valid" do
+ cert = R509::Cert.new(:cert => @cert_not_yet_valid)
+ cert.valid?.should == false
+ end
+ it "checks a cert that is in validity range" do
+ cert = R509::Cert.new(:cert => @test_ca_cert)
+ cert.valid?.should == true
+ end
+ it "checks a cert that is expired" do
+ cert = R509::Cert.new(:cert => @cert_expired)
+ cert.valid?.should == false
+ end
+ it "checks expired_at?" do
+ cert = R509::Cert.new(:cert => @cert_expired)
+ cert.valid_at?(Time.utc(2009,1,1)).should == false
+ cert.valid_at?(Time.utc(2011,3,1)).should == true
+ cert.valid_at?(1298959200).should == true
+ cert.valid_at?(Time.utc(2012,1,1)).should == false
+ end
+ it "is revoked by crl" do
+ cert = R509::Cert.new(:cert => @cert3)
+ crl_admin = R509::CRL::Administrator.new(TestFixtures.test_ca_config)
+ crl_admin.revoke_cert(1425751142578902223005775172931960716533532010870)
+ cert.is_revoked_by_crl?(crl_admin.crl).should == true
+ end
+ it "is not revoked by crl" do
+ cert = R509::Cert.new(:cert => @cert3)
+ crl_admin = R509::CRL::Administrator.new(TestFixtures.test_ca_config)
+ cert.is_revoked_by_crl?(crl_admin.crl).should == false
+ end
+ it "loads a cert with load_from_file" do
+ path = File.dirname(__FILE__) + '/fixtures/cert1.pem'
+ cert = R509::Cert.load_from_file path
+ cert.serial.to_i.should == 211653423715
+ end
+ it "returns a hash for #extensions" do
+ cert = R509::Cert.new(:cert => @cert3)
+ cert.extensions.kind_of?(Hash).should == true
+ end
+ it "returns an array for #unknown_extensions" do
+ cert = R509::Cert.new(:cert => @cert3)
+ cert.unknown_extensions.should == []
+ end
+
+ context "elliptic curve certs", :ec => true do
+ before :all do
+ @cert_ec = TestFixtures::EC_EE_CERT
+ @key_ec = TestFixtures::EC_EE_KEY
end
- it "returns nil when subject component not found" do
- cert = R509::Cert.new(:cert => @cert)
- cert.subject_component('OU').should be_nil
+ it "loads a cert" do
+ expect { R509::Cert.new(:cert => @cert_ec) }.to_not raise_error
end
- it "returns signature algorithm" do
- cert = R509::Cert.new(:cert => @cert)
- cert.signature_algorithm.should == 'sha1WithRSAEncryption'
- end
- it "returns the RSA key algorithm" do
- cert = R509::Cert.new(:cert => @cert)
- cert.key_algorithm.should == 'RSA'
- end
- it "returns the DSA key algorithm" do
- cert = R509::Cert.new(:cert => @cert6)
- cert.key_algorithm.should == 'DSA'
- end
- it "returns list of san_names when it is a san cert" do
- cert = R509::Cert.new(:cert => @cert_san)
- cert.san_names.should == ['langui.sh']
- end
- it "returns an empty list when it is not a san cert" do
- cert = R509::Cert.new(:cert => @cert)
- cert.san_names.should == []
- end
- it "#subject_names should return a list of san_names in addition to the CN" do
- cert = R509::Cert.new(:cert => @cert_san2)
- cert.subject_names.should == ["cn.langui.sh", "san1.langui.sh",
- "san2.langui.sh", "san3.langui.sh"]
- end
- it "#subject_names should not have duplicates" do
- cert = R509::Cert.new(:cert => @cert_san)
- cert.subject_names.should == ["langui.sh"]
- end
- it "#subject_names should return the CN in the array, if there are no SANs" do
- cert = R509::Cert.new(:cert => @cert)
- cert.subject_names.should == ["langui.sh"]
- end
- it "raises exception when providing invalid cert" do
- expect { R509::Cert.new(:cert => "invalid cert") }.to raise_error(OpenSSL::X509::CertificateError)
- end
- it "raises exception when providing invalid key" do
- expect { R509::Cert.new(:cert => @cert, :key => 'invalid key') }.to raise_error(R509::R509Error, 'Failed to load private key. Invalid key or incorrect password.')
- end
- it "raises exception on non-matching key" do
- expect { R509::Cert.new(:cert => @cert, :key => @key3) }.to raise_error(R509::R509Error, 'Key does not match cert.')
- end
- it "return normal object on matching key/cert pair" do
- expect { R509::Cert.new(:cert => @cert3, :key => @key3) }.to_not raise_error
- end
- it "loads properly when an R509::PrivateKey is provided" do
- key = R509::PrivateKey.new(:key => @key3)
- expect { R509::Cert.new(:key => key, :cert => @cert3)}.to_not raise_error
- end
- it "writes to pem" do
- cert = R509::Cert.new(:cert => @cert)
- sio = StringIO.new
- sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
- cert.write_pem(sio)
- sio.string.should == @cert + "\n"
- end
- it "writes to der" do
- cert = R509::Cert.new(:cert => @cert)
- sio = StringIO.new
- sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
- cert.write_der(sio)
- sio.string.should == @cert_der
- end
it "writes to pkcs12 when key/cert are present" do
- cert = R509::Cert.new(:cert => @cert3, :key => @key3)
- sio = StringIO.new
- sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
- cert.write_pkcs12(sio,'r509_password')
- expect { R509::Cert.new(:pkcs12 => sio.string, :password => 'r509_password') }.to_not raise_error
+ cert = R509::Cert.new(:cert => @cert_ec, :key => @key_ec)
+ sio = StringIO.new
+ sio.set_encoding("BINARY") if sio.respond_to?(:set_encoding)
+ cert.write_pkcs12(sio,'r509_password')
+ expect { R509::Cert.new(:pkcs12 => sio.string, :password => 'r509_password') }.to_not raise_error
end
- it "raises error when writing to pkcs12 if key is not present" do
- cert = R509::Cert.new(:cert => @cert3)
- expect { cert.write_pkcs12('/dev/null','password') }.to raise_error(R509::R509Error, "Writing a PKCS12 requires both key and cert")
+ it "raises error on bit strength" do
+ cert = R509::Cert.new(:cert => @cert_ec)
+ expect { cert.bit_strength }.to raise_error(R509::R509Error,'Bit strength is not available for EC at this time.')
end
- it "parses san extension" do
- cert = R509::Cert.new(:cert => @cert_san)
- cert.san_names.should == ["langui.sh"]
+ it "returns curve name" do
+ cert = R509::Cert.new(:cert => @cert_ec)
+ cert.curve_name.should == 'secp384r1'
end
- context "when initialized with an OpenSSL::X509::Certificate" do
- it "returns pem on to_pem" do
- test_cert = OpenSSL::X509::Certificate.new(@cert)
- cert = R509::Cert.new(:cert => test_cert)
- cert.to_pem.should == @cert
- end
- it "returns der on to_der" do
- test_cert = OpenSSL::X509::Certificate.new(@cert)
- cert = R509::Cert.new(:cert => test_cert)
- cert.to_der.should == @cert_der
- end
- it "returns pem on to_s" do
- test_cert = OpenSSL::X509::Certificate.new(@cert)
- cert = R509::Cert.new(:cert => test_cert)
- cert.to_s.should == @cert
- end
+ it "checks ec?" do
+ cert = R509::Cert.new(:cert => @cert_ec)
+ cert.rsa?.should == false
+ cert.dsa?.should == false
+ cert.ec?.should == true
end
- context "when initialized with a pem" do
- it "returns on to_pem" do
- cert = R509::Cert.new(:cert => @cert)
- cert.to_pem.should == @cert
- end
- it "returns der on to_der" do
- cert = R509::Cert.new(:cert => @cert)
- cert.to_der.should == @cert_der
- end
- it "returns pem on to_s" do
- cert = R509::Cert.new(:cert => @cert)
- cert.to_s.should == @cert
- end
+ it "returns the public key" do
+ cert = R509::Cert.new(:cert => @cert_ec)
+ private_key = R509::PrivateKey.new(:key => @key_ec)
+ cert.public_key.to_der.should == private_key.public_key.to_der
end
- it "gets key usage from the extensions array" do
- cert = R509::Cert.new(:cert => @cert)
- cert.extensions["keyUsage"].nil?.should == false
- cert.extensions["keyUsage"]["value"].should == "Digital Signature, Key Encipherment"
+ it "returns the key algorithm" do
+ cert = R509::Cert.new(:cert => @cert_ec)
+ cert.key_algorithm.should == :ec
end
- it "gets extended key usage from the extensions array" do
- cert = R509::Cert.new(:cert => @cert)
- cert.extensions["extendedKeyUsage"].nil?.should == false
- cert.extensions["extendedKeyUsage"]["value"].should == "TLS Web Server Authentication"
- end
+ end
- it "gets the right object from #basic_constraints" do
- cert = R509::Cert.new(:cert => @cert)
- cert.basic_constraints.class.should == R509::Cert::Extensions::BasicConstraints
+ context "when elliptic curve support is unavailable" do
+ before :all do
+ @ec = OpenSSL::PKey.send(:remove_const,:EC) # remove EC support for test!
+ load('r509/ec-hack.rb')
end
- it "gets the right object from #key_usage" do
- cert = R509::Cert.new(:cert => @cert)
- cert.key_usage.class.should == R509::Cert::Extensions::KeyUsage
+ after :all do
+ OpenSSL::PKey.send(:remove_const,:EC) # remove stubbed EC
+ OpenSSL::PKey::EC = @ec # add the real one back
end
- it "gets the right object from #key_usage" do
- cert = R509::Cert.new(:cert => @cert)
- cert.extended_key_usage.class.should == R509::Cert::Extensions::ExtendedKeyUsage
- end
- it "gets the right object from #subject_key_identifier" do
- cert = R509::Cert.new(:cert => @cert)
- cert.subject_key_identifier.class.should == R509::Cert::Extensions::SubjectKeyIdentifier
- end
- it "gets the right object from #authority_key_identifier" do
- cert = R509::Cert.new(:cert => @cert)
- cert.authority_key_identifier.class.should == R509::Cert::Extensions::AuthorityKeyIdentifier
- end
- it "gets the right object from #subject_alternative_name" do
- cert = R509::Cert.new(:cert => @cert5)
- cert.subject_alternative_name.class.should == R509::Cert::Extensions::SubjectAlternativeName
- end
- it "gets the right object from #authority_info_access" do
- cert = R509::Cert.new(:cert => @cert5)
- cert.authority_info_access.class.should == R509::Cert::Extensions::AuthorityInfoAccess
- end
- it "gets the right object from #crl_distribution_points" do
- cert = R509::Cert.new(:cert => @cert)
- cert.crl_distribution_points.class.should == R509::Cert::Extensions::CrlDistributionPoints
- end
-
it "checks rsa?" do
- cert = R509::Cert.new(:cert => @cert)
- cert.rsa?.should == true
- cert.dsa?.should == false
+ cert = R509::Cert.new(:cert => @cert)
+ cert.rsa?.should == true
+ cert.ec?.should == false
+ cert.dsa?.should == false
end
- it "gets RSA bit strength" do
- cert = R509::Cert.new(:cert => @cert)
- cert.bit_strength.should == 2048
+ it "returns RSA key algorithm for RSA CSR" do
+ cert = R509::Cert.new(:cert => @cert)
+ cert.key_algorithm.should == :rsa
end
- it "checks dsa?" do
- cert = R509::Cert.new(:cert => @cert6)
- cert.rsa?.should == false
- cert.dsa?.should == true
- end
- it "gets DSA bit strength" do
- cert = R509::Cert.new(:cert => @cert6)
- cert.bit_strength.should == 1024
- end
- it "gets serial of cert" do
- cert = R509::Cert.new(:cert => @cert6)
- cert.serial.should == 951504
- end
- it "checks a cert that is not yet valid" do
- cert = R509::Cert.new(:cert => @cert_not_yet_valid)
- cert.valid?.should == false
- end
- it "checks a cert that is in validity range" do
- cert = R509::Cert.new(:cert => @test_ca_cert)
- cert.valid?.should == true
- end
- it "checks a cert that is expired" do
- cert = R509::Cert.new(:cert => @cert_expired)
- cert.valid?.should == false
- end
- it "checks expired_at?" do
- cert = R509::Cert.new(:cert => @cert_expired)
- cert.valid_at?(Time.utc(2009,1,1)).should == false
- cert.valid_at?(Time.utc(2011,3,1)).should == true
- cert.valid_at?(1298959200).should == true
- cert.valid_at?(Time.utc(2012,1,1)).should == false
- end
- it "is revoked by crl" do
- cert = R509::Cert.new(:cert => @cert3)
- crl_admin = R509::Crl::Administrator.new(TestFixtures.test_ca_config)
- crl_admin.revoke_cert(1425751142578902223005775172931960716533532010870)
- crl = crl_admin.to_crl
- cert.is_revoked_by_crl?(crl).should == true
- end
- it "is not revoked by crl" do
- cert = R509::Cert.new(:cert => @cert3)
- crl_admin = R509::Crl::Administrator.new(TestFixtures.test_ca_config)
- crl = crl_admin.to_crl
- cert.is_revoked_by_crl?(crl).should == false
- end
- it "loads a cert with load_from_file" do
- path = File.dirname(__FILE__) + '/fixtures/cert1.pem'
- cert = R509::Cert.load_from_file path
- cert.serial.to_i.should == 211653423715
- end
+ end
end