简体   繁体   中英

AES encryption/decryption between C# (encryption) and Java (decryption)

I have a C# application to calls a Java web service to validate a user's password. I'd like to have the C# application encrypt the password and then have the Java web service decrypt the password. I have the code on the Java side done (the decryption code), but I can't figure out the C# code to encrypt the code.

Here is my Java code...

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);
}

Here is something I found to encrypt using C#, but it doesn't produce the same encrypion string as my Java function so my Java web service is unable to decrypt it.

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);
}

I don't mind changing the way my Java web service decrypts in order to make it work with my C# application.

In C# you are using a DeriveBytes function to get your key from the password, while in Java you are using the password directly as key.

This way you obviously have a different key on both sides. Don't do this, use the same key derivation function on both sides.

"You're doing it wrong".

If you need to send a passphrase through (if eg the java system needs to pass on the passphrase to yet another party), simply use SSL between your C# app and the Java app, and forget about adding additional encryption. Most people will end up with one or more implementation errors that will leave the system vulnerable.

If the Java side only needs to verify that the C# client is authorized to access it, there's most likely a better way than sending cleartext passphrases around - depending on what you need to authorize against. This is also an area where you should strive for using tried-and-tested code, as it's frustratingly easy to mess up even if you've got a decent understanding of crypto fundamentals.

Getting the AES communication between Java and C# working (ie, answering your question as-is) is an interesting enough task (that I'll let others handle :)), but if you want security then please use another method.

I'm trying to avoid using SSL as I don't what to have to go in that direction for one method call only.

In any case I found this site and the code works beautifully. I'm able to encrypt/hash the user's password on the C# side, and have the Java side convert it back.

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

There is also this other site that also has an example that works great...

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

Generally speaking, passwords are hashed rather than encrypted (for eg, using one of the SHA-2 algorithms, such as SHA-256), so if I'm understanding your requirement correctly then I would have to dissent with your technical approach in this case.

I concur with another user who suggested utilizing a known method of secure exchange (such as SSL/TLS) for the secure communication between endpoints.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM