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
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
– user28595
@diegofm, had seen yes, but uses another type of encryption.
– Marco Souza
Goku, take a look in Soen’s reply. Try this one
RijndaelManaged
withBlockSize = 128
,aesEncryption.KeySize = 256
and 32 byte (256 bit) keys. If it works give me a tap I write a reply.– Anthony Accioly
@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.
– Marco Souza
You want them both
strings
produced (C# and Java) are exactly the same? Or are you having difficulty getting both systems to communicate?– Gomiero
@Gomiero, Let the string generated in C# be equal to Java.
– Marco Souza
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. TheIV
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
@Gomiero, if I receive the java IV as a parameter I could do?
– Marco Souza
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
@Gomiero, I made a Cipher.getIV(); and it always returns me NULL.
– Marco Souza
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), thegetIV()
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 :)– Gomiero
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
@osmarcf, thanks for the tip, but I guess you didn’t read the question completely, the java side is client.
– Marco Souza
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
@osmarcf , I didn’t quite understand how that would be.
– Marco Souza
@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 .
– Marco Souza
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()) {
 Encoding enc = Encoding.UTF8;
 byte[] pwdBytes = hash.ComputeHash(enc.GetBytes(chave));
}
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
@osmarcf, I’ve seen this before. It doesn’t work.
– Marco Souza