Skip to content

Instantly share code, notes, and snippets.

@mpalmer
Created September 6, 2015 22:08
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 mpalmer/1fd2df4c64ce46e6b8e3 to your computer and use it in GitHub Desktop.
Save mpalmer/1fd2df4c64ce46e6b8e3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'openssl'
require 'digest/sha1'
def main(argv)
if argv.empty?
$stderr.puts <<-EOF.gsub("\t\t\t", '')
Please provide at least one key/cert/csr file.
Usage: #{$0} <files...>
EOF
exit 1
end
argv.each do |f|
data = if f == '-'
$stdin.read
else
unless File.exists?(f)
$stderr.puts "File does not exist: #{f}"
next
end
unless File.readable?(f)
$stderr.puts "File is not readable: #{f}"
next
end
File.read(f)
end
begin
pubkey = case data
when /^-----BEGIN (RSA|ENCRYPTED) PRIVATE KEY-----/
pubkey_from_private_key(data)
when /^-----BEGIN CERTIFICATE-----/
pubkey_from_certificate(data)
when /^-----BEGIN CERTIFICATE REQUEST-----/
pubkey_from_csr(data)
when /^-----BEGIN (RSA )?PUBLIC KEY-----/
pubkey_from_public_key(data)
else
$stderr.puts "Unknown key type for #{f}: must be a PEM-encoded key, cert, or CSR"
next
end
rescue StandardError => e
$stderr.puts "Parsing failed for #{f}: #{e.class} (#{e.message})"
next
end
puts "#{keyid_from_pubkey(pubkey)}\t#{f}"
end
end
def pubkey_from_private_key(data)
begin
passphrase = if File.executable?("/usr/local/sbin/pp")
`/usr/local/sbin/pp`.strip
else
''
end
OpenSSL::PKey::RSA.new(data, passphrase)
rescue OpenSSL::PKey::RSAError
begin
OpenSSL::PKey::RSA.new(data)
rescue OpenSSL::PKey::RSAError
raise RuntimeError,
"File is corrupt, or the correct passphrase is not available"
end
end
end
def pubkey_from_certificate(data)
OpenSSL::X509::Certificate.new(data).public_key
end
def pubkey_from_csr(data)
OpenSSL::X509::Request.new(data).public_key
end
def pubkey_from_public_key(data)
OpenSSL::PKey::RSA.new(data).public_key
end
def keyid_from_pubkey(pubkey)
seq = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(pubkey.n),
OpenSSL::ASN1::Integer.new(pubkey.e)])
Digest::SHA1::hexdigest(seq.to_der).upcase.scan(/../).join(':')
end
main(ARGV) if $0 == __FILE__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment