2012-03-12 24 views
0

Java Webサービスは、PublickKey(PEM Stringとして)を取得し、PublicKeyで暗号化されたWebサービスにデータを送信するためのメソッドを公開します。サービスのクライアントは.NETアプリです。 .NETクライアントのPublicKeyを取得 keytool.exeが使用-genkey -alias ABC -keystore sample.ks -storetype JCEKS -storepass XYZ.NETでの公開鍵暗号化とJavaによる復号化

以下のようにJava側にストアは、鍵ペア(RSA 1024ビット)で作成され公開鍵を使用して機密データを暗号化し、暗号化されたデータでWebサービスを呼び出します。 Webサービスは、キーストアから入手可能な秘密鍵を使用してデータを復号し、その内容をDBに格納します。クライアントの互換性のためにWS-Security機能を使用することはできません。

webserviceはキーストアを読み取り、公開鍵をPEM文字列として返します。 .NETクライアントはPublicKeyをPEM文字列として取得し、これを使用してRSACryptoServiceProviderを作成します。これは問題なく動作します。その後、データを暗号化してJava Webサービスに戻します。

Javaサービスはデータを復号化しますが、問題はガベージ(ASCIIデータではありません)をプリントアウトすることです。例外はありません。

私はここのコードの(簡体字)スニペット

.NETクライアント側

var registrationService = new RegistrationService(); 
    var pKey = registrationService.getPublickey(); 
    //pKey is a PEM String 
    X509Certificate2 cert = new X509Certificate2(ASCIIEncoding.ASCII.GetBytes(pKey)); 

    RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PublicKey.Key; 

    var encryptedMsg = rsa.Encrypt(Encoding.UTF8.GetBytes("Secret Data"), false); 
    var encoded_msg = Convert.ToBase64String(encryptedMsg); 

    registrationService.submitRegistration(encoded_msg); 

のJavaサイドを添付しています注意すべき

public void submitRegistration(String inputData) 
    { 
    //Decoding the encoded and encrypted message in the webservice  
    PrivateKey privateKey = getPrivateKeyFromKeyStore("abc"); 
    //I know I am using JDK proprietary classes, but I can easily replace this 
    byte[] dataInBytes = new Base64Decoder().deodeBuffer(inputData) 

    Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 
    cipher.init(Cipher.DECRYPT_MODE, privateKey); 
    byte[] decryptedData = cipher.doFinal(dataInBytes);   
    String original = new String(decryptedData, "UTF-8"); 
    System.out.println("Original Data : " + original); 
} 
    public String getPublicKey() 
    { 
    Certificate cert = getKeyStore().getCertificate("abc"); 
    byte[] encodedCert = cert.getEncoded(); 
    StringWriter sw = new StringWriter(); 
    sw.write("-----BEGIN PUBLIC KEY-----"); 
    sw.write(new Base64Encoder().encode(encodedCert)); 
    sw.write("-----END PUBLIC KEY-----"); 
    return sw.toString(); 
    } 
+1

あなたはまだこのサイトを検索していませんか?私は何度も非常によく似た質問をしてきました。 –

+0

はい、私はサイトを検索しました。同様の質問が私が直面している問題に対処する答えを見つけることができなかったことがわかります。また、私が持っている微妙な違いは、ファイルからの読み込みに対してWebサービス経由でPublicKeyを取得する必要があることです。他の誰かが似たような問題を抱えていると思います。 – Kris

+4

.NET側でPKCS#1パディングを使用していますが、Java側ではパディングを使用していません。 NoPaddingをPKCS1PADDINGに変更してください –

答えて

2

ことの一つは、あなたがしているということですJava側では「NOPADDING」を使用しますが、.NETではPKCS1Paddingを使用しています。

PKCS1パディングパッドは、高位エンドで0x00 0x02の平文であるため、復号側が正しい秘密鍵を使用しているかどうかを確認する方法も提供します。しかし、0x00 0x02で始まるプレーンテキストへの間違ったキー解読の機会が少なくとも1/65536であるため、このチェックは完全に間違った秘密鍵を検出することはできません。あなたのケースでは、間違ったキーを使用し、平文がこのチェックに失敗したので、あなたは例外を受け取りました。今、NOPADDINGを指定すると、すべての平文が有効であると言われ、それ以上の検査はアプリケーションによって行われます。

+0

暗号化テキストの上に安全な完全性チェック(署名が良いだろう)を作成することは、常に意味があることを誰もが分かります。 –

関連する問題