def verify_gem(signature, data, chain, time = Time.now)
Gem.ensure_ssl_available
cert_class = OpenSSL::X509::Certificate
exc = Gem::Security::Exception
chain ||= []
chain = chain.map{ |str| cert_class.new(str) }
signer, ch_len = chain[-1], chain.size
if @verify_data
dgst = @opt[:dgst_algo]
v = signer.public_key.verify(dgst.new, signature, data)
raise exc, "Invalid Gem Signature" unless v
if @verify_signer
v = signer.check_validity(nil, time)
raise exc, "Invalid Signature: #{v[:desc]}" unless v[:is_valid]
end
end
if @verify_chain
(ch_len - 1).downto(1) do |i|
issuer, cert = chain[i - 1, 2]
v = cert.check_validity(issuer, time)
raise exc, "%s: cert = '%s', error = '%s'" % [
'Invalid Signing Chain', cert.subject, v[:desc]
] unless v[:is_valid]
end
if @verify_root
root = chain[0]
raise exc, "%s: %s (subject = '%s', issuer = '%s')" % [
'Invalid Signing Chain Root',
'Subject does not match Issuer for Gem Signing Chain',
root.subject.to_s,
root.issuer.to_s,
] unless root.issuer.to_s == root.subject.to_s
v = root.check_validity(root, time)
raise exc, "%s: cert = '%s', error = '%s'" % [
'Invalid Signing Chain Root', root.subject, v[:desc]
] unless v[:is_valid]
if @only_trusted
algo = @opt[:dgst_algo]
path = Gem::Security::Policy.trusted_cert_path(root, @opt)
raise exc, "%s: cert = '%s', error = '%s'" % [
'Untrusted Signing Chain Root',
root.subject.to_s,
"path \"#{path}\" does not exist",
] unless File.exist?(path)
save_cert = OpenSSL::X509::Certificate.new(File.read(path))
save_dgst = algo.digest(save_cert.public_key.to_s)
pkey_str = root.public_key.to_s
cert_dgst = algo.digest(pkey_str)
raise exc, "%s: %s (saved = '%s', root = '%s')" % [
'Invalid Signing Chain Root',
"Saved checksum doesn't match root checksum",
save_dgst, cert_dgst,
] unless save_dgst == cert_dgst
end
end
chain.map { |cert| cert.subject }
end
end