C#(加密)和Java(解密)之间的AES加密/解密

问题描述:

我有一个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自卑感。 –

我试图避免使用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

在C#中,您正在使用DeriveBytes函数从密码获取密钥,而在Java中,您直接将密码用作密钥。

这样你显然在双方都有不同的关键。不要这样做,在双方使用相同的密钥派生函数。

“你做错了”。

如果需要通过发送一个密码(如果例如Java系统需要通过对密码又一方),只需使用你的C#应用​​程序和Java应用程序之间的SSL,而忘记了添加额外的加密。大多数人最终会遇到一个或多个实施错误,这会使系统容易受到攻击。

如果Java方面只需要验证C#客户端是否有权访问它,那么很可能比发送明文密码短语更好 - 这取决于您需要授权的方式。这也是您应该努力使用久经考验的代码的一个领域,因为即使您对加密基础知识有相当的理解,也很容易搞砸。

获得Java和C#之间的AES通信工作(即按照原样回答您的问题)是一项足够有趣的任务(我会让其他人处理:)),但是如果您想要安全性,请使用其他方法。

一般来说,密码是散列而不是加密的(例如,使用SHA-2算法之一,例如SHA-256),所以如果我正确理解您的要求,那么我将不得不异议您技术方法在这种情况下。

我同意另一个用户,他建议使用已知的安全交换方法(如SSL/TLS)来进行端点之间的安全通信。

+0

是的,我想我对加密这个术语的使用在技术上可能并不正确,但我想每个人都会明白我在这里要做的事情。 –