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

时间:2011-10-31 18:05:37

标签: c# java aes encryption

我有一个C#应用程序来调用Java Web服务来验证用户的密码。我想让C#应用程序加密密码,然后让Java Web服务解密密码。我已经完成了Java端的代码(解密代码),但我无法弄清楚加密代码的C#代码。

这是我的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服务无法解密它。

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#应用​​程序。

4 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

“你做错了”。

如果您需要发送密码短语(例如,如果java系统需要将密码短语传递给另一方),只需在您的C#应用​​程序和Java应用程序之间使用SSL,然后忘记关于添加额外的加密。大多数人最终会遇到一个或多个实施错误,这会使系统容易受到攻击。

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

让Java和C#之间的AES通信正常工作(即按原样回答你的问题)是一个非常有趣的任务(我会让其他人处理:)),但是如果你想要安全性,那么请使用另一种方法。

答案 2 :(得分: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

答案 3 :(得分:1)

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

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