Convert RSA public key to RSA DER

后端 未结 2 752
不思量自难忘°
不思量自难忘° 2020-12-13 20:53

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

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-13 21:17

    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
    

提交回复
热议问题