web-dev-qa-db-ja.com

文字列からのRSA公開鍵の作成

私は、1024 RSAを使用してこのテスト公開鍵を生成し、それを別のコーディングプラットフォームでDERおよびBase64にエンコードしました。 Android/Eclipseでキーを文字列にコピーし、KeyFactoryを使用してそれを公開キーに変換しようとしています。何をしようとしてもInvalidKeySpecExceptionが出続けます。どんなアドバイスでもいただければ幸いです。

     private void prepKeys() {
         String AppKeyPub = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5" +
"5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ" +
"OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";

        // create the key factory          
            try {
                KeyFactory kFactory = KeyFactory.getInstance("RSA");  
                // decode base64 of your key
                byte yourKey[] =  Base64.decode(AppKeyPub,0);
                // generate the public key
                X509EncodedKeySpec spec =  new X509EncodedKeySpec(yourKey);
                PublicKey publicKey = (PublicKey) kFactory.generatePublic(spec);

            System.out.println("Public Key: " + publicKey);  

            } catch (Exception e) {
                // TODO Auto-generated catch block  
                e.printStackTrace(); 
            }

         }
15
raximus

あなたが持っているキーは、Javaが受け入れるSubjectPublicKeyInfo構造ではなく、PKCS#1形式です。PKCS#1は、RSAパラメータのみのエンコーディングであり、アルゴリズム識別子などがありません。SubjectPublicKeyInfoはPKCSを使用します内部的には#1-とにかくRSA公開鍵用。

PKCS#1公開鍵はSubjectPublicKeyInfo構造の最後にあるため、バイトにプレフィックスを付けるだけで、RSA SubjectPublicKeyInfoになります。このソリューションは、Bouncy Castleなどの追加のライブラリがなくても簡単に実行できます。したがって、外部ライブラリなしで移動する必要がある場合は、私の答え here を確認できます。


または、単純なBERデコーダーを作成して、構造を2つのBigInteger値にデコードすることもできます。構造自体 それほど複雑ではありません ですが、BER/DERの長さのエンコーディングは、ある程度慣れが必要です。

ただし、Bouncy Castle(軽量API)を使用して問題を解決することもできます。

String publicKeyB64 = "MIGHAoGBAOX+TFdFVIKYyCVxWlnbGYbmgkkmHmEv2qStZzAFt6NVqKPLK989Ow0RcqcDTZaZBfO5"
        + "5JSVHNIKoqULELruACfqtGoATfgwBp4Owfww8M891gKNSlI/M0yzDQHns5CKwPE01jD6qGZ8/2IZ"
        + "OjLJNH6qC9At8iMCbPe9GeXIPFWRAgER";
// ok, you may need to use the Base64 decoder of bouncy or Android instead
byte[] decoded = Base64.getDecoder().decode(publicKeyB64);
org.bouncycastle.asn1.pkcs.RSAPublicKey pkcs1PublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey.getInstance(decoded);
BigInteger modulus = pkcs1PublicKey.getModulus();
BigInteger publicExponent = pkcs1PublicKey.getPublicExponent();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulus, publicExponent);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey generatedPublic = kf.generatePublic(keySpec);
System.out.printf("Modulus: %X%n", modulus);
System.out.printf("Public exponent: %d ... 17? Why?%n", publicExponent); // 17? OK.
System.out.printf("See, Java class result: %s, is RSAPublicKey: %b%n", generatedPublic.getClass().getName(), generatedPublic instanceof RSAPublicKey);

ご覧のとおり、実際にはBouncy Castle内のASN.1/BERデコーダー機能全体でバックアップされていますが、インターフェースとして必要なのは単一のクラスのみです。


Base 64デコーダーを the Android specific one(Android.util.Base64 。このコードは、同等のJavaランタイムでテストされました。

11
Maarten Bodewes