2013-08-06 12 views
10

Webサービスチームによって書かれたこのC#コードは、私が使用しようとしているWebサービスを公開しています。私のパスワードはこのコードで暗号化されている必要があります。そのため、Webサービスはそのコードを解読する方法を知っています。C#RSACryptoServiceProviderをJAVコードに翻訳する

using(RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
{ 
    rsa.FromXmlString(publicKey); 
    byte[] plainBytes = Encoding.Unicode.GetBytes(clearText); 
    byte[] encryptedBytes = rsa.Encrypt(plainBytes, false); 
    return Convert.ToBase64String(encryptedBytes); 
} 

私は、このWebサービスを利用するためにJavaを使用していて、そのWebサービスが適切に自分のパスワードを解読することはできませんので、今、私は、Javaコードにその#Cコードを変換する問題を抱えています。私は間違って何をしました

// my clear text password 
String clearTextPassword = "XXXXX"; 

// these values are provided by the web service team 
String modulusString = "..."; 
String publicExponentString = "..."; 

BigInteger modulus = new BigInteger(1, Base64.decodeBase64(modulusString.getBytes("UTF-8"))); 
BigInteger publicExponent = new BigInteger(1, Base64.decodeBase64(publicExponentString.getBytes("UTF-8"))); 

KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); 
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); 

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); 
cipher.init(Cipher.ENCRYPT_MODE, publicKey); 

String encodedEncryptedPassword = new String(Base64.encodeBase64(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

- :

は、ここに私の現在の失敗したのか?どうもありがとう。

2013年8月7日 - UPDATE

私はthis websiteを読んでいたし、私は私のモジュラス値と公開指数値が六角になっていないことに気づきました。だから、コードを少し修正して、@DevのようにRSA/ECB/PKCS1PADDINGで試してみました。

// my clear text password 
String clearTextPassword = "XXXXX"; 

// these are the actual values I get from the web service team 
String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; 
String publicExponentString = "AQAB"; 

Base64 base64Encoder = new Base64(); 

String modulusHex = new String(Hex.encodeHex(modulusString.getBytes("UTF-8"))); 
String publicExponentHex = new String(Hex.encodeHex(publicExponentString.getBytes("UTF-8"))); 

BigInteger modulus = new BigInteger(modulusHex, 16); 
BigInteger publicExponent = new BigInteger(publicExponentHex); 

KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 

RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, publicExponent); 
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); 

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
cipher.init(Cipher.ENCRYPT_MODE, publicKey); 

String encodedEncryptedPassword = new String(base64Encoder.encode(cipher.doFinal(clearTextPassword.getBytes("UTF-8")))); 

私はWebサービスを打つとき、私はこのエラーを取得しています:「のデータを復号化するには、128バイトのこの係数の最大値を超えています。」クリアテキストパスワードがまだ適切に暗号化されていないようです。

ご迷惑をおかけして申し訳ございません。ありがとう。

2013年8月9日 -

ソリューションは、私は以下の私の最終作業溶液を掲載しました。

答えて

8

が見つかりました。

String modulusString = "hm2oRCtP6usJKYpq7o1K20uUuL11j5xRrbV4FCQhn/JeXLT21laKK9901P69YUS3bLo64x8G1PkCfRtjbbZCIaa1Ci/BCQX8nF2kZVfrPyzcmeAkq4wsDthuZ+jPInknzUI3TQPAzdj6gim97E731i6WP0MHFqW6ODeQ6Dsp8pc="; 
String publicExponentString = "AQAB"; 

byte[] modulusBytes = Base64.decodeBase64(modulusString); 
byte[] exponentBytes = Base64.decodeBase64(publicExponentString); 
BigInteger modulus = new BigInteger(1, modulusBytes); 
BigInteger publicExponent = new BigInteger(1, exponentBytes); 

RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent); 
KeyFactory fact = KeyFactory.getInstance("RSA"); 
PublicKey pubKey = fact.generatePublic(rsaPubKey); 
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); 
cipher.init(Cipher.ENCRYPT_MODE, pubKey); 

byte[] plainBytes = clearTextPassword.getBytes("UTF-16LE"); 
byte[] cipherData = cipher.doFinal(plainBytes); 
String encryptedStringBase64 = Base64.encodeBase64String(cipherData); 
+0

私はこれが暗号の代わりにログインプロトコルの問題になるだろうと感じました。私たちは他のすべてをカバーしました。あなたがそれを理解してうれしいです。 – Dev

+0

'Encoding.Unicode.GetBytes(String)'が見えたら、UTF-16LEではなく、UTF-8であると思います。 – Dev

+0

ありがとうございます - 私の問題を解決しました。 NETの人々は、UTF-8ではないことをよく認識していないEncoding.Unicode.GetBytes/Encoding.Unicode.GetStringを使用するように見えます。 – mvmn

1

RSACryptoServiceProvider.EncryptのMSDNドキュメントによると、2番目の引数がfalseのとき、暗号はPKCS#1 v1.5パディングを使用します。あなたの暗号仕様が間違っています。

代わりにRSA/ECB/PKCS1PADDINGを試してください。

2番目のコード例で鍵素材を多く変換していますが、暗号化が終わって実際の鍵素材より多くの鍵素材があると思われ、メッセージが長すぎると思われます(エラーが発生します)他方で復号化暗号には理解できない。バイト配列に直接変換し、それらをBigIntegerに渡します。

String modulusString = "..."; 
String publicExponentString = "..."; 

byte[] mod = Base64.decodeBase64(modulusString); 
byte[] e = Base64.decodeBase64(publicExponentString); 

BigInteger modulus = new BigInteger(1, mod); 
BigInteger publicExponent = new BigInteger(1, e); 
+0

私は "RSA/ECB/PKCS1PADDING"と暗号のための "RSA"を試しました。どちらも失敗しました。 – limc

+0

@limc 'Base64'は誰ですか? – Dev

+0

私は現在コモンズコーデックを使用しています。私は当初、Springのコーデックを使用していましたが、問題があると思ってCommons Codecに切り替えましたが、同じ結果が得られます。 – limc