2016-11-22 97 views
2

我有我的C#服務器和我的Java客戶端,他們的通信是加密的,但當客戶端發送加密查詢時,服務器無法解密它,它可以但它完全不可讀,它像轉換字節數組爲字符串,完全不可讀的,這是對客戶端的加密:Java加密C#解密不會工作

public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException 
{ 
    byte[] encryptedBytes = null; 
    byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 
    final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING); 
    final byte[] keyData = Arrays.copyOf(passwordBytes, KEY_SIZE 
      /Byte.SIZE); 
    final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize()); 
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyData, "AES"), 
      new IvParameterSpec(ivBytes)); 
    encryptedBytes = cipher.doFinal(bytesToBeEncrypted); 
    return encryptedBytes; 
} 

而在服務器端解密:提前

internal string DecryptText(string inputString, Key k) 
{ 
    try 
    { 
     inputString = inputString.Replace("\0", ""); 
     byte[] decryptedBytes = null; 
     byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; 
     byte[] bytesToBeDecrypted = Convert.FromBase64String(inputString); 
     byte[] passwordBytes = Encoding.UTF8.GetBytes("azaz"); 
     passwordBytes = SHA256.Create().ComputeHash(passwordBytes); 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      using (RijndaelManaged AES = new RijndaelManaged()) 
      { 
       AES.KeySize = 256; 
       AES.BlockSize = 128; 

       var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000); 
       AES.Key = key.GetBytes(AES.KeySize/8); 
       AES.IV = key.GetBytes(AES.BlockSize/8); 
       AES.Padding = PaddingMode.None; 
       AES.Mode = CipherMode.CBC; 

       using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write)) 
       { 
        cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length); 
        cs.Close(); 
       } 
       decryptedBytes = ms.ToArray(); 
      } 
     } 
     return Encoding.UTF8.GetString(decryptedBytes); 
    } 
    catch (Exception ex) 
    { 
     throw new SystemException(ex.Message); 
    } 
} 

感謝

編輯在Java客戶端,這個函數調用AES_ENCRYPT函數:

public String EncryptText(String input) throws NoSuchAlgorithmException 
{ 
    byte[] bytesToBeEncrypted = input.getBytes(); 
    byte[] passwordBytes = Config.ServerKey.getBytes(); 
    MessageDigest md = MessageDigest.getInstance("SHA-256"); 
    passwordBytes = md.digest(passwordBytes); 
    byte[] bytesEncrypted = null; 
try { 
    bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes); 
} catch (NoSuchPaddingException ex) { 
    Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex); 
} catch (InvalidAlgorithmParameterException ex) { 
    Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex); 
} catch (InvalidKeyException ex) { 
    Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex); 
} catch (IllegalBlockSizeException ex) { 
    Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex); 
} catch (BadPaddingException ex) { 
    Logger.getLogger(CryptoClass.class.getName()).log(Level.SEVERE, null, ex); 
} 
    return Base64.getEncoder().encodeToString(bytesEncrypted); 
} 

編輯實現基本SslStream和驗證服務器端

private void Do() 
    { 
     int requestCount = 0; 
     string serverResponse = null; 
     string rCount = null; 
     string dataFromClient = null; 
     Byte[] sendBytes = null; 
     requestCount = 0; 
     Responder.Responder R = new Responder.Responder(); 
     while ((true)) 
     { 
      try 
      { 
       byte[] buffer = new byte[4]; 
       requestCount = requestCount + 1; 
       bool leaveInnerStreamOpen = true; 
       RemoteCertificateValidationCallback validationCallback = 
        new RemoteCertificateValidationCallback(ClientValidationCallback); 
       LocalCertificateSelectionCallback selectionCallback = 
        new LocalCertificateSelectionCallback(ServerCertificateSelectionCallback); 
       EncryptionPolicy encryptionPolicy = EncryptionPolicy.AllowNoEncryption; 
       _sslStream = new SslStream(clientSocket.GetStream(), 
        leaveInnerStreamOpen, validationCallback, selectionCallback, encryptionPolicy); 
       X509Certificate2 certificate = ServerCertificate.Servercertificate(); //method that has access to the embedded certificate 
       bool requireClientCertificate = true; 
       SslProtocols enabledSslProtocols = SslProtocols.Tls11 | SslProtocols.Tls12; 
       bool checkCertificateRevocation = true; 
       _sslStream.AuthenticateAsServer 
        (certificate, requireClientCertificate, enabledSslProtocols, checkCertificateRevocation); 
       buffer = new byte[4]; 
       int readBytes = _sslStream.Read(buffer, 0, 4); 
       if (readBytes == 0) 
        break; 
       int MessageSize = BitConverter.ToInt32(buffer, 0); 
       byte[] bufferreader = new byte[MessageSize]; 
       clientSocket.ReceiveBufferSize = MessageSize; 
       readBytes = _sslStream.Read(bufferreader, 0, MessageSize); 
       Console.WriteLine(Convert.ToString(MessageSize)); 
       rCount = Convert.ToString(requestCount); 
       dataFromClient = Encoding.ASCII.GetString(bufferreader); 
       byte[] outbuffer = new byte[4]; 
       serverResponse = R.Respond(dataFromClient, K, clientSocket); 
       sendBytes = Encoding.ASCII.GetBytes(serverResponse); 
       outbuffer = new byte[4]; 
       outbuffer = BitConverter.GetBytes(sendBytes.Length); 
       _sslStream.Write(outbuffer, 0, 4); 
       _sslStream.Flush(); 
       clientSocket.SendBufferSize = sendBytes.Length; 
       MessageBox.Show(serverResponse); 
       _sslStream.Write(sendBytes, 0, sendBytes.Length); 
       _sslStream.Flush(); 
      } 
      catch (Exception ex) 
      { 
       EndPointHandler.RemoveEndPoint(clientSocket); 
       clientSocket.Close(); 
       Console.WriteLine("User Server >> " + ex.ToString()); 
       Thread.CurrentThread.Abort(); 
      } 
     } 
     EndPointHandler.RemoveEndPoint(clientSocket); 
     Console.WriteLine("User Server >> " + "Client No:" + Convert.ToString(clNo) + " Stopped!"); 
    } 

    private bool ClientValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
    { 
     switch (sslPolicyErrors) 
     { 
      case SslPolicyErrors.RemoteCertificateNameMismatch: 
       Console.WriteLine("Client's name mismatch. End communication ...\n"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateNotAvailable: 
       Console.WriteLine("Client's certificate not available. End communication ...\n"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateChainErrors: 
       Console.WriteLine("Client's certificate validation failed. End communication ...\n"); 
       return false; 
     } 
     Console.WriteLine("Client's authentication succeeded ...\n"); 
     return true; 
    } 

    private X509Certificate ServerCertificateSelectionCallback(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) 
    { 
     return ServerCertificate.Servercertificate(); 
    } 
+0

你可以在java端解密你的數據嗎? –

+0

@StephenReindl是的,沒問題 –

+1

你的'passwordBytes'變量包含鍵和IV嗎?這不會導致你的問題,但你應該儘快改變。 IV應該隨機生成每個加密。 –

回答

2

在Java代碼中你有:

final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING); 

這可能意味着您正在使用PKCS5/7填充,除非你爲常量挑選名字真的很糟糕。

然而,在你的C#代碼,您有:

AES.Padding = PaddingMode.None; 

這顯然不是PKCS5/7填充......所以,你或許應該改變,要PaddingMode.PKCS7

編輯:也請不要忽視我對你的IV的評論。如果你想讓你的代碼真正值得使用,你應該自動爲每個加密生成IV並將其加到密文中。

也只是注意到,你以不同的方式派生你的關鍵數據。您在C#中使用PBKDF2 w/SHA1(Rfc2898DeriveBytes),但在Java中使用SHA256的一次迭代。你需要選擇一個或另一個。

+0

該死的我該怎麼看,謝謝,但現在服務器拋出:填充是無效的,不能被刪除...關於評論,我真的很感激它:) –

+0

@MatthiasHoste查看我的編輯:) –

+0

好的謝謝: ),但我的密碼真的很爛,我刪除了var key = new Rfc2898DeriveBytes(passwordBytes,saltBytes,1000);並使用passwordBytes鍵和iv,但它仍然會拋出相同的異常:( –