Skip to content

Instantly share code, notes, and snippets.

@anicet
Last active January 20, 2023 16:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anicet/9dcbe32457185539d74463eaa0b1cc5c to your computer and use it in GitHub Desktop.
Save anicet/9dcbe32457185539d74463eaa0b1cc5c to your computer and use it in GitHub Desktop.
PKeyRSAConverter: RSAKeyValue .NET XML to RSA PEM (and RSA PEM to RSAKeyValue .NET XML)
require 'openssl'
require 'base64'
require 'rexml/document'
class PKeyRSAConverter
def initialize(from_pem: nil, from_xml: nil)
@from_pem = from_pem
@from_xml = from_xml
end
def to_xml
xml = '<RSAKeyValue>'
xml += "<Modulus>#{xml_base64(xml_pkey.n)}</Modulus>"
xml += "<Exponent>#{xml_base64(xml_pkey.e)}</Exponent>"
xml += '</RSAKeyValue>'
xml
end
def to_pem
pem_key.to_pem
end
private
def pem_key
exponent = xml_find_exponent.to_s
modulus = xml_find_modulus.to_s
key = OpenSSL::PKey::RSA.new
key.set_key(pem_base64(modulus), pem_base64(exponent), nil)
key
end
def xml_find_modulus
REXML::XPath.match(xml_document.root, '//RSAKeyValue/Modulus/text()')[0]
end
def xml_find_exponent
REXML::XPath.match(xml_document.root, '//RSAKeyValue/Exponent/text()')[0]
end
def xml_document
@xml_document ||= REXML::Document.new(@from_xml.to_s)
end
def pem_base64(string)
Base64.urlsafe_decode64(string).bytes.inject(0) { |a, e| (a << 8) | e }
end
def xml_pkey
@xml_pkey ||= OpenSSL::PKey::RSA.new(@from_pem)
end
def xml_base64(int)
Base64.encode64([int.to_s(16).downcase].pack('H*')).split("\n").join
end
end
# Example
rsa_xml = '<RSAKeyValue><Modulus>lg6UHw38R0kv2eoSxE0X42j/1CSY9pf/HGk+V5lNM2BqRORSWbJk+53x4QaxpfucuChUXf3NOtd6DiEh5pawCw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>'
rsa_pem = "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJYOlB8N/EdJL9nqEsRNF+No/9QkmPaX\n/xxpPleZTTNgakTkUlmyZPud8eEGsaX7nLgoVF39zTrXeg4hIeaWsAsCAwEAAQ==\n-----END PUBLIC KEY-----\n"
puts 'Convert PEM to XML'
to_xml = PKeyRSAConverter.new(from_pem: rsa_pem).to_xml
puts to_xml == rsa_xml
puts 'Convert XML to PEM'
to_pem = PKeyRSAConverter.new(from_xml: rsa_xml).to_pem
puts rsa_pem == to_pem
@xiaoronglv
Copy link

    key.n = pem_base64(modulus)
    key.e = pem_base64(exponent)

https://gist.github.com/anicet/9dcbe32457185539d74463eaa0b1cc5c#file-pkey_rsa_converter-rb-L29-L30

These two lines don't work in the new ruby version. please replace them with the following.

    key.set_key(pem_base64(modulus), pem_base64(exponent), nil)

@anicet
Copy link
Author

anicet commented Feb 25, 2022

I have no idea why I did this @xiaoronglv, but thanks !
Code updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment