Divergence in encrypting and decrypting in Java and C# Aes algorithm

Asked

Viewed 2,393 times

14

I have two projects in Java and another in C# where the two communicate with each other, and one of the functions and encrypt and decrypt the confidential information between them, using aes algorithm, I’m trying to encrypt with C# as follows.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Aes_Example
{
    class AesExample
    {
        // Mensagem que sera criptografada.
        const string mensagem = "Mensagem que sera criptografada.";
        // Senha definida da operadora.
        const String chave = "uexDPnPr";

        public static void Main()
        {
            try
            {
                byte[] pwdBytes = Encoding.UTF8.GetBytes(chave);
                byte[] keyBytes = new byte[0x10];
                int len = pwdBytes.Length;
                if (len > keyBytes.Length)
                {
                    len = keyBytes.Length;
                }

                Array.Copy(pwdBytes, keyBytes, len);

                using (Aes myAes = Aes.Create("AES"))
                {
                    myAes.Key = keyBytes;

                    byte[] encrypted = EncryptStringToBytes_Aes(mensagem, myAes.Key, myAes.IV);
                    string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);

                    String TESTE = Convert.ToBase64String(encrypted);
                    Console.WriteLine("Original:   {0}", mensagem);
                    Console.WriteLine("Criptografado: {0}", Convert.ToBase64String(encrypted));
                    Console.WriteLine("Descriptografado: {0}", roundtrip);
                    Console.ReadKey();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;
            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting  stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }
    }
}

It returns me an encrypted string like this,

NElQHsXIpc+bHezzad/Ubzj94+1YKomH5LwmlDUseQtGs9veFPmUexy82KJTsBVD

And on the Java side I have.

package Teste;

import java.security.Key;
import java.security.MessageDigest;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;

public final class Criptografia {

    private static final String ALGORITMO = "AES";

    public static String criptografar(String mensagem, String chave) throws Exception {

        final Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, chave);

        final byte[] criptografado = cipher.doFinal(mensagem.getBytes());

        return StringUtils.trim(Base64.encodeBase64String(criptografado));
    }

    public static String descriptografar(String mensagem, String chave) throws Exception {

        final Cipher cipher = getCipher(Cipher.DECRYPT_MODE, chave);

        final byte[] descriptografado = cipher.doFinal(Base64.decodeBase64(mensagem));

        return new String(descriptografado, "UTF-8");
    }

    private static Cipher getCipher(final int encryptMode, final String chave) throws Exception {

        final Cipher cipher = Cipher.getInstance(ALGORITMO);
        cipher.init(encryptMode, buildKey(chave));

        return cipher;
    }

    private static Key buildKey(String chave) throws Exception {

        final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");

        final byte[] key = Arrays.copyOf(messageDigest.digest(chave.getBytes("UTF-8")), 16);

        return new SecretKeySpec(key, ALGORITMO);
    }

    /**
     * Classe de exemplo de utilizacao. Futuramente passar para o padrao JUnit.
     * 
     * @param args
     *            nao precisa informar
     *
     * @throws Exception
     *             erro na criptografia
     */
    public static void main(String[] args) throws Exception {

        // Mensagem que sera criptografada.
        final String mensagem = "Mensagem que sera criptografada.";

        // Senha definida da operadora.
        final String chave = "uexDPnPr";

        // Valor criptografado.
        String criptografado = Criptografia.criptografar(mensagem, chave);
        System.out.printf("Valor criptografado: '%s' %n", criptografado);

        // Valor original.
        String descriptografado = Criptografia.descriptografar(criptografado, chave);
        System.out.printf("Valor descriptografado: '%s'", descriptografado);
    }

}

Generating the cryptography.

JGTfV+CntuSutHK0LLeZix9Teu87ynjpJN8d3OaQdWge6yN0stn7/1I5KmMJEFYk

The difficulty here is to find a way to match the encryption generated in C# where the java part I can’t change because it’s the client, I’ve come to see some issues about this in the gringo stackoverflow, but everyone I’ve seen has not understood how to fix this.

Summarizing; I need the encryption generated in C# to be identical to the one generated in java.

