2016-03-29 7 views
1

私は、パブリックSSHキーからモジュラスと指数を抽出して、PEM公開鍵を生成します。ここに私のコードは、これまでのところです:SSH SubjectPublicKeyInfoモジュラスと指数

require "base64" 
require "openssl" 


def unpacked_byte_array(ssh_type, encoded_key) 
    prefix = [7].pack("N") + ssh_type 
    decoded = Base64.decode64(encoded_key) 

    # Base64 decoding is too permissive, so we should validate if encoding is correct 
    unless Base64.encode64(decoded).gsub("\n", "") == encoded_key && decoded.slice!(0, prefix.length) == prefix 
    raise PublicKeyError, "validation error" 
    end 

    data = [] 
    until decoded.empty? 
    front = decoded.slice!(0,4) 
    size = front.unpack("N").first 
    segment = decoded.slice!(0, size) 
    unless front.length == 4 && segment.length == size 
     raise PublicKeyError, "byte array too short" 
    end 
    data << OpenSSL::BN.new(segment, 2) 
    end 
    return data 
end 

module OpenSSL 
    module PKey 
    class RSA 
     def self.new_from_parameters(n, e) 
     a = self.new # self.new(64) for ruby < 1.8.2 
     a.n = n  # converted to OpenSSL::BN automatically 
     a.e = e 
     a 
     end 
    end 
    end 
end 

e, n = unpacked_byte_array('ssh-rsa', 'AAAAB3NzaC1yc2EAAAABIwAAAQEA3RC8whKGFx+b7BMTFtnIWl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJRh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUAJ+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZARcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/6Aco1XZjPvuKujAQMGSgqNskhKBO9zfhhkAMIcKVryjKYHDfqbDUCCSNzlwFLts3nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7smYnzF23jFs4XhvnjmIGQJcZT4kQAsRwQubyuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJdG2weIF8g3YP12czsBgNppz3jsnhEgstnQ==') 


rsa = OpenSSL::PKey::RSA.new_from_parameters(n, e) 
puts rsa 

目標はssh-keygen -f <file> -e -m pemが何をするかの純粋なRubyの実装を持つことです。

は今、結果を比較すると、彼らは非常に似ていますが、私のコードは、キーの先頭にいくつかのより多くのバイトを返します。

$ ssh-keygen -f ~/.ssh/id_rsa_perso.pub -e -m pem 
-----BEGIN RSA PUBLIC KEY----- 
MIIBCAKCAQEA3RC8whKGFx+b7BMTFtnIWl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJ 
Rh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUAJ+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZA 
RcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/6Aco1XZjPvuKujAQMGSgqNskhKBO9zfh 
hkAMIcKVryjKYHDfqbDUCCSNzlwFLts3nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7sm 
YnzF23jFs4XhvnjmIGQJcZT4kQAsRwQubyuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJ 
dG2weIF8g3YP12czsBgNppz3jsnhEgstnQIBIw== 
-----END RSA PUBLIC KEY----- 
$ ruby ssh2x509.rb 
-----BEGIN PUBLIC KEY----- 
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA3RC8whKGFx+b7BMTFtnI 
Wl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJRh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUA 
J+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZARcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/ 
6Aco1XZjPvuKujAQMGSgqNskhKBO9zfhhkAMIcKVryjKYHDfqbDUCCSNzlwFLts3 
nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7smYnzF23jFs4XhvnjmIGQJcZT4kQAsRwQu 
byuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJdG2weIF8g3YP12czsBgNppz3jsnhEgst 
nQIBIw== 
-----END PUBLIC KEY----- 

私の出力がssh-keygen出力の内容を持っていますが、とに注意してくださいMIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0Aが前に付いています。

これらの余分なバイトが原因で、正しい結果が得られるのでしょうか?

+0

実際にこのhttp:// stackoverflowの重複が見つかりました。com/questions/4635837/invalid-public-keys-ruby-openssl-libraryを使用している場合 –

+0

