For secure communication between client and server, I want to encrypt and decrypt data from both the client and the server, but I cannot get the same results, the data that comes from the client to the server is not decrypted, also when encrypting the same the same data from the server, I get a distinctive result from encryption on the client.
The client is written in C ++ using Crypto ++. The code:
string data = "teststring,teststring,teststring";
string encryptedData = client.encrypt(userData, "01234567891234560123456789123456", "0123456789123456");
string Client::encrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
AES::Encryption aesEncryption((byte*)key.c_str(), key.length());
CBC_Mode_ExternalCipher::Encryption encryption(aesEncryption, (byte*)iv.c_str());
StringSource encryptor(str_in, true,
new StreamTransformationFilter(encryption,
new Base64Encoder(
new StringSink(str_out),
false
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
string Client::decrypt(const string& str_in, const string& key, const string& iv)
{
try {
string str_out;
CBC_Mode<AES>::Decryption decryption((byte*)key.c_str(), key.length(), (byte*)iv.c_str());
StringSource decryptor(str_in, true,
new Base64Decoder(
new StreamTransformationFilter(decryption,
new StringSink(str_out)
)
)
);
return str_out;
}
catch (exception e) {
return "null";
}
}
Gives the following output:
data: "teststring,teststring,teststring"
encryptedData: "STpuD/dRgYard+Yqpdd5KOYET7607i7ZRUoKm5eshHzR3ErafaxgZ2+T1tSp0lWJ"
The server side of the code is written in C # (ASP.NET Core 3.1):
public static string Encrypt(string input)
{
byte[] clearBytes = Encoding.Default.GetBytes(input);
using (Aes encryptor = Aes.Create("AES"))
{
// encryptor.BlockSize = 32;
encryptor.Padding = PaddingMode.Zeros;
encryptor.KeySize = 128;
encryptor.Mode = CipherMode.CBC;
encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Convert.ToBase64String(bt);
}
}
return input;
}
public static string Decrypt(string input)
{
byte[] clearBytes = Encoding.ASCII.GetBytes(input);
using (Aes decryptor = Aes.Create("AES"))
{
//decryptor.BlockSize = 32;
decryptor.Padding = PaddingMode.Zeros;
decryptor.KeySize = 128;
decryptor.Mode = CipherMode.CBC;
decryptor.Key = Encoding.ASCII.GetBytes("01234567891234560123456789123456");
decryptor.IV = Encoding.ASCII.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
input = Encoding.ASCII.GetString(bt);
}
}
return input;
}
Output:
data: "teststring,teststring,teststring"
encryptedData: "tIDlWnnzOQWh5HIvRDJya6z7jOglkIlYrICeYW9RoEM="
I cannot decrypt data from both the client and the server. Help me please.
The posted C++ code is fine. It returns the posted ciphertext STpu...0lWJ on my machine and the ciphertext can be decrypted with the decrypt() method.
In contrast, although the posted C# code returns the posted ciphertext tIDl...RoEM=, the ciphertext cannot be decrypted using the Decrypt() method. This has two reasons:
In the Encrypt() and in the Decrypt() method different keys are used. The key of the Decrypt() method matches the key applied in the C++ code. With regard to a comparison of the ciphertexts of both codes, the key in the Encrypt() method should be replaced.
The ciphertext is Base64 encoded in the Encrypt() method, but not Base64 decoded in the Decrypt() method (but ASCII encoded instead). Here a Base64 decoding must be done in the Decrypt() method (note that an ASCII decoding in the Encrypt() method is not an alternative, since this would corrupt the ciphertext).
If these two bugs are fixed, the ciphertexts of C++ and C# code match except for the end. This last mismatch is caused by different paddings. In the C++ code PKCS7 padding is used, in the C# code Zero padding. If the padding in the C# code (in the Encrypt() and Decrypt() methods) is changed to PaddingMode.PKCS7, the ciphertexts match.
Other problems in the C# code are:
In the Encrypt() method Encoding.Default is used, in the Decrypt() method Encoding.ASCII. Here a consistent encoding, e.g. Encoding.UTF8 should be applied.
The specified 128-bit key size is not consistent with the 256-bit key used. This has no effect because the explicit key specification automatically corrects the key size (nevertheless, the key size should be specified correctly or completely omitted).
Also, it should be noted that a static IV is insecure (for testing purposes, of course, that's OK).
Related
I'm trying to match encryption schemes on c++ using crypto++ and c# and can't seem to get the same results on both. They both work on them selves, but not from one to the other. Any help would be great!
C++ code using Crypto++:
std::string key = "01286567891233460123456789123456";
std::string iv = "0123456789123456";
std::string encrypt(const std::string& str_in)
{
std::string str_out;
CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());
StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);
stfEncryptor.MessageEnd();
return str_out;
}
std::string decrypt(const std::string& cipher_text)
{
std::string str_out;
CryptoPP::AES::Decryption aesDecryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, (byte*)iv.c_str());
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(str_out));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(cipher_text.c_str()), cipher_text.size());
stfDecryptor.MessageEnd();
return str_out;
}
The Code Ran:
std::string str = encrypt("123456789012345");
str = decrypt(str);
This output is:
Encrypted: Ö&qcƒ“¹yLY»Lïv¹w“¼LLŠÀ¶ó¢,óð9·
Length: 32
Decrypted: 123456789012345
Length: 16
Now in C#, I have the following code:
public string Encrypt(string clearText)
{
byte[] clearBytes = Encoding.Default.GetBytes(clearText);
using (Aes encryptor = Aes.Create("AES"))
{
// encryptor.BlockSize = 128;
encryptor.Padding = PaddingMode.Zeros;
encryptor.KeySize = 128;
encryptor.Mode = CipherMode.CBC;
encryptor.Key = Encoding.Default.GetBytes("01234567891234560123456789123456");
encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
clearText = Encoding.Default.GetString(bt);// Convert.ToBase64String(bt);
}
}
return clearText; //Return the encrypted command
}
public string Decrypt(string cipherText)
{
byte[] clearBytes = Encoding.Default.GetBytes(cipherText);
using (Aes decryptor = Aes.Create("AES"))
{
// decryptor.BlockSize = 128;
decryptor.Padding = PaddingMode.Zeros;
decryptor.KeySize = 128;
decryptor.Mode = CipherMode.CBC;
decryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
decryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
cipherText = Encoding.Default.GetString(bt);// Convert.ToBase64String(bt);
}
}
return cipherText; //Return the decrypted text
}
}
The code ran:
string orig = "123456789012345";
string cipher = Encrypt(orig);
string dedata = Decrypt(cipher);
The results are:
Orig: 123456789012345
Encrypted: êßyoº0¦ëì›X˜Ü
Length: 16
Decrypted: 123456789012345
Length: 16
As you can see, the encrypted strings end up being different. So when I take an encrypted string in c++, it can't decrypt it in c#, as shown here:
bytes[] encryptedText = ENCRYPTED TEXT FROM C++
text = System.Text.Encoding.Default.GetString(encryptedText);
text = Decrypt(text);
The c++ returns 32 bytes for it's encrypted string which I believe is the padding being added. Not sure how to replicate this in the c# code or vise versa to match things up. Not sure if there is something else I'm missing here... Thanks for any help!
EDIT:
I've matched the keys and now the string matches on both ends except for the padding difference. When I try to decrypt the string in C# it tells me the input data is not the correct block size? Any help with this now?
EDIT AGAIN:
It seems to be generating the same byte string for each c# and c++ encryption function, so that problem is resolved. The problem I now seem to have is on the c# side, I receive the encrypted string and convert the bytes using: text = System.Text.Encoding.Default.GetString(recvBuf); recvBuf being the encrypted string from c++ and it's missing the last character of the string. It matches up with the c++ string minus the last char?? Not sure why this is happening.
For example, my c++ sends over this encrypted string: Ö&qcƒ“¹yLY»Lïv and my c# program will only receive this: Ö&qcƒ“¹yLY»Lï which in turn will make it fail at decryptng. The encrypted string is being sent over a TCP SOCKET if that makes any difference.
EDIT
Still missing bytes after changing encoding and decoding to base64 on both ends.
C++ 1iZxY4OTHrl5TFm7Gkzvdrl3k7xMTIrAtvOiLPPwObc=
C# 1iZxY4OTHrl5TFm7Gkzvdg==
C# RECEIVED 1iZxY4OTHrl5TFm
New Code C#:
public string Encrypt(string clearText)
{
byte[] clearBytes = Encoding.Default.GetBytes(clearText);
using (Aes encryptor = Aes.Create("AES"))
{
// encryptor.BlockSize = 128;
encryptor.Padding = PaddingMode.Zeros;
encryptor.KeySize = 128;
encryptor.Mode = CipherMode.CBC;
encryptor.Key = Encoding.Default.GetBytes("01286567891233460123456789123456");
encryptor.IV = Encoding.Default.GetBytes("0123456789123456");
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
byte[] bt = ms.ToArray();
clearText = Convert.ToBase64String(bt);
}
}
return clearText; //Return the encrypted command
}
And C++ Code:
std::string encrypt(const std::string& str_in)
{
std::string str_out;
std::string str_out2;
CryptoPP::AES::Encryption aesEncryption((byte*)key.c_str(), CryptoPP::AES::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, (byte*)iv.c_str());
StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(str_out));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(str_in.c_str()), str_in.length() + 1);
stfEncryptor.MessageEnd();
str_out2 = base64_encode(reinterpret_cast<const unsigned char*>(str_out.c_str()), strlen(str_out.c_str()));
return str_out2;
}
EDIT
IT WORKS!!! It was simply an overlook on my part, my socket was checking the size of the data before encrypted and sending that size instead of the encrypted string size. Fix that and all it working perfect. Thanks Brandon for the help!
What I am suggesting is your running afoul of text encoding both when converting the clear text to bytes for encrypting and also when converting from bytes to display string for "transmission".
Try this:
C# code
public string Encrypt(string clearText, Encoding encoding)
{
// use supplied encoding to convert clear text to bytes
byte[] clearBytes = encoding.GetBytes(clearText);
byte[] bt = // insert your encrypt code here...
// bt bytes are *not* ascii or utf8 or anything else. If you just
// use an encoding to convert to text, you won't have good results
// lets use base64 encoding to get a nice display string representation
// of the bytes
return Convert.ToBase64String(bt);
}
public string Decrypt(string base64EncryptedString, Encoding encoding)
{
// decode the base64
byte[] bt = Convert.FromBase64String(base64EncryptedString);
byte[] decrypted = // insert your decrypt code here
// now we have the original bytes. Convert back to string using the same
// encoding we used when encrypting
return encoding.GetString(decrypted);
}
// Usage:
var clearText = "Hello World";
var asciiEncrypted = Encrypt(clearText, Encoding.ASCII);
var decrypted = Decrypt(clearText, Encoding.ASCII); // MUST USE SAME ENCODING
var utf8Encrypted = Encrypt(clearText, Encoding.UTF8);
var utf8Decrypted = Decrypt(clearText, Encoding.UTF8);
You need to make the same base64 changes in your C++ code. I'm less familiar with the encoding of your C++ strings. I think that if you are using C++ string literals hard coded in the code, then they will be UTF8. This means that your C++ and C# code should agree once you make the C# changes, make the base64 changes in your C++ code, and pass UTF8 to your C# Encrypt/Decrypt methods.
I am trying to solve an encryption issue I am having between php and c#.
I have encrypted data using the following php and openssl operation.
$encrypt_method = "AES-256-CBC";
$secret_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$secret_iv = 'XXXXXXXXXXXXXXXX';
$key = hash ('sha256', $secret_key);
$iv = substr (hash ('sha256', $secret_iv), 0, 16);
$output = openssl_encrypt ($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode ($output);
I have tried a couple of methods in C# to decrypt but this is what I am trying now.
public string Encrypt_Decrypt(string action, string value) {
string secretKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
string secretIV = "XXXXXXXXXXXXXXXX";
string key = Hash(secretKey);
string iv = Hash(secretIV).Substring(0,16);
string retValue = "";
if (action == "encrypt") {
retValue = EncryptString(value, key, iv);
}
else if (action == "decrypt") {
retValue = DecryptString(value, key, iv);
}
}
// Hash to match php hash function
public static string Hash(string unhashedString) {
return BitConverter.ToString(new SHA256CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(unhashedString))).Replace("-", String.Empty).ToLower();
}
public static string DecryptString(string cipherData, string keyString, string ivString) {
byte[] key = Encoding.UTF8.GetBytes(keyString);
Console.WriteLine(key.Length);
byte[] iv = Encoding.UTF8.GetBytes(ivString);
Console.WriteLine(iv.Length);
byte[] cipherCrypt = Convert.FromBase64String(cipherData);
for (int i = 0; i < cipherCrypt.Length; i++) {
Console.Write(cipherCrypt[i] + " ");
}
try {
RijndaelManaged crypto = new RijndaelManaged();
crypto.Key = key;
crypto.IV = iv;
crypto.Mode = CipherMode.CBC;
crypto.KeySize = 256;
crypto.BlockSize = 128;
crypto.Padding = PaddingMode.None;
ICryptoTransform decryptor = crypto.CreateDecryptor(crypto.Key, crypto.IV);
using (MemoryStream memStream = new MemoryStream(cipherCrypt)) {
using (CryptoStream cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Read)) {
using (StreamReader streamReader = new StreamReader(cryptoStream)) {
return streamReader.ReadToEnd();
}
}
}
}
catch (CryptographicException e) {
Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
return null;
}
}
I have tried a couple different encoding types when getting the byte[] for the operation.
I keep getting the following error:
Specified key is not a valid size for this algorithm.
Not sure what I am missing. Any help is appreciated.
Also, I already read through this and tried what the solution suggestion recommended. I got the same resulting error.
UPDATE - 01
I have updated the code here to reflect the code I have changed.
The key length is 32,
The iv length is 16,
The data coming in at "cipherData" is length 32,
When "cipherData" goes through "FromBase64String(cipherData)" it comes out as a 24 byte array. This is causing an issue for the decryptor which wants a 32 byte array.
There are obviously problems with the key size. The code between PHP and C# seem to match. The problem seems to be that the code is wrong in both cases.
Let's see how long the key actually is:
Start with a 32 byte key (non-encoded).
Hash the key with SHA-256: 32 bytes (non-encoded).
Encode to hex (integrated into PHP's hash() function by default): 64 bytes.
AES only supports the following key sizes: 16, 24 and 32 bytes. openssl_encrypt() will only use the first 32 bytes of the hex key silently. So, you need to use the first 32 bytes in C#.
Note that openssl_encrypt() takes an options argument which denotes that the output is Base64 when OPENSSL_RAW_DATA is not set. It means that the PHP output was encoded twice with Base64. So you need to decode it twice in C#.
I am encryption/decryption some plain text using following code.
private static string EncryptionKey = "##$%^&*()2343";
private static byte[] Salt = Encoding.ASCII.GetBytes(EncryptionKey.Length.ToString());
public static string EncryptIt(string Input)
{
RijndaelManaged Cipher = new RijndaelManaged();
byte[] TextByteArray = Encoding.Unicode.GetBytes(Input);
PasswordDeriveBytes Key = new PasswordDeriveBytes(EncryptionKey, Salt);
using (ICryptoTransform Transform = Cipher.CreateEncryptor(Key.GetBytes(32), Key.GetBytes(16)))
{
using (MemoryStream MS = new MemoryStream())
{
using (CryptoStream CS = new CryptoStream(MS, Transform, CryptoStreamMode.Write))
{
CS.Write(TextByteArray, 0, TextByteArray.Length);
CS.FlushFinalBlock();
return Convert.ToBase64String(MS.ToArray());
}
}
}
}
public static string DecryptIt(string Input)
{
RijndaelManaged Cipher = new RijndaelManaged();
byte[] EncryptedByteArray = Convert.FromBase64String(Input);
PasswordDeriveBytes Key = new PasswordDeriveBytes(EncryptionKey, Salt);
using (ICryptoTransform Transform = Cipher.CreateDecryptor(Key.GetBytes(32), Key.GetBytes(16)))
{
using (MemoryStream MS = new MemoryStream(EncryptedByteArray))
{
using (CryptoStream cryptoStream = new CryptoStream(MS, Transform, CryptoStreamMode.Read))
{
byte[] TransformedText = new byte[EncryptedByteArray.Length];
int Count = cryptoStream.Read(TransformedText, 0, TransformedText.Length);
return Encoding.Unicode.GetString(TransformedText, 0, Count);
}
}
}
}
In most of the cases, this code works fine. However in some cases when I try to decrypt the encrypted text, I get following exception when byte[] EncryptedByteArray = Convert.FromBase64String(Input) is called in DecryptIt methods.
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters.
Any idea what could be causing this exception. What I am finding more puzzling is that why this excpetion is not thrown on every cases and only few cases.
EDIT :
Sample Input to DecryptIt method that throws exception is below. Please note that I have changed the value of EncryptionKey variable in my sample above.
oaOQ6qWWDwWby3C04N7HJAiqQgILBifqdHq4OQ5KDDRA3F2ZlBITu31a8mJJQ8sKn4g3vODFEJbigtNZozv6ockAdsDChhHwaaLL4l8MJPKbV1EiUE3rL30y+xHz/S1a8mJJQ8sKn4g3vODFEJbigtNZozv6ockAdsDChhHwaaLL4l8MJPKbV1EiUE3rL30y+oz/eR9OzXn+3Lepo0tRqH5BsfvEtJ/IcqRu3gJiIBTMAM0TmVxa2EZSj2mn6jZlgvlOEFCWzNKS3R9OzXn+In1br14venJmpApXyt930khz35UE5BtWn3Fq7jyer6mY2l60P/cI4z
Your sample deconverts perfectly with 2 extra '=' at the end.
So somewhere they are lost in transport.
The ecrypted text is sent via email in a http link.
So that involves both URL and HTML encoding? Plenty of room for an error.
Run a test with a small string ending in ==.
I tried to encrypt data using this function in PHP and decrypt it with the other function in C#. But I don't get the same string.
//php function
public function onCrypt($text)
{
$key=md5('DFDFDFDFDFDFDFDFDFDFDFDF',true);
$crypttext = urldecode(trim(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key, $text, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB), MCRYPT_RAND))));
$text_crp =base64_encode($crypttext);
return $text_crp;
}
//c# function
//public static void DecryptFile
Parameters :
strKey : the key choosed in decryption .
PathPlainTextFile : path of the crypted file
PathPlainTextFile : the original file decrypted.
public static void DecryptFile(string strKey, string pathPlainTextFile, string pathCypheredTextFile)
{
//crypt key with md5 function
System.Security.Cryptography.MD5 alg = System.Security.Cryptography.MD5.Create();
System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
byte[] md5val = alg.ComputeHash(enc.GetBytes(strKey));
StreamReader fsPlainTextFile = File.OpenText(pathPlainTextFile);
FileInfo t = new FileInfo(pathCypheredTextFile);
StreamWriter Tex =t.CreateText();
string input = null;
while ((input = fsPlainTextFile.ReadLine()) != null)
{
byte[] cipheredData = Convert.FromBase64String(input);
RijndaelManaged rijndaeld = new RijndaelManaged();
// define the used mode
rijndaeld.Mode = CipherMode.ECB;
// create the cipher AES - Rijndael
ICryptoTransform decryptor = rijndaeld.CreateDecryptor(md5val,null);
// Write the ciphered data in MemoryStream
MemoryStream ms= new MemoryStream(cipheredData);
CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
// Insert the ciphered data in a byte array
byte[] plainTextData = new byte[cipheredData.Length];
int decryptedByteCount = cs.Read(plainTextData, 0, plainTextData.Length);
ms.Close();
cs.Close();
// Insert the ciphered data in string encoded on Base64
Tex.WriteLine (Encoding.UTF8.GetString(plainTextData, 0, decryptedByteCount));
}
Tex.Close();
}
ECB mode is not secure. You should use either CTR mode or CBC mode. It is also best to explicitly specify the padding you are going to use at both ends.
At a quick glance, you're not supplying an IV to the C# decryptor:
ICryptoTransform decryptor = rijndaeld.CreateDecryptor(md5val, null);
I'm not familiar with php, but it looks like you created an IV when you encrypted the content. You'll need to have that same IV to decrypt it in the C# code (you'd need the same IV to decrypt it even if you were doing the decryption through php).
I am using the following C# source code to encrypt plain text using AES (ECB 256):
public static string Encode(string PlainText)
{
byte[] Key = ASCIIEncoding.UTF8.GetBytes("12345678901234567890123456789012");
string encrypted = null;
RijndaelManaged rj = new RijndaelManaged();
rj.BlockSize = 256;
rj.KeySize = 256;
rj.Key = Key;
rj.GenerateIV();
byte[] IV = rj.IV;
rj.Mode = CipherMode.ECB;
rj.Padding = PaddingMode.Zeros;
try
{
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(PlainText);
sw.Close();
sw.Dispose();
}
cs.Close();
cs.Dispose();
}
byte[] encryptArray = ms.ToArray();
encrypted = (Convert.ToBase64String(encryptArray));
ms.Close();
ms.Dispose();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
rj.Clear();
}
return encrypted;
}
And I need decrypt/encrypt data through same algorithm, but I don't know how.
Here my Java Class (not working):
public static String encrypt(byte[] key, String cleartext, boolean base64) throws Exception
{
byte[] rawKey = key;
byte[] result = encrypt(rawKey, cleartext.getBytes());
// Base 64
if (base64)
return toBase64(result);
// Hex
return toHex(result);
}
public static String decrypt(byte[] key, String encrypted)
throws Exception
{
byte[] rawKey = key;
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception
{
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
Java call:
encrypt("12345678901234567890123456789012".getBytes(), "Example Message", true);
I dont know how I can select the block size or the PaddingMode.Zeros in Java.
¿Any idea?
Thanks in advance
Yes, the problem is the limit of 128 bits block size in AES (see 'Strong Versus Unlimited Strength Cryptography').
Finally, I've used GNU Crypto and it works!. I've imported all source code and I've deleted the code that I'm not using.
If somebody wants the cleaned source code he only have to ask me.
Thanks for the help.
You should also consider Bouncy Castle, it's available for both C# and Java
http://www.bouncycastle.org
Reading over this article, it seems you might need to use a version of Java that allows unlimited strength cryptography so that you can use large key sizes (AES-192 and AES-256). They intentionally limit the key lengths that can be used by default due to import-control restrictions imposed by some countries. See the 'Strong Versus Unlimited Strength Cryptography' section for more information.