2014-04-18 7 views
0

.NET Soap 웹 서비스에 로그인을 구현해야합니다. 이 웹 서비스는 방법이RSA. Java 암호화 .NET 암호 해독

AuthenticateUser(username, password) 

이고 암호는 RSA 공개 키로 암호화되어야합니다. 내가 뭘하려고 오전 아래 :

public static final String PUBLIC = "q/9CujExqL6rsMMO22WWIotoXDCw5KEmGQJqL9UJEfoErwZ9ZCm3OwMTSlAMSfoXEMA04Y1rhfYC3MtU/7dYEoREfsvOPGDBWanTKyMzv2otCfiURyQoghEdkhv3ipQQaaErT7lfBKobJsdqJlvxo4PCOUas2Z6YpoMYgthzTiM="; 
    public static final String EXPONENT = "AQAB"; 

    public static PublicKey getPublicKey() throws Exception{ 
     byte[] modulusBytes = Base64.decode(PUBLIC, 0); 
     byte[] exponentBytes = Base64.decode(EXPONENT, 0); 

     BigInteger modulus = new BigInteger(1, (modulusBytes)); 
     BigInteger exponent = new BigInteger(1, (exponentBytes)); 

     RSAPublicKeySpec spec = new RSAPublicKeySpec(modulus, exponent); 
     KeyFactory kf = KeyFactory.getInstance("RSA"); 
     return kf.generatePublic(spec); 
    } 

    public static byte[] encrypt(Key publicKey, String s) throws Exception{ 
     byte[] byteData = s.getBytes("UTF-8"); 
     Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, publicKey); 
     byte[] encryptedData = cipher.doFinal(byteData); 
     return encryptedData; 
    } 

    public static String arrayAsString (byte [] array){ 
     String p = ""; 
     for (int i = 0; i < array.length; i++) { 
      p += unsignedToBytes(array[i]); 
      if (i < array.length - 1) 
       p+= ","; 
     } 
     return p; 
    } 

    public static int unsignedToBytes(byte b) { 
     return b & 0xFF; 
    } 

    public static void main(String[] args){ 
     PublicKey publicKey = getPublicKey(); 
     byte [] encrypted = encode(publicKey, "passwordHere"); 
     String pass = arrayAsString(encrypted); 
     webservice.AuthenticateUser("testAdmin", pass); 
    } 

나는 또한

private static string publicKey = "<RSAKeyValue><Modulus>q/9CujExqL6rsMMO22WWIotoXDCw5KEmGQJqL9UJEfoErwZ9ZCm3OwMTSlAMSfoXEMA04Y1rhfYC3MtU/7dYEoREfsvOPGDBWanTKyMzv2otCfiURyQoghEdkhv3ipQQaaErT7lfBKobJsdqJlvxo4PCOUas2Z6YpoMYgthzTiM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; 
    private static UnicodeEncoding _encoder = new UnicodeEncoding(); 

    public static string Encrypt(string data) 
    { 
     var rsa = new RSACryptoServiceProvider(); 
     rsa.FromXmlString(publicKey); 
     var dataToEncrypt = _encoder.GetBytes(data); 
     var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray(); 
     var length = encryptedByteArray.Count(); 
     var item = 0; 
     var sb = new StringBuilder(); 
     foreach (var x in encryptedByteArray) 
     { 
      item++; 
      sb.Append(x); 

      if (item < length) 
       sb.Append(","); 
     } 

     return sb.ToString(); 
    } 



    public static string Decrypt(string data) 
    { 
     var rsa = new RSACryptoServiceProvider(); 
     var dataArray = data.Split(new char[] { ',' }); 
     byte[] dataByte = new byte[dataArray.Length]; 
     for (int i = 0; i < dataArray.Length; i++) 
     { 
      dataByte[i] = Convert.ToByte(dataArray[i]); 
     } 

     rsa.FromXmlString(privateKey); 
     var decryptedByte = rsa.Decrypt(dataByte, false); 
     return _encoder.GetString(decryptedByte); 
    } 

누군가가 내가 잘못 뭐하는 거지 어떤 생각을 가지고 있나요 웹 서비스 측면에서 .NET 코드가? 웹 서비스가 항상 나를 돌려주는 이유 AuthenticateUserResponse {AuthenticateUserResult = false; }

+0

웹 서비스 디버깅을 시도 했습니까? 서비스 측의 '복호화'출력은 클라이언트 측에서 암호화 된 데이터와 동일합니까? 이것은 제쳐두고, 나는 여기서 진짜 문제는 당신이 자신의 암호화 프로토콜을 사용하고 있다는 것입니다. 제 제안은 webservice가 SSL을 통해서만 액세스 할 수 있도록하는 것입니다. SSL을 통해 웹 서비스에 액세스 할 수있게되어 현재 사용중인 코드의 불안정성을 줄일 수 있습니다 (리플레이 방지 기능이 없음). – Iridium

+0

답장을 보내 주셔서 감사합니다. 불행히도 제 3 자 웹 서비스이기 때문에 출력을 검사 할 수없고 보안을 변경할 수 없으므로 웹 서비스에 액세스 할 수 없습니다. "당신은 자신의 암호화 프로토콜을 사용하고 있습니까?" –

답변

1

여기 문제는 암호화/복호화 프로세스 자체가 아니라 텍스트 인코딩과 관련이 있다고 생각합니다. 자바 측에서는 UTF-8로 인코딩 된 암호를 암호화하는 반면, .NET 측에서는 UTF-16 인 UnicodeEncoding을 사용합니다. 암호화하기 전에 Java 측에서 UTF-16을 사용해보십시오.

+0

시도했지만 여전히 작동하지 않습니다. 나는 두 가지가 있다고 생각하며 엉망이 될 수도 있습니다. 첫 번째 - 자바 바이트 부호, .NET 바이트 부호 없음. 내가 convertion - unsignedToBytes,하지만 어쩌면 내가 잘못된 장소에서합니까? 2 바이트 배열 엔디안. Java가 BigEndian을 사용한다는 것을 이해했기 때문에 .NET은 리틀 엔디안을 사용합니다. 그건 바이트 배열의 경우 이것은 단지 되돌려 진 배열이라는 것을 의미합니다. 암호화 결과를 되돌리려 고 시도했지만 작동하지 않습니다. 감사. –

+0

@GeorgyGobozov 여전히 인코딩 문제라고 생각합니다. Java의 기본 UTF-16 인코딩은 .NET의 UnicodeEncoding이 기대하지 않는 바이트 순서 마크를 추가하고 출력을 손상시킵니다. Java에서 인코딩으로'UTF-16LE'을 사용해야합니다. Java에서 문자열을 성공적으로 인코딩 할 수 있었고 암호를 Java의 바이트 배열로 변환하는 데 사용 된이 인코딩을 사용하여 .NET에서 디코딩 할 수있었습니다. – Iridium

+0

그게 뭐야! UTF-16LE에서 UTF-8을 바꿨습니다. 도와 줘서 고마워, 고마워! –