2011-10-31 250 views
4

我有一個C#應用程序來調用Java Web服務來驗證用戶的密碼。我想讓C#應用程序加密密碼,然後讓Java Web服務解密密碼。我已經完成了Java方面的代碼(解密代碼),但我無法弄清楚C#代碼來加密代碼。C#(加密)和Java(解密)之間的AES加密/解密

這是我的Java代碼...

public void validateUserPassword(String encryptedPassword) { 
    String algorithm = "AES"; 
    SecretKeySpec keySpec = null; 
    byte[] key = "<==OMGWTFBBQ!==>".getBytes(); 

    Cipher cipher = null; 

    cipher = Cipher.getInstance(algorithm); 
    keySpec = new SecretKeySpec(key, algorithm); 

    byte[] encryptionBytes = new sun.misc.BASE64Decoder().decodeBuffer(encryptedPassword);  
    cipher.init(Cipher.DECRYPT_MODE, keySpec); 
    byte[] recoveredBytes = cipher.doFinal(encryptionBytes); 
    String recovered = new String(recoveredBytes); 

    log.info("Encrypted password: " + encryptedPassword); 
    log.info("Dencrypted password: " + recovered); 
} 

這裏是我發現使用C#進行加密,但由於我的Java功能,所以我的Java Web服務是無法也不會產生相同的encrypion串解密它。

private void btnEncrypt_Click(object sender, EventArgs e) 
{ 
    string PlainText = "testing"; 
    string Password = "<==OMGWTFBBQ!==>"; 
    string Salt = "Kosher"; 
    string HashAlgorithm = "SHA1"; 
    int PasswordIterations = 2; 
    string InitialVector = "OFRna73m*aze01xY"; 
    int KeySize = 256; 
    string encryptedPassword; 

    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); 
    byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); 
    byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText); 

    PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations); 

    byte[] KeyBytes = DerivedPassword.GetBytes(KeySize/8); 
    RijndaelManaged SymmetricKey = new RijndaelManaged(); 
    SymmetricKey.Mode = CipherMode.CBC; 
    byte[] CipherTextBytes = null; 

    using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes)) 
    { 
     using (MemoryStream MemStream = new MemoryStream()) 
     { 
      using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)) 
      { 
       CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length); 
       CryptoStream.FlushFinalBlock(); 
       CipherTextBytes = MemStream.ToArray(); 
       MemStream.Close(); 
       CryptoStream.Close(); 
      } 
     } 
    } 
    SymmetricKey.Clear(); 
    encryptedPassword = Convert.ToBase64String(CipherTextBytes); 

    MessageBox.Show("Encrypted password: " + encryptedPassword); 
} 

我不介意改變我的Java Web服務解密的方式,以使其與我的C#應用​​程序一起工作。

+3

我是一個相當隨便SO用戶,我看問定期質詢的確切類型。請在SO中搜索以下內容:'aes c#java'或者現在您已經提出了該問題,請查看右欄中的相關問題。 –

+0

@Eric J有700多個答案,我不太確定你是否有資格成爲休閒用戶;) – Nate

+0

@Nate:也許我只是有一個Skeet自卑感。 –

回答

2

我試圖避免使用SSL,因爲我不知道該如何去那個方向去調用一個方法。

在任何情況下,我發現這個網站和代碼的作品非常漂亮。我能夠在C#端加密/散列用戶的密碼,並讓Java端將其轉換回來。

http://zenu.wordpress.com/2011/09/21/aes-128bit-cross-platform-java-and-c-encryption-compatibility/

另外還有一點也有偉大工程的例子這個其他網站...

http://blogs.msdn.com/b/dotnetinterop/archive/2005/01/24/java-and-net-aes-crypto-interop.aspx

4

在C#中,您正在使用DeriveBytes函數從密碼獲取密鑰,而在Java中,您直接將密碼用作密鑰。

這樣你顯然在雙方都有不同的關鍵。不要這樣做,在雙方使用相同的密鑰派生函數。

3

「你做錯了」。

如果需要通過發送一個密碼(如果例如Java系統需要通過對密碼又一方),只需使用你的C#應用​​程序和Java應用程序之間的SSL,而忘記了添加額外的加密。大多數人最終會遇到一個或多個實施錯誤,這會使系統容易受到攻擊。

如果Java方面只需要驗證C#客戶端是否有權訪問它,那麼很可能比發送明文密碼短語更好 - 這取決於您需要授權的方式。這也是您應該努力使用久經考驗的代碼的一個領域,因爲即使您對加密基礎知識有相當的理解,也很容易搞砸。

獲得Java和C#之間的AES通信工作(即按照原樣回答您的問題)是一項足夠有趣的任務(我會讓其他人處理:)),但是如果您想要安全性,請使用其他方法。

1

一般來說,密碼是散列而不是加密的(例如,使用SHA-2算法之一,例如SHA-256),所以如果我正確理解您的要求,那麼我將不得不異議您技術方法在這種情況下。

我同意另一個用戶,他建議使用已知的安全交換方法(如SSL/TLS)來進行端點之間的安全通信。

+0

是的,我想我對加密這個術語的使用在技術上可能並不正確,但我想每個人都會明白我在這裏要做的事情。 –