2013-08-06 3 views
10

웹 서비스 팀에서 작성한이 C# 코드는 내가 사용하려고하는 일부 웹 서비스를 제공합니다. 웹 서비스가 암호를 해독하는 방법을 알 수 있도록 암호를이 코드로 암호화해야합니다.C# RSACryptoServiceProvider를 자바 코드로 변환

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

내가 그 웹 서비스가 제대로 암호를 해독 할 수 있기 때문에 자바 코드에 그 #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")))); 

, 나는이 오류를 받고 있어요 : "데이터의 암호를 해독 할 수는 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 문서에 따르면 두 번째 인수가 false 일 때 암호문은 PKCS # 1 v1.5 패딩을 사용합니다. 방망이에서 벗어나 암호 사양이 잘못되었습니다.

RSA/ECB/PKCS1PADDING을 대신 시도하십시오.

두 번째 코드 예에서 키 재료를 많이 변환하면 암호가 손상되어 실제 키보다 많은 키 자료가 있다고 생각하여 메시지를 너무 길게 만듭니다 (오류를 유발 함) 뿐만 아니라 상대방의 복호화 암호에 대해 이해할 수 없게된다. 직접 바이트 배열로 변환하고 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

현재 Commons Codec을 사용하고 있습니다. 처음에는 Spring의 코덱을 사용 했으므로 문제가 될 것이라고 생각하여 Commons Codec으로 전환했지만 같은 결과가 나타납니다. – limc