currently im using System.Security.Cryptography and this is my code for it:
private static SymmetricAlgorithm createCryptoServiceProvider(string key, string IV)
{
byte[] password;
using (MD5 md5 = MD5.Create())
password = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
var crypt = new TripleDESCryptoServiceProvider();
byte[] iv = Encoding.UTF8.GetBytes(IV);
crypt.IV = iv;
crypt.Key = password;
return crypt;
}
public static byte[] Serialize(object obj, string key, string key2)
{
var provider = createCryptoServiceProvider(key, key2);
using (MemoryStream memory = new MemoryStream())
{
using (CryptoStream stream = new CryptoStream(memory, provider.CreateEncryptor(), CryptoStreamMode.Write))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
return memory.ToArray();
}
}
public static object Deserialize(byte[] inBytes, string key, string key2)
{
var provider = createCryptoServiceProvider(key, key2);
using(MemoryStream memory = new MemoryStream(inBytes))
{
using (CryptoStream stream = new CryptoStream(memory, provider.CreateDecryptor(), CryptoStreamMode.Read))
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
}
}
i use this when getting ready to send data over a socket, I create a object that will have the key in a private field and also keep the key so it knows the key, when the object is received on the other client then it uses a function inside the object that was sent that uses that private string key, key2; and encrypts the message into bytes and sets the keys to "" and then it sends the object back holding the bytes. so now only the original sender can decrypt it. Is this a good way to do this or is there a better way?
Don't try to do the encryption yourself.
http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx
The example code uses TcpClient, but it should work with any stream IO, so direct sockets should be fine also.
Related
I have encryption decryption code which is perfectly working fine in local. From local system using code first approach I created database in aws which created successfully with seeds values in which I have decrypted the password.
Now, I have published the .net6 application in aws ec2 instance. On logging it is giving error of incorrect credentials.
I have logged the username and passwords and rechecked the scenario. The issue I have found is the encryption is changed.
I have updated the password and successfully logged in. But now the problem is with roles. I have applied checks on encrypted role ids which are not maching now.
Can anyone please help me here on this issue please?
`
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Common
{
public static class EncyptionDcryption
{
static string key = "85OIbnI9";
static string vector = "eH90BDl0";
////////////////////////////////////////////////////////////////////////////////
// Decryption
////////////////////////////////////////////////////////////////////////////////
public static string GetDecryptedText(string txt)
{
txt = txt.Replace(' ', '+');
DESCryptoServiceProvider key = new DESCryptoServiceProvider();
key.Key = ASCIIEncoding.ASCII.GetBytes(key); // decryption key
key.IV = ASCIIEncoding.ASCII.GetBytes(vector);// initialization vector
int length = txt.Length;
byte[] buffer = new byte[length];
buffer = Convert.FromBase64String(txt);
string decText = Decrypt(buffer, key);
return decText;
}
public static string Decrypt(byte[] CypherText, SymmetricAlgorithm key)
{
// Create a memory stream to the passed buffer.
MemoryStream ms = new MemoryStream(CypherText);
// Create a CryptoStream using the memory stream and the
// CSP DES key.
CryptoStream encStream = new CryptoStream(ms, key.CreateDecryptor(), CryptoStreamMode.Read);
// Create a StreamReader for reading the stream.
StreamReader sr = new StreamReader(encStream);
// Read the stream as a string.
string val = sr.ReadLine();
// Close the streams.
sr.Close();
encStream.Close();
ms.Close();
return val;
}
////////////////////////////////////////////////////////////////////////////////
// Encryption
////////////////////////////////////////////////////////////////////////////////
public static byte[] Encrypt(string PlainText, SymmetricAlgorithm key)
{
// Create a memory stream.
MemoryStream ms = new MemoryStream();
// Create a CryptoStream using the memory stream and the
// CSP DES key.
CryptoStream encStream = new CryptoStream(ms, key.CreateEncryptor(), CryptoStreamMode.Write);
// Create a StreamWriter to write a string
// to the stream.
StreamWriter sw = new StreamWriter(encStream);
// Write the plaintext to the stream.
sw.WriteLine(PlainText);
// Close the StreamWriter and CryptoStream.
sw.Close();
encStream.Close();
// Get an array of bytes that represents
// the memory stream.
byte[] buffer = ms.ToArray();
// Close the memory stream.
ms.Close();
// Return the encrypted byte array.
return buffer;
}
public static string GetEncryptedText(string txt)
{
DESCryptoServiceProvider key = new DESCryptoServiceProvider();
key.Key = ASCIIEncoding.ASCII.GetBytes(key); // decryption key
key.IV = ASCIIEncoding.ASCII.GetBytes(vector);// initialization vector
// Encrypt a string to a byte array.
byte[] buffer = Encrypt(txt, key);
string encText;
encText = Convert.ToBase64String(buffer);
return encText;
}
}
}
`
Why it behaves differently on server and local? But no clue.
I wrote this code to encrypt a text and write the encrypted text to a file and then decrypt it from the file. But I get this exception: System.Security.Cryptography.CryptographicException: 'The input data is not a complete block.' When I use a byte[] for storing data, it works perfect but it seems that it cant correctly convert a file to byte[]. I also tried File.ReadAllBytes but I got the same error. Please Help me.
class Program
{
static void Main(string[] args)
{
string decrypted;
byte[] encrypted;
Console.Write("Enter a text to encrypt : ");
string plaintext = Console.ReadLine();
using (Aes aes = Aes.Create())
{
encrypted = AesEncryption.Encrypt(plaintext, aes);
File.WriteAllText(#"C:\Users\sepita\Desktop\My.txt", Encoding.UTF8.GetString(encrypted), Encoding.UTF8);
decrypted = AesEncryption.Decrypt(Encoding.UTF8.GetBytes(File.ReadAllText(#"C:\Users\sepita\Desktop\My.txt")), aes);
}
Console.WriteLine($"Encrypted : {Encoding.UTF8.GetString(encrypted)}");
Console.WriteLine($"Decrypted : {decrypted}");
}
}
static class AesEncryption
{
public static byte[] Encrypt(string plaintext, Aes aes)
{
byte[] encrypted;
ICryptoTransform encryptor = aes.CreateEncryptor();
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream stream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(plaintext);
}
encrypted = memoryStream.ToArray();
}
}
return encrypted;
}
public static string Decrypt(byte[] encrypted, Aes aes)
{
string decrypted = null;
ICryptoTransform decryptor = aes.CreateDecryptor();
using (MemoryStream memoryStream = new MemoryStream(encrypted))
{
using (CryptoStream stream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(stream))
{
decrypted = reader.ReadToEnd();
}
}
}
return decrypted;
}
}
The result of your Encrypt function is binary data. It would be pure luck if this were a valid UTF8 string, so Encoding.UTF8.GetString(encrypted) will not work in general.
Replacing it by
File.WriteAllBytes(#"C:\Users\sepita\Desktop\My.bin", encrypted);
decrypted = AesEncryption.Decrypt(File.ReadAllBytes(#"C:\Users\sepita\Desktop\My.bin"), aes);
will work.
If you want a text file, use BASE64 conversion on the binary data:
File.WriteAllText(#"C:\Users\sepita\Desktop\My.txt", Convert.ToBase64String(encrypted));
decrypted = AesEncryption.Decrypt(Convert.FromBase64String(File.ReadAllText(#"C:\Users\sepita\Desktop\My.txt")), aes);
I need to encrypt a string which I am sending in a URL and later I need to decrypt it ...
Which approach would be better for this? I tried the following:
string s = "String to be encrypted";
string encrypted = CipherUtility.Encrypt<RijndaelManaged>(s, "pass", "salt");
string decrypted = CipherUtility.Decrypt<RijndaelManaged>(encrypted, "pass", "salt");
But the encrypted string gets an "=" at the end ... I would like to avoid that.
And I am not sure that this would be the best option ...
The CipherUtility is the following:
public class CipherUtility
{
public static string Encrypt<T>(string value, string password, string salt)
where T : SymmetricAlgorithm, new()
{
DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateEncryptor(rgbKey, rgbIV);
using (MemoryStream buffer = new MemoryStream())
{
using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Write))
{
using (StreamWriter writer = new StreamWriter(stream, Encoding.Unicode))
{
writer.Write(value);
}
}
return Convert.ToBase64String(buffer.ToArray());
}
}
public static string Decrypt<T>(string text, string password, string salt)
where T : SymmetricAlgorithm, new()
{
DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
SymmetricAlgorithm algorithm = new T();
byte[] rgbKey = rgb.GetBytes(algorithm.KeySize >> 3);
byte[] rgbIV = rgb.GetBytes(algorithm.BlockSize >> 3);
ICryptoTransform transform = algorithm.CreateDecryptor(rgbKey, rgbIV);
using (MemoryStream buffer = new MemoryStream(Convert.FromBase64String(text)))
{
using (CryptoStream stream = new CryptoStream(buffer, transform, CryptoStreamMode.Read))
{
using (StreamReader reader = new StreamReader(stream, Encoding.Unicode))
{
return reader.ReadToEnd();
}
}
}
}
}
Thank You,
Miguel
On a newsletter I received I see something like /unsubscribe?u=16b832d9ad4b28edf261f56df. I was looking for something like this with the email somehow "hidden"
This is not "hidden." All this is a reference to a repository (e.g. a database) that contains all the information necessary to unsubscribe. Essentially a key into a record that contains all the necessary info about a subscriber.
If feasible, that'll probably be easier approach than to encrypt individual values in a URL.
If you still want to encrypt the value (to avoid storage in DB and redesign), what's the issue with having = at the end of a URL? It's just a character as part of encrypted output?
I'm not sure what I'm doing wrong, the encryption it seems to work but when you get to the decryption says bad data when trying to deserialize it, not sure what I'm doing wrong. I'm new at doing encryption so if it's something really simple I'm sorry.
public byte[] Serialize(object obj, string key)
{
byte[] returnBytes;
using (MemoryStream memory = new MemoryStream())
{
UTF8Encoding UTF8 = new UTF8Encoding();
TripleDESCryptoServiceProvider crypt = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] pass = provider.ComputeHash(UTF8.GetBytes(key));
crypt.Key = pass;
crypt.Mode = CipherMode.ECB;
crypt.Padding = PaddingMode.PKCS7;
using (CryptoStream stream = new CryptoStream(memory, crypt.CreateEncryptor(), CryptoStreamMode.Write))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Close();
memory.Close();
}
returnBytes = memory.ToArray();
}
return returnBytes;
}
public object Deserialize(byte[] inBytes, string key)
{
object returnObj;
using (MemoryStream memory = new MemoryStream())
{
UTF8Encoding UTF8 = new UTF8Encoding();
TripleDESCryptoServiceProvider crypt = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] pass = provider.ComputeHash(UTF8.GetBytes(key));
crypt.Key = pass;
crypt.Mode = CipherMode.ECB;
crypt.Padding = PaddingMode.PKCS7;
using (CryptoStream stream = new CryptoStream(memory, crypt.CreateDecryptor(), CryptoStreamMode.Read))
{
BinaryFormatter formatter = new BinaryFormatter();
returnObj = formatter.Deserialize(stream);
stream.Close();
memory.Close();
}
return returnObj;
}
}
This code i did a while back works on strings
public string encrypt(string message, string password)
{
byte[] result;
UTF8Encoding UTF8 = new UTF8Encoding();
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] key = provider.ComputeHash(UTF8.GetBytes(password));
TripleDESCryptoServiceProvider algorithm = new TripleDESCryptoServiceProvider();
algorithm.Key = key;
algorithm.Mode = CipherMode.ECB;
algorithm.Padding = PaddingMode.PKCS7;
byte[] data = UTF8.GetBytes(message);
try
{
ICryptoTransform encryptor = algorithm.CreateEncryptor();
result = encryptor.TransformFinalBlock(data, 0, data.Length);
}
finally
{
algorithm.Clear();
provider.Clear();
}
return Convert.ToBase64String(result);
}
public string decrypt(string message, string passsword)
{
byte[] result;
UTF8Encoding UTF8 = new UTF8Encoding();
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] key = provider.ComputeHash(UTF8.GetBytes(passsword));
TripleDESCryptoServiceProvider algorithm = new TripleDESCryptoServiceProvider();
algorithm.Key = key;
algorithm.Mode = CipherMode.ECB;
algorithm.Padding = PaddingMode.PKCS7;
byte[] data = Convert.FromBase64String(message);
try
{
ICryptoTransform decryptor = algorithm.CreateDecryptor();
result = decryptor.TransformFinalBlock(data, 0, data.Length);
}
finally
{
algorithm.Clear();
provider.Clear();
}
return UTF8.GetString(result);
}
You're not setting the IV property of crypt, so it's starting off as a random value each time. You need to set it to the same value when decrypting as when encrypting - like a salt for hashing. EDIT: Given the way ECB works, it looks like the IV may be ignored, which is why your previous code worked without storing it.
EDIT: While the IV part is certainly required for non-ECB, it's not enough. I'm not sure what the rest of the problem is, although:
The ECB cipher mode isn't recommended - any reason for using it?
You may well end up running into problems due to padding; I don't know if BinaryFormatter handles that for you automatically, but it's worth looking into.
EDIT: Doh - I've worked out the bigger problem; you should indeed be using inBytes, as per Elian's comment. Currently you're completely ignoring the cipher-text - that's got no chance of working!
Here's a complete program showing the whole thing hanging together:
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;
class Test
{
static void Main()
{
byte[] data = Serialize("Some arbitrary test data", "pass");
object x = Deserialize(data, "pass");
Console.WriteLine(x);
}
private static SymmetricAlgorithm CreateCryptoServiceProvider(string key)
{
byte[] passwordHash;
using (MD5 md5 = MD5.Create())
{
// It's not clear why you're taking the hash of the password...
passwordHash = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
}
var crypt = new TripleDESCryptoServiceProvider();
crypt.Key = passwordHash;
crypt.Mode = CipherMode.CBC; // This is the default anyway - can remove
crypt.Padding = PaddingMode.PKCS7; // Ditto
// Fix this to use a randomly generated one and store it for real code.
crypt.IV = new byte[crypt.BlockSize / 8];
return crypt;
}
public static byte[] Serialize(object obj, string key)
{
var provider = CreateCryptoServiceProvider(key);
using (MemoryStream memory = new MemoryStream())
{
using (CryptoStream stream = new CryptoStream(
memory, provider.CreateEncryptor(), CryptoStreamMode.Write))
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
}
return memory.ToArray();
}
}
public static object Deserialize(byte[] inBytes, string key)
{
var provider = CreateCryptoServiceProvider(key);
using (MemoryStream memory = new MemoryStream(inBytes))
{
using (CryptoStream stream = new CryptoStream(
memory, provider.CreateDecryptor(), CryptoStreamMode.Read))
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
}
}
}
I'm getting a bit desperate here. I'm trying to write an encrypted file with a serialized object to disk and later retrieve the file, decrypt it and deserialize the object back.
UPDATE:
I refactored the code to this:
using (Stream innerStream = File.Create(this.GetFullFileNameForUser(securityContext.User, applicationName)))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateEncryptor(), CryptoStreamMode.Write))
{
// 3. write to the cryptoStream
//BinaryFormatter bf = new BinaryFormatter();
//bf.Serialize(cryptoStream, securityContext);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
xs.Serialize(cryptoStream, securityContext);
}
}
using (Stream innerStream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open))
{
using (Stream cryptoStream = new CryptoStream(innerStream, GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read))
{
//BinaryFormatter bf = new BinaryFormatter();
//return (SecurityContextDTO)bf.Deserialize(cryptoStream);
XmlSerializer xs = new XmlSerializer(typeof(SecurityContextDTO));
//CryptographicException here
return (SecurityContextDTO)xs.Deserialize(cryptoStream);
}
}
Now I'm getting a cryptographic exception on deserialize: Bad Data
ORIGINAL:
I'm doing this:
public void StoreToFile(SecurityContextDTO securityContext, string applicationName)
{
if (securityContext.LoginResult.IsOfflineMode == false)
{
Stream stream = null;
CryptoStream crStream = null;
try
{
TripleDESCryptoServiceProvider cryptic = GetCryptoProvider();
stream = File.Open(this.GetFullFileNameForUser(securityContext.User, applicationName), FileMode.Create);
crStream = new CryptoStream(stream,
cryptic.CreateEncryptor(), CryptoStreamMode.Write);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(crStream, securityContext);
}
catch(Exception)
{
throw;
}
finally
{
if (crStream != null)
crStream.Close();
}
}
}
public SecurityContextDTO RetrieveFromFile(UserDTO user,string applicationName)
{
SecurityContextDTO objectToSerialize;
Stream stream = null;
CryptoStream crStream=null;
try
{
stream = File.Open(this.GetFullFileNameForUser(user, applicationName), FileMode.Open);
crStream= new CryptoStream(stream,
GetCryptoProvider().CreateDecryptor(), CryptoStreamMode.Read);
BinaryFormatter bFormatter = new BinaryFormatter();
//Exception here
objectToSerialize = (SecurityContextDTO)bFormatter.Deserialize(crStream);
}
catch (Exception)
{
objectToSerialize = null;
}
finally
{
if (crStream!=null)
crStream.Close();
}
return objectToSerialize;
}
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose();
}
return cryptic;
}
Encrypting and writing works fine, the file appears on the disk and the content is there (encrypted of course). But when I call the retrieve method I always get a SerializationException
Binary stream '30' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
When I leave the cryptographic methods out everything works fine.
So,
You realize that in this code
private static TripleDESCryptoServiceProvider GetCryptoProvider()
{
TripleDESCryptoServiceProvider cryptic = new TripleDESCryptoServiceProvider();
try
{
cryptic.Key = ASCIIEncoding.ASCII.GetBytes(CrypKey);
Rfc2898DeriveBytes db = new Rfc2898DeriveBytes("sdddsdsd", 8);
cryptic.IV = db.GetBytes(8);
}
catch (Exception)
{
throw;
}
finally
{
cryptic.Dispose(); // <------- Don't do this until you are done decrypting.
}
return cryptic;
}
you will ALWAYS dispose of the provider meaning you are always using a random key and iv
You are close. However, the stream you pass into the creation of CryptoStream is always, always, always the buffer that will hold your end result. It is not the stream that holds the data you want to encrypt or decrypt. I put the emphasis in there because I remember learning this for the first time and I did exactly what you were doing. So here:
// this is for encryption
var memStreamEncryptedData = new MemoryStream();
var encryptStream = new CryptoStream(memStreamEncryptedData,
transform, CryptoStreamMode.Write);
// this is for decryption
var memStreamDecryptedData = new MemoryStream();
var decryptStream = new CryptoStream(memStreamDecryptedData,
transform, CryptoStreamMode.Write);
Notice in both cases, CryptoStream is being initialized with a blank output stream. Your stream does not enter into the picture until later. So, during a write, you will do the following:
encryptStream.Write(dataToBeEncrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamEncryptedData now safely holds your encrypted data
And during the read, you will:
decryptStream.Write(dataToBeDecrypted);
encryptStream.FlushFinalBlock();
encryptStream.Close();
// memStreamDecryptedData now safely holds your decrypted data
So, to save you some trouble, here's a nice simple Symmetric method that will perform both encryption and decryption. The only difference between this and yours is that I am working directly on byte arrays, but perhaps that augmentation can be an exercise:
public static byte[] Symmetric(bool encrypt, byte[] plaintext, string ikey)
{
if (plaintext.Length == 0) return plaintext;
// setting up the services can be very expensive, so I'll cache them
// into a static dictionary.
SymmetricSetup setup;
if (!_dictSymmetricSetup.TryGetValue(ikey, out setup))
{
setup = new SymmetricSetup();
setup.des = new DESCryptoServiceProvider { Mode = CipherMode.CBC,
Padding = PaddingMode.Zeros };
setup.hash = Hash(Encoding.ASCII.GetBytes(ikey));
setup.key = setup.hash.ForceLength(8, 0);
setup.IV = Encoding.ASCII.GetBytes("init vec");
setup.des.Key = setup.key;
setup.des.IV = setup.IV;
setup.encrypt = setup.des.CreateEncryptor(setup.des.Key, setup.des.IV);
setup.decrypt = setup.des.CreateDecryptor(setup.des.Key, setup.des.IV);
_dictSymmetricSetup[ikey] = setup;
}
var transform = encrypt ? setup.encrypt : setup.decrypt;
var memStreamEncryptedData = new MemoryStream();
var encStream = new CryptoStream(memStreamEncryptedData, transform, CryptoStreamMode.Write);
if (encrypt)
encStream.Write(new[] {(byte) ((8 - (plaintext.Length + 1)%8)%8)}, 0, 1);
encStream.Write(plaintext, 0, plaintext.Length);
encStream.FlushFinalBlock();
encStream.Close();
memStreamEncryptedData.Flush();
var ciphertext = memStreamEncryptedData.ToArray();
byte b;
if (!encrypt)
if (byte.TryParse("" + ciphertext[0], out b))
ciphertext = ciphertext.Skip(1).Take(ciphertext.Length - b - 1).ToArray();
return ciphertext;
}
And to call it, you might do something like this:
static public byte[] DecryptData(this byte[] source, string password) {
return Symmetric(false, source, password);
}
static public byte[] EncryptData(this byte[] source, string password) {
return Symmetric(true, source, password);
}
Again, you'll do something slightly different to work with streams, but hopefully you get the gist. Instead of MemoryStream, it will be whatever stream you need to feed into your serializer.
Some previous posts that can be of use:
How do I encrypt a string in vb.net using RijndaelManaged, and using PKCS5 padding?
Does BinaryFormatter apply any compression?
In later, you can see how I stacked compression with encryption with serialization. And it works.