Certificate trust chain check

new-scoring
aeris 6 years ago
parent 3d12eaacea
commit e28b857213
  1. 1
      lib/cryptcheck.rb
  2. 19
      lib/cryptcheck/tls/cert.rb
  3. 21
      lib/cryptcheck/tls/fixture.rb
  4. 32
      spec/cryptcheck/cert_spec.rb
  5. 13
      spec/resources/ca.crt
  6. 13
      spec/resources/custom.crt
  7. 13
      spec/resources/intermediate.crt
  8. 13
      spec/resources/self-signed.crt

@ -38,6 +38,7 @@ module CryptCheck
autoload :Method, 'cryptcheck/tls/method'
autoload :Cipher, 'cryptcheck/tls/cipher'
autoload :Curve, 'cryptcheck/tls/curve'
autoload :Cert, 'cryptcheck/tls/cert'
autoload :Server, 'cryptcheck/tls/server'
autoload :TcpServer, 'cryptcheck/tls/server'
autoload :UdpServer, 'cryptcheck/tls/server'

@ -1,6 +1,10 @@
module CryptCheck
module Tls
class Cert
DEFAULT_CA_DIRECTORIES = [
'/usr/share/ca-certificates/mozilla'
]
SIGNATURE_ALGORITHMS = {
'dsaWithSHA' => %i(sha1 dss),
'dsaWithSHA1' => %i(sha1 dss),
@ -48,6 +52,21 @@ module CryptCheck
end
RUBY_EVAL
end
def self.trusted?(cert, chain, roots: DEFAULT_CA_DIRECTORIES)
store = ::OpenSSL::X509::Store.new
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
store.add_chains roots
chain.each do |cert|
# Never add other self signed certificates than system CA !
next if cert.subject == cert.issuer
store.add_cert cert rescue nil
end
trusted = store.verify cert
return :trusted if trusted
store.error_string
end
end
end
end

@ -154,3 +154,24 @@ class ::OpenSSL::PKey::DH
end
end
end
class ::OpenSSL::X509::Store
def add_chains(chains)
chains = [chains] unless chains.is_a? Enumerable
chains.each do |chain|
case chain
when ::OpenSSL::X509::Certificate
self.add_cert chain
else
if File.directory?(chain)
Dir.entries(chain)
.collect { |e| File.join chain, e }
.select { |e| File.file? e }
.each { |f| self.add_file f }
else
self.add_file chain
end
end
end
end
end

@ -0,0 +1,32 @@
describe CryptCheck::Tls::Cert do
def load_chain(chain)
chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read File.join 'spec/resources', "#{f}.crt" }
end
describe '::trusted?' do
it 'must accept valid certificat' do
cert, *chain, ca = load_chain %w(custom intermediate ca)
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
expect(trust).to eq :trusted
end
it 'must reject self signed certificate' do
cert, ca = load_chain %w(self-signed ca)
trust = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
expect(trust).to eq 'self signed certificate'
end
it 'must reject unknown CA' do
cert, *chain = load_chain %w(custom intermediate ca)
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: []
expect(trust).to eq 'unable to get issuer certificate'
end
it 'must reject missing intermediate chain' do
cert, ca = load_chain %w(custom ca)
chain = []
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
expect(trust).to eq 'unable to get local issuer certificate'
end
end
end

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB7zCCAXWgAwIBAgIJAKFu2k3vOIffMAoGCCqGSM49BAMEMBIxEDAOBgNVBAMM
B3Rlc3QtY2EwHhcNMTcwMTIyMTg1NTUxWhcNMTgwMTIyMTg1NTUxWjASMRAwDgYD
VQQDDAd0ZXN0LWNhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhVE2pSx4GG922yqA
z0W0usG8dFdY4qtTD5mwwBzRhu9NegzQmaE5oHNzQrQE8v0/ShrSHNdID6Phty9K
lPYoenUmpH0sdJDqQ5cVUDkmw0+f+XpROtCiBcN8kTmiVXQ5o4GWMIGTMA8GA1Ud
EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgL0MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
BgEFBQcDAjAdBgNVHQ4EFgQU2saIfk29nr+adaNemnS2AaNjXJEwHwYDVR0jBBgw
FoAU2saIfk29nr+adaNemnS2AaNjXJEwFAYDVR0RBA0wC4IJbG9jYWxob3N0MAoG
CCqGSM49BAMEA2gAMGUCMQCzxeexb5HauoM8OQPBK7MWxzganLfVoi1GCsbvjUQy
AB8AAVijIPwT/MGcigge4z8CMFimJXl934AtL8iM+Jd9ykvNXXxzSn9YRm9aLD3K
w6vam+k+gA4sdijDbRC/Tc/3NQ==
-----END CERTIFICATE-----

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAXCgAwIBAgIJAKyx4KGEOyVdMAoGCCqGSM49BAMEMBwxGjAYBgNVBAMM
EXRlc3QtaW50ZXJtZWRpYXRlMB4XDTE3MDEyMjE4NTU1MVoXDTE4MDEyMjE4NTU1
MVowFDESMBAGA1UEAwwJdGVzdC1sZWFmMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE
kZFi7jp4Z+3m1lR/aIHuNalLQtjaCErIgrWhFL7oUjzWMN1dR3nAmmosKlCSRc7A
Xazs+CC0QB1LgsZCFFPhPqUd5456iwCHaSVQ3maESrZtzJo78v/fE9HRuuh5fFiL
o4GFMIGCMAsGA1UdDwQEAwIE8DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
AwIwHQYDVR0OBBYEFB54cEd+wLKHpMKYkYCxmSgWERrQMB8GA1UdIwQYMBaAFMgN
6Mqlnk3ZRmp4RrAXXKeC3yVHMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAKBggqhkjO
PQQDBANoADBlAjEAwbhbwXjekyl3esK9ywh+jKCVhf7BzaF4H7LAxUE1PmXTORrZ
tqz2MXK3/zYfe1bXAjAuan+xZ4d5zCgBvnFO2/LMEX07SFQJT3l1hKAZjpbdNm/K
MY23IR6iLWkPlG1u+Wo=
-----END CERTIFICATE-----

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB+TCCAX+gAwIBAgIJAOko1FM8hOfNMAoGCCqGSM49BAMEMBIxEDAOBgNVBAMM
B3Rlc3QtY2EwHhcNMTcwMTIyMTg1NTUxWhcNMTgwMTIyMTg1NTUxWjAcMRowGAYD
VQQDDBF0ZXN0LWludGVybWVkaWF0ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABNjg
qyABIHj96OvYN1YCe+z3mILDlm1qNXm1bpoMcx7AVANk+AFUjbK/mhSyx5ONbBw/
4kMBNtVW7OpkiZwLr57SbqDv0n4ExirUvvBm7OcqqSY+73lXM/cezMTRA/3ZqqOB
ljCBkzAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIC9DAdBgNVHSUEFjAUBggr
BgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFMgN6Mqlnk3ZRmp4RrAXXKeC3yVH
MB8GA1UdIwQYMBaAFNrGiH5NvZ6/mnWjXpp0tgGjY1yRMBQGA1UdEQQNMAuCCWxv
Y2FsaG9zdDAKBggqhkjOPQQDBANoADBlAjAUAte4U3OtzmeQLA/Cq1JTtsrE7sy9
kZzxGHxACZ53sTGA2c4K86lR2RGoXYvW62wCMQCNSLH+qukadu52ip7HTkihrtae
hBVOBO+el6rCcby91xUuWU24AJy9Ce9TxcQC384=
-----END CERTIFICATE-----

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICBjCCAYugAwIBAgIJAPnnJnLp7H/XMAoGCCqGSM49BAMEMBQxEjAQBgNVBAMM
CWxvY2FsaG9zdDAeFw0xNzAxMjIxNjM1NDdaFw0xODAxMjIxNjM1NDdaMBQxEjAQ
BgNVBAMMCWxvY2FsaG9zdDB2MBAGByqGSM49AgEGBSuBBAAiA2IABJvRcgAMkjzZ
p0YD/mXa2Td8sy7fBr7F5Sj8toSmLAxkxxPCnm9DDdLQXy7IZXA1HJkiRUIJ8BTk
gSxmKQBwl3my2quHGx7GSZshpER4tRtqWI21dTUkuu9bGR66bbLa8aOBqDCBpTAP
BgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIC9DAdBgNVHSUEFjAUBggrBgEFBQcD
AQYIKwYBBQUHAwIwHQYDVR0OBBYEFCEkGXQc44mMopATg1jr+stKnF4LMB8GA1Ud
IwQYMBaAFCEkGXQc44mMopATg1jr+stKnF4LMBQGA1UdEQQNMAuCCWxvY2FsaG9z
dDAQBggrBgEFBQcBGAEB/wQBMDAKBggqhkjOPQQDBANpADBmAjEAkPKxToKRloWT
eH4lGaUrqBGpRof92rWmJiBLs5WnaYM73S/GdKNK1j0jKRCKXKpzAjEAgpjvaUhd
qXkR3g8iWedrFjkVHHVrUGV9JW7elHP7bD6XryqsGRNK2X8yq0J616gP
-----END CERTIFICATE-----
Loading…
Cancel
Save