For message = "Message to be encrypted.";

and the key = "uexDPnPr";

I have today.

In the C#

NElQHsXIpc+bHezzad/Ubzj94+1YKomH5LwmlDUseQtGs9veFPmUexy82KJTsBVD

This C# encryption has to be true to the java below.

and in Java.

JGTfV+CntuSutHK0LLeZix9Teu87ynjpJN8d3OaQdWge6yN0stn7/1I5KmMJEFYk

  • 1

    It appeared in the suggested ones, I don’t know if you’ve seen it or if it helps in any way, but it’s worth the suggestion: https://answall.com/questions/12206/algorithmo-cryptography-commutam-entre-java-e-c?rq=1

  • @diegofm, had seen yes, but uses another type of encryption.

  • 3

    Goku, take a look in Soen’s reply. Try this one RijndaelManaged with BlockSize = 128, aesEncryption.KeySize = 256 and 32 byte (256 bit) keys. If it works give me a tap I write a reply.

  • @Anthonyaccioly, I had seen this, but I couldn’t make it equal to the encryption, if I get a solution I’m grateful and you get the bonus.

  • You want them both strings produced (C# and Java) are exactly the same? Or are you having difficulty getting both systems to communicate?

  • @Gomiero, Let the string generated in C# be equal to Java.

  • Without access to Java code, you probably can’t do this because of Initialization vector (in its code C#: myAes.IV), that would have to be the same in both implementations. The IV is usually random (Salt ()) and if you fix it directly in the codes (C# and Java), it will greatly reduce the security of the algorithm.

  • @Gomiero, if I receive the java IV as a parameter I could do?

  • Yes! If all parameters of the algorithm (eg: IV, block size, key size) are the same, you can always generate the same string with any programming language. However, I believe you need to assess the context of the system as a whole well (e.g. IV will transit between Java and C# applications over an insecure connection? ) to avoid security issues :)

  • @Gomiero, I made a Cipher.getIV(); and it always returns me NULL.

  • 2

    The instance (cipher) is using the pattern ECB, without IV (INSECURE!). Changing the startup to, for example: Cipher.getInstance("AES/CBC/PKCS5Padding") (CBC mode, default in . NET), the getIV() will work (these strings are in the documentation of Cipher). There are other alternatives (such as changing the C# code to use the ECB mode and "zeroing" the IV), however, they are bad programming practices and I do not recommend using them :)

  • I don’t understand why buildKeys (which will generate a hash and modify the key) in Java. I suggest taking the call to buildKeys and forcing a debug message just before calling the encryption functions containing the key and the message (both in C# and Java); both variables have to have the same content and size.

  • @osmarcf, thanks for the tip, but I guess you didn’t read the question completely, the java side is client.

  • I’m sorry, I didn’t get that information! Anyway, just turn my suggestion (multiply by -1): take the first 16 bytes of the SHA-256 hash calculation of the key (in UTF-8) in C# before encrypting (which is what buildKeys of Java is doing). You are giving the copy, with the Len of 16 (0x10), but you are not doing this deopis of calculating the SHA-256. A hash of a text must be equal if the input text and the algorithm are equal. Even though it is code that you cannot change, you can compile it locally to test (and put debug messages)?

  • @osmarcf , I didn’t quite understand how that would be.

  • @osmarcf, it is not possible to multiply -1 the Byte range is 0 to 255, what would do this is the sbyte but it is incompatible with the Key which is byte type .

  • 1

    Unfortunately the joke about multiplying by -1 did not work (to reverse the way you think). key: byte[] pwdBytes = Encoding.UTF8.GetBytes(chave); for the code that generates the SHA-256 hash from it: ;using (SHA256 hash = SHA256Managed.Create()) {&#xA; Encoding enc = Encoding.UTF8;&#xA; byte[] pwdBytes = hash.ComputeHash(enc.GetBytes(chave));&#xA;} I got it from (http://stackoverflow.com/questions/16999361/obtain-sha-256-string-of-a-string) I don’t have a C# compiler here to test, I hope it works!

  • @osmarcf, I’ve seen this before. It doesn’t work.

Show 13 more comments

3 answers

19


First let’s make your code work

There are three main differences between the C# and Java implementations of your question:

The key

The Java-side algorithm is computing a hash (SHA-256) of the original key and selecting the first 128 bits (16 bytes) of the result as the key of the AES algorithm. The choice is quite peculiar, but it can be imitated on the C side#:

static byte[] BuildKey(string chave)
{
    SHA256Managed sha256algorithm = new SHA256Managed();
    byte[] originalKeyBytes = Encoding.UTF8.GetBytes(chave);
    byte[] keyBytes = sha256algorithm.ComputeHash(originalKeyBytes);
    // primeiros 16 bytes do SHA-256            
    Array.Resize(ref keyBytes, 16);

    return keyBytes;
}

The cipher

The encryption process goes far beyond the algorithm. When specifying a cipher we also need to talk about the mode of operation and of the technique of padding (extra bit fill inside a block). Other parameters to consider are the block and key size.

On the Java side, Cipher.getInstance("AES")is equivalent to specification string AES/ECB/PKCS5Padding (128). By the way, this is a detail of implementation. It is always recommended to use the full string.

This means that when you request a cipher in the AES standard Java will give you a specific algorithm (Rijndael), in mode Electronic Codebook (ECB) with padding of type PKCS#5 (actually PKCS#7, but that’s another matter) and block and key size = 128 bits.

On the side of C# o standard mode of operation is Cipher-block chaining (CBC) and padding pattern PKCS#7

In order for the result to be the same on both sides we need to instruct them to use the same "configuration". Since you don’t want to change anything on the Java side, here’s the solution on the C side#:

static SymmetricAlgorithm GetCipher(byte[] key)
{
    Aes aesAlg = Aes.Create("AES");
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.ECB;
    aesAlg.Padding =  PaddingMode.PKCS7;  
    aesAlg.Key = key;

    return aesAlg;
}

The vast majority of these properties have values default reasonable; in practice the only two amendments that are making a difference in this example are the Mode = CipherMode.ECB and Key = key. That said, in code related to encryption I prefer to be explicit whenever possible.

Finally we can use the above setting during calls to encrypt / decrypt the text:

using (SymmetricAlgorithm aesAlg = GetCipher(Key))
{
    ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
    // Ou
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); 
    // [...] Restante do seu código...
 }

Et voilá

Original:   Mensagem que sera criptografada. 
Criptografado: JGTfV+CntuSutHK0LLeZix9Teu87ynjpJN8d3OaQdWge6yN0stn7/1I5KmMJEFYk
Descriptografado: Mensagem que sera criptografada.

Functional example in Ideone


Now let’s try to understand a few more things

What is initialization vector?

The great weakness of the way ECB is that equal input blocks always generate equal outputs. This means that somehow part of the original structure is conserved. With some knowledge of cryptanalysis and the structure / original content it is possible to extract enough information from the encrypted content.

Other modes of operation use some "state" during transformation (e.g., previous block information, a counter, "disposable" random blocks, etc.) to produce variations in encrypted content. In general this hinders the parallelization of transformation operations into a trade-off for greater security.

The initialization vector (IV) is nothing more than the "state" to be used initially. This value should be as random as possible; reuse the initialization vector can compromise application security.

In accordance with the comments on the question and the answer of Mark, Java and C# adopt different strategies regarding IV.

How a initialization vector makes no sense for the operation mode ECB Java does nothing about IV, i and.., cipher.getIV() == null. If you chose a mode of operation in which the IV made sense (e. g. CBC) Java would generate a random value.

Already in the C# one IV random is always generated by default, but it is completely ignored in operation mode ECB, making no difference to the final result of the cipher.

Aes aesAlg = Aes.Create("AES");
// IV aleatório toda vez que você instancia  `Aes`
Console.WriteLine(string.Join(", ", aesAlg.IV));

Anyway, it costs nothing to "zero" the IV explicitly:

aesAlg.IV = new byte[16];

So this solution is weak?

Yes! For reasons explained above, outside very specific contexts (single blocks of information without great semantic relevance), operate in mode ECB is a lousy idea! From a security point of view this type of solution is quite amateur! Serious, do not try to find reasons to justify the use of ECB.

Wikipedia - Fraqueza do ECB

A minimally satisfactory solution would be operate in mode CBC, generate a initialization vector and share it with the client. A better idea would still be to use a solution of authenticated encryption. In most cases however, throw the responsibility of encryption out of your code (e. g., TLS) is the easiest and correct solution. If you are using an application server the problem becomes infrastructure (i.e., get a certificate and configure https protocol support). If you are not so lucky, it is always possible to use a library common to Java and C# as Bouncy Castle.

But the code on the Java side is external/proprietary/obfuscated

You can always do something. Even if it’s something to contact the customer and tell them to read this post. The main point here is that all this manual encryption effort is not helping your application’s security much.

As the points above, you earn more by exchanging information via https than by trying to reinvent the wheel. If the client application has an "insecure" mode of operation (no encryption) how about suggesting it to it? Use insecure mode over https.

Otherwise I would assess whether the exchange of information between applications really has to be secure. In that case I would volunteer to write something halfway between your application and the customer to ensure real security. For example, you can write a client-side layer to talk to your C# application securely.

If your client really is completely irreducible you can even keep all this logic with AES/ECB on his side, as long as this is just an encryption scheme on-site. From his net out I would at least wrap the messages in a better thought out security scheme.

In short: The code problem is solved. The security problem is still pending.


References:

  1. Wikipedia - Operating mode (cryptography)
  2. Wikipedia - Padding
  3. Java Cryptography Architecture (JCA) Reference Guide - The Cipher Class
  4. Soen - AES/CBC/Pkcs5padding vs AES/CBC/Pkcs7padding with 256 key size performance java
  5. MSDN - Symmetricalgorithm.Mode Property
  6. MSDN - Symmetricalgorithm.Padding Property
  7. Cipher (Java Platform SE 8 )
  8. Crypto - Why shouldn’t I use ECB Encryption?
  9. Soen - How to Choose an AES Encryption mode (CBC ECB CTR OCB CFB)?
  10. Is AES ECB mode Useful for Anything?
  11. Crypto Fails - Crypto Noobs #1: Initialization Vectors
  12. Javamex - Using block modes and initialisation Vectors in Java
  13. Wikipedia - Authenticated Encryption
  14. Wikipedia - Transport Layer Security
  15. The Legion of the Bouncy Castle

P.S.: I’m sorry if I broke any of the C code conventions. That’s not a language I use on a day-to-day basis. Feel free to edit my reply and fix / improve everything you find convenient.

  • 3

    I support this answer. Who uses ECB, does not know what to do.

  • 2

    Despite not mastering the subject, the answer is excellent. Even being quite lay in cryptography, I managed to understand his point of view. This type of response greatly increases the quality of the site! :)

  • 1

    +1 for ECB Penguin :)

11

In the . NET code, only one change. Initializing IV, always with the same value:

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;

    namespace Aes_Example
    {
    class AesExample
    {
        // Mensagem que sera criptografada.
        const string mensagem = "Mensagem que sera criptografada.";
        // Senha definida da operadora.
        const String chave = "uexDPnPr";

        public static void Main()
        {
            try
            {
                byte[] pwdBytes = Encoding.UTF8.GetBytes(chave);
                byte[] keyBytes = new byte[0x10];
                int len = pwdBytes.Length;
                if (len > keyBytes.Length)
                {
                    len = keyBytes.Length;
                }

                Array.Copy(pwdBytes, keyBytes, len);

                using (Aes myAes = Aes.Create("AES"))
                {
                    myAes.Key = keyBytes;
                    myAes.IV = new byte[0x10];//IV é zeroooooooooooooooo

                    byte[] encrypted = EncryptStringToBytes_Aes(mensagem, myAes.Key, myAes.IV);
                    string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);

                    String TESTE = Convert.ToBase64String(encrypted);
                    Console.WriteLine("Original:   {0}", mensagem);
                    Console.WriteLine("Criptografado: {0}", Convert.ToBase64String(encrypted));
                    Console.WriteLine("Descriptografado: {0}", roundtrip);
                    Console.ReadKey();
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;
            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }

            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting  stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            return plaintext;
        }
    }
}

In Java:

    package teste;

    import java.security.Key;
    import java.util.Base64;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;

    public final class Criptografia {

    private static final String ALGORITMO = "AES/CBC/PKCS5Padding";

    public static String criptografar(String mensagem, String chave) throws Exception {

        final Cipher cipher = getCipher(Cipher.ENCRYPT_MODE, chave);

        final byte[] criptografado = cipher.doFinal(mensagem.getBytes("UTF-8"));

        return Base64.getEncoder().encodeToString(criptografado);
    }

    public static String descriptografar(String mensagem, String chave) throws Exception {

        final Cipher cipher = getCipher(Cipher.DECRYPT_MODE, chave);

        final byte[] descriptografado = cipher.doFinal(Base64.getDecoder().decode(mensagem));

        return new String(descriptografado, "UTF-8");
    }

    private static Cipher getCipher(final int encryptMode, final String chave) throws Exception {

        final Cipher cipher = Cipher.getInstance(ALGORITMO);
        cipher.init(encryptMode, buildKey(chave), new IvParameterSpec(new byte[16], 0, 16));

        return cipher;
    }

    private static Key buildKey(String chave) throws Exception {

        byte[] utf8 = chave.getBytes("UTF-8");
        final byte[] key = new byte[16];
        System.arraycopy(utf8, 0, key, 0, utf8.length < 16 ? utf8.length : 16);

        return new SecretKeySpec(key, "AES");
    }

    /**
     * Classe de exemplo de utilizacao. Futuramente passar para o padrao JUnit.
     *
     * @param args nao precisa informar
     *
     * @throws Exception erro na criptografia
     */
    public static void main(String[] args) throws Exception {

        // Mensagem que sera criptografada.
        final String mensagem = "Mensagem que sera criptografada.";

        // Senha definida da operadora.
        final String chave = "uexDPnPr";

        // Valor criptografado.
        String criptografado = Criptografia.criptografar(mensagem, chave);
        System.out.printf("Valor criptografado: '%s' %n", criptografado);

        // Valor original.
        String descriptografado = Criptografia.descriptografar(criptografado, chave);
        System.out.printf("Valor descriptografado: '%s'", descriptografado);
    }

}

I just changed enough code to make it work. Now the value should be:

MlHaz/gOfy+9n/lptTYhqIAjRxqZAwH0hKkQoqyE+DTIV1WB6Tain322hk2yWnjw

It is very weak the way the key is generated there. I suggest using PBKDF2 or something better. If possible, switch CBC to CTR (you may need to replace Policy File).

  • 5

    GOKU, actually Marcos is right. I’m preparing an answer to your problem, but your Constraint not changing the Java side compromises all system security. Behavior default on the java side is to use AES/ECB/PKCS5Padding. This combination, outside of very specific applications, is quite useless from a security point of view. The fact that the original code does not specify the encryption and padding mode already shows that whoever wrote this part did not have much idea of what they were doing. I’ll give you a "solution", but the milestones are right, the hole is lower.

  • 3

    Well, it’s the way I decided to solve your problem and that of your client. Mr Anthony Accioly explained the reasons very well. I didn’t even bother to leave the SHA hash there because it’s easy to apply Dictionary Attack and Rainbow Tables.

6

Use IKVM.net and Compile the Java class in .NET. So it is sure to come out the same:

Editing:

Step by step:

  1. Download and install the IKVM.net:

  2. Compile your Java code:

     javac Aes_Example.java
    

    Exit: Aes_Example.class

  3. Manages an Assembly . NET from the class:

     ikvmc -target:library Aes_Example.class
    

    Exit: Aes_Example.dll

  4. Then you take the dll and use it in the C project#!


For more information: http://www.ikvm.net/userguide/tutorial.html

Browser other questions tagged

You are not signed in. Login or sign up in order to post.