1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
|
begin
require "openssl"
require File.join(File.dirname(__FILE__), "utils.rb")
rescue LoadError
end
require "test/unit"
if defined?(OpenSSL)
class OpenSSL::TestX509Certificate < Test::Unit::TestCase
def setup
@rsa1024 = OpenSSL::TestUtils::TEST_KEY_RSA1024
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
@dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
@ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
@ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
end
def teardown
end
def issue_cert(*args)
OpenSSL::TestUtils.issue_cert(*args)
end
def test_serial
[1, 2**32, 2**100].each{|s|
cert = issue_cert(@ca, @rsa2048, s, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(s, cert.serial)
cert = OpenSSL::X509::Certificate.new(cert.to_der)
assert_equal(s, cert.serial)
}
end
def test_public_key
exts = [
["basicConstraints","CA:TRUE",true],
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","keyid:always",false],
]
sha1 = OpenSSL::Digest::SHA1.new
dss1 = OpenSSL::Digest::DSS1.new
[
[@rsa1024, sha1], [@rsa2048, sha1], [@dsa256, dss1], [@dsa512, dss1],
].each{|pk, digest|
cert = issue_cert(@ca, pk, 1, Time.now, Time.now+3600, exts,
nil, nil, digest)
assert_equal(cert.extensions[1].value,
OpenSSL::TestUtils.get_subject_key_id(cert))
cert = OpenSSL::X509::Certificate.new(cert.to_der)
assert_equal(cert.extensions[1].value,
OpenSSL::TestUtils.get_subject_key_id(cert))
}
end
def test_validity
now = Time.now until now && now.usec != 0
cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_not_equal(now, cert.not_before)
assert_not_equal(now+3600, cert.not_after)
now = Time.at(now.to_i)
cert = issue_cert(@ca, @rsa2048, 1, now, now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(now.getutc, cert.not_before)
assert_equal((now+3600).getutc, cert.not_after)
now = Time.at(0)
cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(now.getutc, cert.not_before)
assert_equal(now.getutc, cert.not_after)
now = Time.at(0x7fffffff)
cert = issue_cert(@ca, @rsa2048, 1, now, now, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(now.getutc, cert.not_before)
assert_equal(now.getutc, cert.not_after)
end
def test_extension
ca_exts = [
["basicConstraints","CA:TRUE",true],
["keyUsage","keyCertSign, cRLSign",true],
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","keyid:always",false],
]
ca_cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, ca_exts,
nil, nil, OpenSSL::Digest::SHA1.new)
ca_cert.extensions.each_with_index{|ext, i|
assert_equal(ca_exts[i].first, ext.oid)
assert_equal(ca_exts[i].last, ext.critical?)
}
ee1_exts = [
["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","keyid:always",false],
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
["subjectAltName","email:ee1@ruby-lang.org",false],
]
ee1_cert = issue_cert(@ee1, @rsa1024, 2, Time.now, Time.now+1800, ee1_exts,
ca_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der)
ee1_cert.extensions.each_with_index{|ext, i|
assert_equal(ee1_exts[i].first, ext.oid)
assert_equal(ee1_exts[i].last, ext.critical?)
}
ee2_exts = [
["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","issuer:always",false],
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
["subjectAltName","email:ee2@ruby-lang.org",false],
]
ee2_cert = issue_cert(@ee2, @rsa1024, 3, Time.now, Time.now+1800, ee2_exts,
ca_cert, @rsa2048, OpenSSL::Digest::MD5.new)
assert_equal(ca_cert.subject.to_der, ee2_cert.issuer.to_der)
ee2_cert.extensions.each_with_index{|ext, i|
assert_equal(ee2_exts[i].first, ext.oid)
assert_equal(ee2_exts[i].last, ext.critical?)
}
end
def test_sign_and_verify_wrong_key_type
cert_rsa = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
cert_dsa = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::DSS1.new)
begin
assert_equal(false, cert_rsa.verify(@dsa256))
rescue OpenSSL::X509::CertificateError => e
# OpenSSL 1.0.0 added checks for pkey OID
assert_equal('wrong public key type', e.message)
end
begin
assert_equal(false, cert_dsa.verify(@rsa1024))
rescue OpenSSL::X509::CertificateError => e
# OpenSSL 1.0.0 added checks for pkey OID
assert_equal('wrong public key type', e.message)
end
end
def test_sign_and_verify
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal("sha1WithRSAEncryption", cert.signature_algorithm)
assert_equal(false, cert.verify(@rsa1024))
assert_equal(true, cert.verify(@rsa2048))
cert.serial = 2
assert_equal(false, cert.verify(@rsa2048))
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::MD5.new)
assert_equal("md5WithRSAEncryption", cert.signature_algorithm)
assert_equal(false, cert.verify(@rsa1024))
assert_equal(true, cert.verify(@rsa2048))
cert.subject = @ee1
assert_equal(false, cert.verify(@rsa2048))
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::DSS1.new)
assert_equal("dsaWithSHA1", cert.signature_algorithm)
assert_equal(false, cert.verify(@dsa256))
assert_equal(true, cert.verify(@dsa512))
cert.not_after = Time.now
assert_equal(false, cert.verify(@dsa512))
assert_raise(OpenSSL::X509::CertificateError){
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::DSS1.new)
}
assert_raise(OpenSSL::X509::CertificateError){
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::MD5.new)
}
end
def test_dsig_algorithm_mismatch
assert_raise(OpenSSL::X509::CertificateError) do
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::DSS1.new)
end
assert_raise(OpenSSL::X509::CertificateError) do
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::MD5.new)
end
end
def test_dsa_with_sha2
begin
cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA256.new)
assert_equal("dsa_with_SHA256", cert.signature_algorithm)
rescue OpenSSL::X509::CertificateError
# dsa_with_sha2 not supported. skip following test.
return
end
# TODO: need more tests for dsa + sha2
# SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requireds DSS1)
cert = issue_cert(@ca, @dsa256, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal("dsaWithSHA1", cert.signature_algorithm)
end
def test_check_private_key
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(true, cert.check_private_key(@rsa2048))
end
def test_to_text
cert_pem = <<END
-----BEGIN CERTIFICATE-----
MIIC8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQQFADA9MRMwEQYKCZImiZPyLGQB
GRYDb3JnMRkwFwYKCZImiZPyLGQBGRYJcnVieS1sYW5nMQswCQYDVQQDDAJDQTAe
Fw0wOTA1MjMxNTAzNDNaFw0wOTA1MjMxNjAzNDNaMD0xEzARBgoJkiaJk/IsZAEZ
FgNvcmcxGTAXBgoJkiaJk/IsZAEZFglydWJ5LWxhbmcxCzAJBgNVBAMMAkNBMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuV9ht9J7k4NBs38jOXvvTKY9
gW8nLICSno5EETR1cuF7i4pNs9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enen
fzq/t/e/1IRW0wkJUJUFQign4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWm
qbjs07JbuS4QQGGXLc+Su96DkYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v6
8JkRFIhdGlb6JL8fllf/A/blNwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX
9KZYcU00mOX+fdxOSnGqS/8JDRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wID
AQABMA0GCSqGSIb3DQEBBAUAA4IBAQB8UTw1agA9wdXxHMUACduYu6oNL7pdF0dr
w7a4QPJyj62h4+Umxvp13q0PBw0E+mSjhXMcqUhDLjrmMcvvNGhuh5Sdjbe3GI/M
3lCC9OwYYIzzul7omvGC3JEIGfzzdNnPPCPKEWp5X9f0MKLMR79qOf+sjHTjN2BY
SY3YGsEFxyTXDdqrlaYaOtTAdi/C+g1WxR8fkPLefymVwIFwvyc9/bnp7iBn7Hcw
mbxtLPbtQ9mURT0GHewZRTGJ1aiTq9Ag3xXME2FPF04eFRd3mclOQZNXKQ+LDxYf
k0X5FeZvsWf4srFxoVxlcDdJtHh91ZRpDDJYGQlsUm9CPTnO+e4E
-----END CERTIFICATE-----
END
cert = OpenSSL::X509::Certificate.new(cert_pem)
cert_text = <<END
[0] Version: 3
SerialNumber: 1
IssuerDN: DC=org,DC=ruby-lang,CN=CA
Start Date: Sat May 23 17:03:43 CEST 2009
Final Date: Sat May 23 18:03:43 CEST 2009
SubjectDN: DC=org,DC=ruby-lang,CN=CA
Public Key: RSA Public Key
modulus: b95f61b7d27b938341b37f23397bef4ca63d816f272c80929e8e4411347572e17b8b8a4db3d2354091801405f40443b829bcd79ae3af7c2a43dc253e4a5a757a77a77f3abfb7f7bfd48456d30909509505422827e02b6b9092fe3f4ef2c75f148f23e50576fcd40a449800799ab2554ab5a6a9b8ecd3b25bb92e104061972dcf92bbde839182a648d5630622f15554a9c997c0637843dfb77ad2e1be5fcc5d5b9bfaf0991114885d1a56fa24bf1f9657ff03f6e53707493a156bf661121e1c068f07d27930cf7ddf192c4d36ec4e65c80557f4a658714d3498e5fe7ddc4e4a71aa4bff090d187410f1c32f5e517098d5d89eaf6633dbd2b398183a0c707fbde3
public exponent: 10001
Signature Algorithm: MD5withRSA
Signature: 7c513c356a003dc1d5f11cc50009db98bbaa0d2f
ba5d17476bc3b6b840f2728fada1e3e526c6fa75
dead0f070d04fa64a385731ca948432e3ae631cb
ef34686e87949d8db7b7188fccde5082f4ec1860
8cf3ba5ee89af182dc910819fcf374d9cf3c23ca
116a795fd7f430a2cc47bf6a39ffac8c74e33760
58498dd81ac105c724d70ddaab95a61a3ad4c076
2fc2fa0d56c51f1f90f2de7f2995c08170bf273d
fdb9e9ee2067ec773099bc6d2cf6ed43d994453d
061dec19453189d5a893abd020df15cc13614f17
4e1e15177799c94e419357290f8b0f161f9345f9
15e66fb167f8b2b171a15c65703749b4787dd594
690c325819096c526f423d39cef9ee04
END
assert_not_nil(cert.to_text)
# This is commented out because it doesn't take timezone into consideration; FIXME
#assert_equal(cert_text, cert.to_text)
end
end
end
|