Skip to content

Instantly share code, notes, and snippets.

@rhyselsmore
Created February 18, 2019 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rhyselsmore/c0ec0538f40788e33b2696fb1719ce94 to your computer and use it in GitHub Desktop.
Save rhyselsmore/c0ec0538f40788e33b2696fb1719ce94 to your computer and use it in GitHub Desktop.
ctl.rb
require 'bindata'
require 'base64'
require 'openssl'
require 'multi_json'
require 'excon'
class MerkleTreeHeader < BinData::Record
class Types
X509_LOG_ENTRY = "x509_log_entry".freeze
PRECERT_LOG_ENTRY = "precert_log_entry".freeze
end
uint8be :version
uint8be :merkle_leaf_type
uint64be :timestamp
uint16be :log_entry_type
rest :data
def leaf_type
case log_entry_type
when 0
Types::X509_LOG_ENTRY
when 1
Types::PRECERT_LOG_ENTRY
end
end
end
class Certificate < BinData::Record
endian :big
uint24be :cert_length
string :data, length: :cert_length
end
class CertificateChain < BinData::Record
endian :big
uint24be :chain_length
array :data, type: Certificate, read_until: :eof
end
class PreCertEntry < BinData::Record
endian :big
Certificate :leaf_cert
uint24be :precert_length
string :data, length: :cert_length
end
response = Excon.get('https://yeti2020.ct.digicert.com/log/ct/v1/get-entries?start=169249&end=170249')
data = MultiJson.load(response.body, symbolize_keys: true)
data[:entries].map do |entry|
# Read the header
h = MerkleTreeHeader.read Base64.decode64(entry[:leaf_input])
p "------------"
case h.leaf_type
when MerkleTreeHeader::Types::X509_LOG_ENTRY
# Parse the Certificate
cert = OpenSSL::X509::Certificate.new Certificate.read(h.data).data
# Obtain issuer/serial
issuer = cert.issuer.to_s
serial = cert.serial.to_s
# Obtain the Certificate Subject
subject = cert.subject.to_a.each(&:pop).to_h
p subject["CN"]
begin
domains = [ subject.fetch("CN") ]
rescue
domains = []
end
# Obtain Subject Alternative Names
subject_alt_name = cert.extensions.find {|e| e.oid == "subjectAltName"}
asn_san = OpenSSL::ASN1.decode(subject_alt_name)
asn_san_sequence = OpenSSL::ASN1.decode(asn_san.value[1].value)
asn_san_sequence.each do |asn_data|
domains << asn_data.value
end
p domains
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment