Unity C# AES - Can't send IV - c#

I am having a problem with my code and cannot figure out the problem.
With fullMsg set to false it works.
If I change fullMsg to true it no longer works even if I set it back to false.
I have no idea what is going on as the byte[] array remains the same in all the cases.
private void sendIndividualMsg(string msg){
//Debug.Log (msg);
byte[] toSend = PackageMsg (msg);
byte[] decoded = UnPackageMsg (toSend);
Debug.Log( System.Text.Encoding.ASCII.GetString(decoded) );
}
private byte[] UnPackageMsg(byte[] msg){
var toDecrypt = msg;
if (fullMsg) {
toDecrypt = new byte[msg.Length - 16];
var decryptIV = new byte[16];
System.Buffer.BlockCopy (msg, 0, decryptIV, 0, 16);
System.Buffer.BlockCopy (msg, 16, toDecrypt, 0, (msg.Length - 16));
//myAes.IV = decryptIV;
}
PrintByteArray (toDecrypt, "ToDecrypt");
byte[] plaintext;
// Create the streams used for decryption.
{
ICryptoTransform decryptor = myAes.CreateDecryptor (myAes.Key, myAes.IV);
MemoryStream msDecrypt = new MemoryStream ();
CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Write);
csDecrypt.Write(msg, 0, msg.Length);
csDecrypt.FlushFinalBlock();
csDecrypt.Close();
plaintext = msDecrypt.ToArray();
msDecrypt.Close ();
decryptor.Dispose();
}
if (plaintext.Length > 16) {
byte[] hash = new byte[16];
byte[] hashCalc = new byte[16];
byte[] payload = new byte[plaintext.Length - 16 ];
System.Buffer.BlockCopy (plaintext, 0, hash, 0, 16);
System.Buffer.BlockCopy (plaintext, 16, payload, 0, plaintext.Length - 16);
hashCalc = md5.ComputeHash(payload);
if(ByteArrayCompare(hash, hashCalc)){
return payload;
}else{
return new byte[0];
}
} else {
return new byte[0];
}
}
private byte[] PackageMsg(string msg){
System.Text.ASCIIEncoding ue = new System.Text.ASCIIEncoding();
byte[] bytes = ue.GetBytes(msg);
byte[] hashBytes = md5.ComputeHash(bytes);
byte[] toEncrypt = new byte[bytes.Length + hashBytes.Length];
System.Buffer.BlockCopy(hashBytes, 0, toEncrypt, 0, hashBytes.Length);
System.Buffer.BlockCopy(bytes, 0, toEncrypt, hashBytes.Length, bytes.Length);
//myAes.GenerateIV();
byte[] encrypted;
{
ICryptoTransform encryptor = myAes.CreateEncryptor (myAes.Key, myAes.IV);
MemoryStream msEncrypt = new MemoryStream ();
CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
csEncrypt.Close();
encrypted = msEncrypt.ToArray();
msEncrypt.Close ();
encryptor.Dispose();
}
PrintByteArray (encrypted, "Encrypted");
//SessionBytes + IV + ENCRYPTED( hash + msg)
byte[] finalMsg = new byte[myAes.IV.Length + encrypted.Length ];
System.Buffer.BlockCopy(myAes.IV, 0, finalMsg, 0 , myAes.IV.Length);
System.Buffer.BlockCopy(encrypted, 0, finalMsg, myAes.IV.Length , encrypted.Length);
if (!fullMsg) {
finalMsg = encrypted;
}
return finalMsg;
}
(I want to send the IV through each message, but until I get this working their is no point.)
Basic explanation of the algorithm for encrypting:
If fullMsg is set the encryption is [session][iv][encryptedmsg]
If fullMsg is not set the encryption is [encryptedmsg]
For Decryption the first part of the code is too extract just the encryptedmsg part.
As show by the screenshot of the logs, in both modes the bytes are the same.
--

Related

C# RijndaelManaged Encryption Output Is Wrong

I have encryption and decryption methods but the encryption method's output is wrong. The key is "u1S1t12vTeZtlRHd" and the output must be "kJtXKmIiP9f73IZJim16LA==" ( Please check decryiption method) but the encryption method is giving me this output "VmmB3k7hVoKF9/cAQedaYQ==". How can i fix it?
UTF8Encoding utf8Encoding = new UTF8Encoding();
byte[] bytes = utf8Encoding.GetBytes("u1S1t12vTeZtlRHd");
RijndaelManaged rijndaelManaged = new RijndaelManaged
{
Key = bytes,
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7
};
byte[] bytes2 = utf8Encoding.GetBytes("FAILED");
rijndaelManaged.CreateEncryptor();
byte[] inArray;
try
{
inArray = rijndaelManaged.CreateEncryptor().TransformFinalBlock(bytes2, 0, bytes2.Length);
}
finally
{
rijndaelManaged.Clear();
}
Console.WriteLine(Convert.ToBase64String(inArray));
byte[] array = Convert.FromBase64String("kJtXKmIiP9f73IZJim16LA==");
byte[] bytes = Encoding.ASCII.GetBytes("u1S1t12vTeZtlRHd");
ICryptoTransform transform = new RijndaelManaged
{
Mode = CipherMode.ECB,
Padding = PaddingMode.None
}.CreateDecryptor(bytes, null);
MemoryStream memoryStream = new MemoryStream(array);
CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read);
byte[] array2 = new byte[checked(array.Length - 1 + 1)];
int count = cryptoStream.Read(array2, 0, array2.Length);
memoryStream.Close();
cryptoStream.Close();
Console.WriteLine(Encoding.UTF8.GetString(array2, 0, count));

AesCryptoServiceProvider "The input data is not a complete block"

I wrote two programs in C#. One does the encryption, and the other one does the decryption. The decryption program throws exception of "The input data is not a complete block" with data from the encryption program. However the decryption program works fine with the encrypted data from a Unix encryption program, using PKCS5_PBKDF2_HMAC_SHA1().
Encrypted data is base 64 encoded, and saved in a text file. The first 8 bytes is a salt, the next 16 bytes is an IV, and the rest is the application text.
I would appreciate very much if anyone could help.
public static string DecryptText(string cipherData)
{
if (string.IsNullOrEmpty(_passwd))
return null;
var decodedBytes = Convert.FromBase64String(cipherData);
// First 8 bytes contain the salt used for key derivation. Use the password from the passwd.dat
// file and the salt to derive the key used to encode the credential.
//
var salt = new byte[8];
Buffer.BlockCopy(decodedBytes, 0, salt, 0, 8);
var derivedBytes = new Rfc2898DeriveBytes(_passwd, salt, 1000);
var key = derivedBytes.GetBytes(32);
// Next 16 bytes contain the initialization vector used to encrypt
//
var ivBytes = new byte[16];
Buffer.BlockCopy(decodedBytes, 8, ivBytes, 0, ivBytes.Length);
// Remaining bytes contain the credential cipher text
//
var cipherBytes = new byte[decodedBytes.Length - 8 - 16];
Buffer.BlockCopy(decodedBytes, 8 + 16, cipherBytes, 0, cipherBytes.Length);
string decryptedData = null;
try
{
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = key;
aes.IV = ivBytes;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
decryptedData = Encoding.UTF8.GetString(ms.ToArray());
}
}
}
catch (Exception ex)
{
Console.Write("Caught exception while decryption: {0}: ", ex.Message);
}
return decryptedData;
}
public static string EncryptText(string plainData)
{
if (string.IsNullOrEmpty(_passwd))
return null;
var rfc2898db = new Rfc2898DeriveBytes(_passwd, 8, 1000);
byte[] salt = new byte[8];
Buffer.BlockCopy(rfc2898db.Salt, 0, salt, 0, 8);
byte[] key = new byte[32];
Buffer.BlockCopy(rfc2898db.GetBytes(32), 0, key, 0, 32);
string cipherData;
try
{
var aes = new AesCryptoServiceProvider
{
Key = key,
KeySize = 256,
BlockSize = 128,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
aes.GenerateIV();
byte[] encrypted;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
ms.Write(aes.IV, 0, aes.IV.Length);
ms.Write(salt, 0, 8);
cs.Write(Encoding.UTF8.GetBytes(plainData), 0, plainData.Length);
cs.Close();
}
encrypted = ms.ToArray();
}
byte[] encryptedBytes = new byte[SaltLength + IvLength + encrypted.Length];
Buffer.BlockCopy(salt, 0, encryptedBytes, 0, SaltLength);
Buffer.BlockCopy(aes.IV, 0, encryptedBytes, SaltLength, IvLength);
Buffer.BlockCopy(encrypted, 0, encryptedBytes, SaltLength + IvLength, encrypted.Length);
cipherData = Convert.ToBase64String(encryptedBytes);
}
catch (Exception ex)
{
Console.Write("Caught exception while encryption: {0}", ex.Message);
return null;
}
return cipherData;
}

Padding is invalid when decrypt file

