Skip to content

Instantly share code, notes, and snippets.

@cky
Last active December 29, 2022 23:26
Show Gist options
  • Save cky/b25fc1b1b745d42d01beb5ad384664a1 to your computer and use it in GitHub Desktop.
Save cky/b25fc1b1b745d42d01beb5ad384664a1 to your computer and use it in GitHub Desktop.
Quick script for converting PEM-format RSA keys to a format usable by .NET's RSA.FromXmlString
#!/usr/bin/ruby
require 'openssl'
TYPES = {
6 => {magic: 'RSA1', private_key: false},
7 => {magic: 'RSA2', private_key: true}
}
data = ARGV[0] ? File.binread(ARGV[0]) : $stdin.binmode.read
type, version, algo, magic, bits, rest = data.unpack('ccx2l<a4l<a*')
if match = TYPES[type]
raise 'Wrong magic' if magic != match[:magic]
private_key = match[:private_key]
else
raise 'Unsupported type'
end
raise 'Unsupported version' if version != 2
raise 'Unsupported algorithm' if ((algo >> 9) & 15) != 2
fields = [32, bits]
fields.push(*[bits / 2] * 5, bits) if private_key
key = OpenSSL::PKey::RSA.new
key.e, key.n, key.p, key.q, key.dmp1, key.dmq1, key.iqmp, key.d = fields.map do |bits|
size = (bits + 7) / 8
raise 'Unexpected end of data reached' if rest.size < size
OpenSSL::BN.new(rest.slice!(0, size).reverse!, 2)
end
raise 'Unexpected leftover data' unless rest.empty?
puts key.to_pem
#!/usr/bin/ruby
require 'nokogiri'
require 'openssl'
def base64(bn)
[bn.to_s(2)].pack('m0')
end
key = OpenSSL::PKey::RSA.new($stdin)
builder = Nokogiri::XML::Builder.new do |xml|
xml.RSAKeyValue do
xml.Modulus base64(key.n)
xml.Exponent base64(key.e)
if key.private?
xml.D base64(key.d)
xml.P base64(key.p)
xml.Q base64(key.q)
xml.DP base64(key.dmp1)
xml.DQ base64(key.dmq1)
xml.InverseQ base64(key.iqmp)
end
end
end
puts builder.to_xml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment