Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
781 views
in Technique[技术] by (71.8m points)

openssl - Convert RSA public key to RSA DER

I have id_rsa.pub key generated by ssh-keygen. How can I programmatically convert id_rsa.pub files to RSA DER formatted keys?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you use ssh-keygen to generate a key:

$ ssh-keygen

Then you can just use openssl to pull out the public key and write it in the DER format like this:

$ openssl rsa -in id_rsa -out pub.der -outform DER -pubout
writing RSA key

You can view the DER output as PEM like this:

$ openssl rsa -in pub.der -inform DER -pubin -text

I don't use Ruby, so I don't know how easy it is to use OpenSSL from Ruby.

Edit: I answered too quickly -- you wrote id_rsa.pub and you may not have the id_rsa itself. Another Stack Overflow question is for the reverse conversion, but the source code found there might help: Convert pem key to ssh-rsa format Once you have PEM you can use openssl to convert the PEM to DER.

Edit, May 2014: Ruby has become my favorite programming language, and the original question (since edited) asked about Ruby. Here is code to read the id_rsa.pub (public key) and write an OpenSSL-generated, DER-formatted public key:

require 'openssl'
require 'base64'

def read_length(s)
    # four bytes, big-endian
    length = s[0..3].unpack('N')[0]
end

def read_integer(s, length)
    # shift all bytes into one integer
    s[4..3 + length].unpack('C*').inject { |n, b| (n << 8) + b }
end

def cut(s, length)
    s[4 + length..-1]
end

def decode_pub(pub)
    # the second field is the Base64 piece needed
    s = Base64.decode64(pub.split[1])

    # first field reading "ssh-rsa" is ignored
    i = read_length(s)
    s = cut(s, i)

    # public exponent e
    i = read_length(s)
    e = read_integer(s, i)
    s = cut(s, i)

    # modulus n
    i = read_length(s)
    n = read_integer(s, i)

    [ e, n ]
end

def make_asn1(e, n)
    # Simple RSA public key in ASN.1
    e0 = OpenSSL::ASN1::Integer.new(e)
    n1 = OpenSSL::ASN1::Integer.new(n)
    OpenSSL::ASN1::Sequence.new([ e0, n1 ])
end

pub = File.read('id_rsa.pub')

asn1 = make_asn1(*decode_pub(pub))

# Let OpenSSL deal with converting from the simple ASN.1
key = OpenSSL::PKey::RSA.new(asn1.to_der)

# Write out the public key in both PEM and DER formats
File.open('id_rsa.pem', 'w') { |f| f.write key.to_pem }
File.open('id_rsa.der', 'w') { |f| f.write key.to_der }

You can check the output with these openssl commands in the shell:

$ openssl rsa -pubin -text -in id_rsa.pem
$ openssl rsa -pubin -text -inform DER -in id_rsa.der

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...