static SymmetricAlgorithm encryption;
static string password = "SBC";
static string salt = "ash";
public Decryption()
{
encryption = new RijndaelManaged();
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));
encryption.Key = key.GetBytes(encryption.KeySize / 8);
encryption.IV = key.GetBytes(encryption.BlockSize / 8);
encryption.Padding = PaddingMode.PKCS7;
}
public void Decrypt(Stream inStream, Stream OutStream)
{
ICryptoTransform encryptor = encryption.CreateDecryptor();
inStream.Position = 0;
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
CopyTo(inStream, encryptStream1);
encryptStream1.FlushFinalBlock();
encryptStream1.Close();
inStream.Close();
OutStream.Close();
}
public void CopyTo(Stream input, Stream output)
{
// This method exists only in .NET 4 and higher
byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
In my windows form load i just create a thread and call the function to decrypt file, this is thread function
Thread objthreadhtml = new Thread(new ThreadStart(JsHtmlDecrypt));
objthreadhtml.IsBackground = true;
objthreadhtml.Name = "HtmlJsDecrypt";
objthreadhtml.Priority = ThreadPriority.Highest;
objthreadhtml.Start();
below function is decrypt function
public static void JsHtmlDecrypt()
{
string startPathForHtml = Application.LocalUserAppDataPath.Replace("\\OfflineApplication\\OfflineApplication\\1.0.0.0", "").ToString() + "\\Apps\\Html\\";
var directoryPathForHtml = new DirectoryInfo(startPathForHtml);
foreach (FileInfo fileForHtml in directoryPathForHtml.GetFiles())
{
FileStream inFsForHtml = fileForHtml.OpenRead();
FileInfo inforFHtml = new FileInfo(fileForHtml.FullName.Replace(fileForHtml.Extension, ".html"));
FileStream outFsForHtml = inforFHtml.Create();
UnZipDecryptionEncryption.Decryption m_decryption1 = new Decryption();
m_decryption1.Decrypt(inFsForHtml, outFsForHtml);
inFsForHtml.Close();
outFsForHtml.Close();
UnZipDecryptionEncryption.DeleteZipandFiles m_delete1 = new DeleteZipandFiles();
m_delete1.DeleteFiles(fileForHtml.FullName);
}
}
Here i get the error padding is invalid in the line
encryptStream1.FlushFinalBlock();
Please help me someone how to solve this i am stuck in it.
Your "decrypt" function is trying to do the opposite of what you want: encrypt the data:
CryptoStream encryptStream1 = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
What you want, I assume, is to decrypt it (my code uses byte arrays as input/output, so you may want to modify that):
ICryptoTransform decryptor = encryption.CreateDecryptor();
// byte[] (cipherText) <-- encryted text
MemoryStream memoryStream = new MemoryStream(cipherText);
// here is the most important part: CryptoStreamMode.Read
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherText.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
// my text uses UTF8 encoding, so to get the plain text as string:
string result = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);

Cannot AES decrypt data in C# that was enccrypted in Objective-C

I have an iOS app that sends encrypted data that is later decrypted in C#. I have checked that the hex key and data received is same, but I still get Bad PKCS7 padding. Invalid length 0.
my Objective-C call is
+(NSData*) encryptData: (NSData*) data
key: (NSString*) key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [data length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[data bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
my keysize is 256, blocksize is 128, padding is pkcs7, IV is null, mode is CBC (default).
My C# code to decrypt is
using (MemoryStream memoryStream = new MemoryStream(outputBytes))
{
AesManaged algo = GetCryptoAlgorithm(GetRawBrokerKey());
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, algo.CreateDecryptor(), CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(cryptoStream))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
private static AesManaged GetCryptoAlgorithm()
{
return GetCryptoAlgorithm(null);
}
private static AesManaged GetCryptoAlgorithm(byte[] key)
{
AesManaged algorithm = new AesManaged();
//set the mode, padding and block size
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 256;
algorithm.BlockSize = 128;
if (key != null)
{
algorithm.Key = key;
}
algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return algorithm;
}
I tried encryption using C# and see a different hex output using the same key.
c# encryption - 42AC7494606333309287768F47DFB35B
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
byte[] encrypted;
AesManaged algorithm = new AesManaged();
//set the mode, padding and block size
algorithm.Padding = PaddingMode.PKCS7;
algorithm.Mode = CipherMode.CBC;
algorithm.KeySize = 256;
algorithm.BlockSize = 128;
if (key != null)
{
algorithm.Key = key;
}
algorithm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = algorithm.CreateEncryptor();
// 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();
}
}
string hex = BitConverter.ToString(encrypted);
Console.WriteLine("c# encryption - " + hex.Replace("-", ""));
// Return the encrypted bytes from the memory stream.
return encrypted;
}
Any ideas what could be going wrong? I seem to be following all the online advice around defaults for mode and IV, I think.
in GetCryptoAlgorithm, you need to pass the private key to GetCryptoAlgorithm.

C# method to decrypt in PHP

I have a C# code to decrypt data, now I'm trying to make the same in PHP but I can't get the same result. I know that I missing something but I don't know how to transfer this to PHP. Any ideas? Thanks.
This is the C# code:
public static string Decrypt(string cipherData, string key)
{
byte[] salt = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
PasswordDeriveBytes cdk = new PasswordDeriveBytes(key, salt);
byte[] kex = cdk.CryptDeriveKey("RC2", "SHA1", 128, salt);
RijndaelManaged rijKey = new RijndaelManaged();
rijKey.Mode = CipherMode.CBC;
byte[] textBytes = Convert.FromBase64String(cipherData);
ICryptoTransform decryptor = rijKey.CreateDecryptor(kex, IV);
MemoryStream memoryStream = new MemoryStream(textBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] pTextBytes = new byte[(textBytes.Length - 1) + 1];
int decryptedByteCount = cryptoStream.Read(pTextBytes, 0, pTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(pTextBytes, 0, decryptedByteCount);
}
This is the PHP code trying to make the same (I know that it is incomplete):
function Decrypt($data, $key) {
$method = 'rc2-cbc';
$iv = '0000000000000000';
return utf8_encode(openssl_decrypt($data, $method, sha1($key), OPENSSL_ZERO_PADDING, $iv));
}

Categories