[.NetでOpenSSL RSA鍵を使用する](http://stackoverflow.com/q/30475758)を参照してください。 OpenSSLを使用してPKCSと従来のエンコーディング( 'BEGIN RSA PUBLIC KEY'と' BEGIN PUBLIC KEY')の両方でキーを保存する方法について説明します。 C/C++で見ると、すぐにRubyコードに必要な変更を加えることができます。 – jww

答えて

0

この問題を解決するには、ASN1の構造を分析できます。あなたの出力のために

が、それはsshの出力について

SEQUENCE(2 elem) 
SEQUENCE(2 elem) 
OBJECT IDENTIFIER1.2.840.113549.1.1.1 
NULL 
BIT STRING(1 elem) 
SEQUENCE(2 elem) 
INTEGER(2048 bit) 279069188856447290054297383130027286257044344789969750715307012565210… 
INTEGER35 

あり、それは

SEQUENCE(2 elem) 
INTEGER(2048 bit) 279069188856447290054297383130027286257044344789969750715307012565210… 
INTEGER35 

が、これは何を意味するのですか?これは、RSAキーの構造が異なっていることを意味します。 SSHでは、2048ビットの整数のシーケンスが入っています。あなたのケースでは、それはまた、オブジェクトの識別を運びます。

解決策? ASN1構造を解析して計算できる開始ビットを削除します。

または、RSA公開鍵からいくつのバイトを削除するかをhexdumpで分析します。

あなたのRSA公開鍵:これを分析することにより

30 82 01 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01 
01 05 00 03 82 01 0D 00 **30 82 01 08 02 82 01 01 
00 DD 10 BC C2** 12 86 17 1F 9B EC 13 13 16 D9 C8 
5A 5E AD FE AC AF 3A F9 EE A8 8A CC 34 8F 49 F3 
ED 6C 11 8B FC 63 FA 49 46 1D 2F 01 ED 91 69 22 
80 80 1D A1 CB 35 F0 48 9D 45 87 EA 28 AD A5 00 
27 EA BB 3F 68 20 DA 44 05 D6 70 85 78 65 63 B5 
… skipping 160 bytes … 
0F D7 67 33 B0 18 0D A6 9C F7 8E C9 E1 12 0B 2D 
9D 02 01 23 

SSH RSA公開鍵

**30 82 01 08 02 82 01 01 00 DD 10 BC C2** 12 86 17 
1F 9B EC 13 13 16 D9 C8 5A 5E AD FE AC AF 3A F9 
EE A8 8A CC 34 8F 49 F3 ED 6C 11 8B FC 63 FA 49 
46 1D 2F 01 ED 91 69 22 80 80 1D A1 CB 35 F0 48 
9D 45 87 EA 28 AD A5 00 27 EA BB 3F 68 20 DA 44 
… skipping 160 bytes … 
74 6D B0 78 81 7C 83 76 0F D7 67 33 B0 18 0D A6 
9C F7 8E C9 E1 12 0B 2D 9D 02 01 23 

は、あなたがこれらを削除する必要があることがわかります。

30 82 01 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01 
01 05 00 03 82 01 0D 00 

手段24バイト。あなたの鍵から24バイトを削除してください。

または、ASN1パーサーを使用してシーケンスを抽出するだけで済みます。

+0

あなたの答えをありがとう。 –

2

ルビーのOpenSSLでRSAキーの出力フォーマットはX509(OpenSSLのポスト1.9.3で使用)に(OpenSSHので使用)PKCS#1から1.9.3で変化させたと思われる:

https://redmine.ruby-lang.org/issues/4421

OpenSSL::PKey::RSAの猿のパッチ適用は、このように必要はありません

ary = [OpenSSL::ASN1::Integer.new(n), OpenSSL::ASN1::Integer.new(e)] 
pub_key = OpenSSL::ASN1::Sequence.new(ary) 
base64 = Base64.encode64(pub_key.to_der) 

#This is the equivalent to the PKCS#1 encoding used before 1.9.3 
pem = "-----BEGIN RSA PUBLIC KEY-----\n#{base64}-----END RSA PUBLIC KEY-----" 

:とemulate the PKCS#1にこのバグレポートで提案されて何

です。

関連する問題