I'm trying to use AES to see how encryption/decryption works. Encrypting files works fine with the following code:
(These methods are in two separate files)
private void tempEncrypt()
{
// Creates file with "Test String" inside
byte[] test = Encoding.ASCII.GetBytes("Test String");
var file = File.Create("test.txt");
file.Write(test, 0, test.Length);
// Saves key and IV for decryption
var temp = new AesCryptoServiceProvider();
Console.WriteLine(System.Convert.ToBase64String(temp.Key));
Console.WriteLine(System.Convert.ToBase64String(temp.IV));
Encryptor.Encrypt(file, temp.Key, temp.IV);
}
public static void Encrypt(FileStream source, byte[] key, byte[] IV)
{
// Creates a temp file for encrypting
var destination = File.Create("encrypted.tmp");
string path = source.Name;
using (var provider = new AesCryptoServiceProvider())
using (var transform = provider.CreateEncryptor(key, IV))
using (var cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
{
// Encrypts file
source.CopyTo(cryptoStream);
source.Close();
// Deletes unencrypted file
File.Delete(path);
}
// Replaces source file with encrypted file
destination.Close();
File.Move(destination.Name, path);
File.Delete(destination.Name);
}
But when I use this to decrypt the file, the file will be empty:
private void tempDecrypt()
{
// Opens encrypted file
var file = File.OpenRead("test.txt");
var temp = new AesCryptoServiceProvider();
temp.Key = System.Convert.FromBase64String("SANeQe1MK4UKrQmJ4fa16lrhIexK7gaxqE/N/HycdhI=");
temp.IV = System.Convert.FromBase64String("Pb2SciISBP2p0hWzEUG05A==");
Encryptor.Decrypt(file, temp.Key, temp.IV);
}
public static void Decrypt(FileStream source, byte[] key, byte[] IV)
{
// Creates a temp file for decrypting
var destination = File.Create("decrypted.tmp");
string path = source.Name;
Console.WriteLine(source.Length);
// Decrypts rest of file
using (var provider = new AesCryptoServiceProvider())
using (var transform = provider.CreateDecryptor(key, IV))
using (var cryptoStream = new CryptoStream(source, transform, CryptoStreamMode.Read))
{
// Decrypts file
cryptoStream.CopyTo(destination);
}
// Replaces source file with decrypted file
destination.Close();
source.Close();
File.Delete(path);
File.Move(destination.Name, path);
File.Delete(destination.Name);
}
Replacing the file doesn't seem to be the problem because even "decrypted.tmp" is empty before I replace the destination file with the source one.
In the tempEncrypt() method, I had to close the file then re-open using File.OpenRead() for it to decrypt properly. I guess test.txt was still empty even though I used file.Write() to write to the file. Here is the working method:
private void tempEncrypt()
{
// Creates file with "Test String" inside
byte[] test = Encoding.ASCII.GetBytes("Test String");
var file = File.Create("test.txt");
file.Write(test, 0, test.Length);
file.Close();
var newFile = File.OpenRead("test.txt");
// Saves key and IV for decryption
var temp = new AesCryptoServiceProvider();
Console.WriteLine(System.Convert.ToBase64String(temp.Key));
Console.WriteLine(System.Convert.ToBase64String(temp.IV));
Encryptor.Encrypt(newFile, temp.Key, temp.IV);
}
Related
I need to correct an encryption method written in C#.
First, a little background: I am taking charge of an existing web application with an ecma6 / html frontend and c# web api .net standard 4.6 backend.
It has many integrations with different customers for user identification. Some of the integrations simply navigate to a customers URL to do a login process on the infrastructure of the customer, and then return to the app with an encripted user token in the URL's query string.
This token is encripted using AES256 encryption.
The backend is correctly decrypting the tokens, but when I tried to use the encryption routine to build a unit test, I discovered something is wrong. When I encrypt and then decrypt a message, the decryption routine throws the following error:
Unhandled Exception:
System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.
Input message is "key1=value1;key2=value2" (without the quotes)
Encrypted message I get is NzcrOTc3Kzk3Nys5NzcrOTc3Kzk3Nys5NzcrOVpsVHZ2NzF3NzcrOUZ6UVlRZ3Z2djcxSVlPKy92U0V6NzcrOVNqZFY3Nys5VHpBZA==
I need to correct the implementation error in the encryption method. The implementation of the decryption method shows expected behavior, and you'll notice a double Base64 decoding done on the encrypted string: this is given, as we are integrated with an already developed encryption routine done by a customer in PERL which we detected did double encoding.
I inspected the order of operations to see a mismatch among the encryption and decryption and I was unable to detect an inconsistency, so the need to ask for help.
The code I synthesized for this test is:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class MainClass {
public static void Main (string[] args) {
var secretKey = "This is my secret key";
var secretIV = "This is my secret iv";
var originalMessage = "key1=value1;key2=value2";
var userToken = Cryptography.EncryptAES256CBCBase64x2(originalMessage, secretKey, secretIV);
Console.WriteLine(userToken);
var unencryptedToken = Cryptography.DecryptAES256CBCBase64x2(userToken, secretKey, secretIV);
if (originalMessage == unencryptedToken)
Console.WriteLine("All fine!");
else
Console.WriteLine("Error!");
}
}
public static class Cryptography
{
public static string DecryptAES256CBCBase64x2(string base64EncryptedString, string secretKey, string secretIV)
{
base64EncryptedString = SaveBase64String(base64EncryptedString);
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var ivBytes = Encoding.UTF8.GetBytes(secretIV);
var hash = SHA256.Create();
var keyHash = hash.ComputeHash(keyBytes);
Array.Resize(ref keyHash, 32);
var keyHashString = string.Empty;
foreach (byte x in keyHash)
keyHashString += string.Format("{0:x2}", x);
keyHash = Encoding.UTF8.GetBytes(keyHashString.Substring(0, 32));
var ivHash = hash.ComputeHash(ivBytes);
Array.Resize(ref ivHash, 16);
var ivHashString = string.Empty;
foreach (byte x in ivHash)
ivHashString += string.Format("{0:x2}", x);
ivHash = Encoding.UTF8.GetBytes(ivHashString.Substring(0, 16));
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged())
{
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.Mode = CipherMode.CBC;
rijAlg.Key = keyHash;
rijAlg.IV = ivHash;
var encryptedBytes =
Convert.FromBase64String(
Encoding.UTF8.GetString(
Convert.FromBase64String(base64EncryptedString)));
// Create a decryptor to perform the stream transform.
var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(encryptedBytes))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
return srDecrypt.ReadToEnd();
}
}
}
}
}
public static string EncryptAES256CBCBase64x2(string baseString, string secretKey, string secretIV)
{
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var ivBytes = Encoding.UTF8.GetBytes(secretIV);
var hash = SHA256.Create();
var keyHash = hash.ComputeHash(keyBytes);
Array.Resize(ref keyHash, 32);
var keyHashString = string.Empty;
foreach (byte x in keyHash)
keyHashString += string.Format("{0:x2}", x);
keyHash = Encoding.UTF8.GetBytes(keyHashString.Substring(0, 32));
var ivHash = hash.ComputeHash(ivBytes);
Array.Resize(ref ivHash, 16);
var ivHashString = string.Empty;
foreach (byte x in ivHash)
ivHashString += string.Format("{0:x2}", x);
ivHash = Encoding.UTF8.GetBytes(ivHashString.Substring(0, 16));
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged())
{
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.Mode = CipherMode.CBC;
rijAlg.Key = keyHash;
rijAlg.IV = ivHash;
var encryptedBytes = Encoding.UTF8.GetBytes(baseString);
// Create a encryptor to perform the stream transform.
var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (var msEncrypt = new MemoryStream(encryptedBytes))
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Read))
{
using (var srEncrypt = new StreamReader(csEncrypt))
{
// Read the encrypted bytes from the encrypting stream
// and place them in a string.
var result = srEncrypt.ReadToEnd();
return Convert.ToBase64String(
Encoding.UTF8.GetBytes(
Convert.ToBase64String(
Encoding.UTF8.GetBytes(result))));
}
}
}
}
}
public static string SaveBase64String(string data)
{
data = data.Replace("-", "+").Replace("_", "/");
var mod = data.Length % 4;
if (mod > 2)
mod = 1;
return data + string.Empty.PadRight(mod, '=');
}
}
At the following link an online example is available for you to try: https://repl.it/#ormasoftchile/Test-encrypt-decrypt
Thank you everyone.
In the current code, the ciphertext is stored in a string (StreamReader.ReadToEnd), which generally doesn't work, since the data are corrupted thereby. Instead, the ciphertext should be stored in a byte-array, which can be Base64-encoded if required.
To fix the problem
remove the line:
var encryptedBytes = Encoding.UTF8.GetBytes(baseString);
and replace the entire MemoryStream-block by:
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(baseString);
}
var encryptedBytes = msEncrypt.ToArray();
return Convert.ToBase64String(Encoding.UTF8.GetBytes(Convert.ToBase64String(encryptedBytes)));
}
}
Another point is the double Base64-encoding/decoding. This makes no sense and is simply redundant and degrades performance. If possible, this should be changed.
I made a console app to decrypt a file . Please refer to the screenshot for detail error message.
If you copy paste the code in a console app . You should be able to debug .
1) Need to make folder SourceFolder\Newfolder\ and a new txt file destination.txt
2) Need to make folder for C:\DestinationFolder\source.txt(encrypted file cannot attach file here i hope you can make one
using System;
using System.IO;
using System.Security.Cryptography;
namespace ConsoleApp5
{
class Program
{
//SALT is a random data that is used as addition to a password to encrypt data
// The primary function is to protect against lists of often used password
private static readonly byte[] SALT = new byte[] {0x26,0xdc,0xff,0x76,0x76,
0xad,0xed,0x7a,0x64,0xc5,0xfe
,0x20,0xaf,0x4d,0x08,0x3c};
static void Main(string[] args)
{
//Need to make a SourceFolder and but the file in there abc.txt
string path = #"C:\SourceFolder\New folder\";
string[] txtFile = Directory.GetFiles(path, "*.txt");
string fileinnn = txtFile[0];
//Get the filepath of the decrypted file. Need to make this folder and add a new file that is what i am donig for now for this cosole app
string filepathDecrypted = #"C:\DestinationFolder\destination.txt"; //this is a new file need to create
//Get the password
string encrytionKey = "password.";
Decrypt(fileinnn, filepathDecrypted, encrytionKey);
}
public static void Decrypt(string fileIn, string fileOut, string Password)
{
//open filestreat for encrypted source file
using (System.IO.FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read))
{
using (System.IO.FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write))
{
try
{
//Create Key and IV from the password with the SALT
Rfc2898DeriveBytes pdf = new Rfc2898DeriveBytes(Password, SALT);
//Create a symmetric algorithm with Rijndael
Rijndael alg = Rijndael.Create();
alg.Padding = PaddingMode.PKCS7;
//alg.BlockSize = 128;
//SET key and IV
alg.Key = pdf.GetBytes(32);
alg.IV = pdf.GetBytes(16);
//Create a cryptoStream
using (CryptoStream cs = new CryptoStream(fsOut, alg.CreateDecryptor(), CryptoStreamMode.Write))
{
//Intialize the buffer and process the input in chunks
// this is done to avoid reading the whole file which is huge and memory consumption.
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
do
{ //read a chunck of data from the input file
bytesRead = fsIn.Read(buffer, 0, bufferLen);
//Decrypt it
cs.Write(buffer, 0, bytesRead);
}
while (bytesRead != 0);
//close everything
cs.Close(); //this is where it throws exception
fsOut.Close();
fsIn.Close();
}
}
catch (Exception ex)
{
var error = ex.Message;
throw;
}
}
}
}
}
}
Error message that i am getting
I wanted to know if there is a code that encrypts and decrypts a file using AES in C#?I have seen some code about encrypting and decrypting a text in c# using aes but
encrypting and decrypting a file in c# ..there was no full code to understand it well..If somebody can help me please?
In general, you don't want to encrypt a file. That is, you don't want to write a file, then encrypt it. The data is probably in a different sector of the storage device, and can likely be recovered. (Of course, if you're trying to write ransomware, by all means write it poorly). What you want to do instead is encrypt contents before they make it to disk.
What you asked for
public static void EncryptFile(string filePath, byte[] key)
{
string tempFileName = Path.GetTempFileName();
using (SymmetricAlgorithm cipher = Aes.Create())
using (FileStream fileStream = File.OpenRead(filePath))
using (FileStream tempFile = File.Create(tempFileName))
{
cipher.Key = key;
// aes.IV will be automatically populated with a secure random value
byte[] iv = cipher.IV;
// Write a marker header so we can identify how to read this file in the future
tempFile.WriteByte(69);
tempFile.WriteByte(74);
tempFile.WriteByte(66);
tempFile.WriteByte(65);
tempFile.WriteByte(69);
tempFile.WriteByte(83);
tempFile.Write(iv, 0, iv.Length);
using (var cryptoStream =
new CryptoStream(tempFile, cipher.CreateEncryptor(), CryptoStreamMode.Write))
{
fileStream.CopyTo(cryptoStream);
}
}
File.Delete(filePath);
File.Move(tempFileName, filePath);
}
public static void DecryptFile(string filePath, byte[] key)
{
string tempFileName = Path.GetTempFileName();
using (SymmetricAlgorithm cipher = Aes.Create())
using (FileStream fileStream = File.OpenRead(filePath))
using (FileStream tempFile = File.Create(tempFileName))
{
cipher.Key = key;
byte[] iv = new byte[cipher.BlockSize / 8];
byte[] headerBytes = new byte[6];
int remain = headerBytes.Length;
while (remain != 0)
{
int read = fileStream.Read(headerBytes, headerBytes.Length - remain, remain);
if (read == 0)
{
throw new EndOfStreamException();
}
remain -= read;
}
if (headerBytes[0] != 69 ||
headerBytes[1] != 74 ||
headerBytes[2] != 66 ||
headerBytes[3] != 65 ||
headerBytes[4] != 69 ||
headerBytes[5] != 83)
{
throw new InvalidOperationException();
}
remain = iv.Length;
while (remain != 0)
{
int read = fileStream.Read(iv, iv.Length - remain, remain);
if (read == 0)
{
throw new EndOfStreamException();
}
remain -= read;
}
cipher.IV = iv;
using (var cryptoStream =
new CryptoStream(tempFile, cipher.CreateDecryptor(), CryptoStreamMode.Write))
{
fileStream.CopyTo(cryptoStream);
}
}
File.Delete(filePath);
File.Move(tempFileName, filePath);
}
What you really want
Instead of writing the original file via a FileStream, open the file, write the header and IV, create the CryptoStream, and use the CryptoStream for everything. There's no reason to ever let the unencrypted form be on disk.
I have written a process where a file is encrypted and uploaded to Azure, then the download process has to be decrypted which is what fails with a "Padding is invalid and cannot be removed" error, or a "Length of the data to decrypt is invalid." error.
I've tried numerous solutions online, including C# Decrypting mp3 file using RijndaelManaged and CryptoStream, but none of them seem to work and I end up just bouncing back and forth between these two errors. The encryption process uses the same key/IV pair that decryption uses, and since it will decrypt a portion of the stream I feel like that's working fine - it just ends up dying with the above errors.
Here is my code, any ideas? Please note that the three variants (cryptoStream.CopyTo(decryptedStream), do {} and while) aren't run together - they are here to show the options I've already tried, all of which fail.
byte[] encryptedBytes = null;
using (var encryptedStream = new MemoryStream())
{
//download from Azure
cloudBlockBlob.DownloadToStream(encryptedStream);
//reset positioning for reading it back out
encryptedStream.Position = 0;
encryptedBytes = encryptedStream.ConvertToByteArray();
}
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
//fails here with "Length of the data to decrypt is invalid." error
cryptoStream.CopyTo(decryptedStream);
int data;
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
do
{
data = cryptoStream.ReadByte();
decryptedStream.WriteByte((byte)cryptoStream.ReadByte());
} while (!cryptoStream.HasFlushedFinalBlock);
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
while ((data = cryptoStream.ReadByte()) != -1)
{
decryptedStream.WriteByte((byte)data);
}
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
One of the comments mentioned wanting to know what ConvertToByteArray is, and it's just a simple extension method:
/// <summary>
/// Converts a Stream into a byte array.
/// </summary>
/// <param name="stream">The stream to convert.</param>
/// <returns>A byte[] array representing the current stream.</returns>
public static byte[] ConvertToByteArray(this Stream stream)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
The code never reaches this though - it dies before I can ever get it to this point.
After a lot of back and forth from various blogs, I found I actually had a couple of errors in the above code that were nailing me. First, the encryption process was incorrectly writing the array - it was wrapped with a CryptoStream instance, but wasn't actually utilizing that so I was writing the unencrypted data to Azure. Here is the proper route to go with this (fileKey is part of a custom class I created to generate Key/IV pairs, so wherever that is referenced can be changed to the built-in process from RijndaelManaged or anything else you'd utilize for coming up with a key/IV pair):
using (var aes = new RijndaelManaged { KeySize = 256, Key = fileKey.Key, IV = fileKey.IV })
{
using (var encryptedStream = new MemoryStream())
{
using (ICryptoTransform encryptor = aes.CreateEncryptor())
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
{
using (var originalByteStream = new MemoryStream(file.File.Data))
{
int data;
while ((data = originalByteStream.ReadByte()) != -1)
cryptoStream.WriteByte((byte)data);
}
}
}
var encryptedBytes = encryptedStream.ToArray();
return encryptedBytes;
}
}
Second, since my encryption process involves multiple steps (three total keys per file - container, filename and file itself), when I tried to decrypt, I was using the wrong key (which is seen above when I referenced blobKey to decrypt, which was actually the key used for encrypting the filename and not the file itself. The proper decryption method was:
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
int data;
while ((data = cryptoStream.ReadByte()) != -1)
decryptedStream.WriteByte((byte)data);
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
I had looked into the Azure Encryption Extensions (http://www.stefangordon.com/introducing-azure-encryption-extensions/), but it was a little more local file-centric than I was interested - everything on my end is streams/in-memory only, and retrofitting that utility was going to be more work than it was worth.
Hopefully this helps anyone looking to encrypt Azure blobs with zero reliance on the underlying file system!
Bit late to the party, but in case this is useful to someone who finds this thread:
The following works well for me.
internal static byte[] AesEncryptor(byte[] key, byte[] iv, byte[] payload)
{
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
var encryptor = aesAlg.CreateEncryptor(key, iv);
var encrypted = encryptor.TransformFinalBlock(payload, 0, payload.Length);
return iv.Concat(encrypted).ToArray();
}
}
and to decrypt:
internal static byte[] AesDecryptor(byte[] key, byte[] iv, byte[] payload)
{
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
return decryptor.TransformFinalBlock(payload, 0, payload.Length);
}
}
this works for encrypting/decrypting both fixed length hex strings when decoded from hex to byte[] as well as utf8 variable length strings when decoded using Encoding.UTF8.GetBytes().
I've used AESManaged Class to encrypt a zip file, but it couldn't be decompressed by winzip/7zip. I can only decompress it after decrypting in my code.
Below is the code I used to encrypt and decrypt. Anyone can help?
private static void EncryptFile(string input, string output, string pwd)
{
using (AesManaged aes = new AesManaged())
{
FileStream fsCrypt=null;
try
{
byte[] key = Encoding.UTF8.GetBytes(pwd);
fsCrypt = new FileStream(output, FileMode.Create);
using (CryptoStream cs = new CryptoStream(fsCrypt, aes.CreateEncryptor(key, key), CryptoStreamMode.Write))
{
using (FileStream fsIn = new FileStream(input, FileMode.Open))
{
int data;
while ((data = fsIn.ReadByte()) != -1)
{
cs.WriteByte((byte)data);
}
aes.Clear();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
aes.Clear();
}
finally
{
if(fsCrypt!=null)
{
fsCrypt.Dispose();
}
}
}
}
private static void DecryptFile(string input, string output, string pwd)
{
using (AesManaged aes = new AesManaged())
{
FileStream fsCrypt = null;
try
{
byte[] key = Encoding.UTF8.GetBytes(pwd);
fsCrypt = new FileStream(input, FileMode.Open);
{
using (FileStream fsOut = new FileStream(output, FileMode.Create))
{
using (CryptoStream cs = new CryptoStream(fsCrypt, aes.CreateDecryptor(key, key), CryptoStreamMode.Read))
{
int data;
while ((data = cs.ReadByte()) != -1)
{
fsOut.WriteByte((byte)data);
}
aes.Clear();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
aes.Clear();
}
finally
{
if (fsCrypt != null)
{
fsCrypt.Dispose();
}
}
}
}
You are overwriting the internal structure of a zip file with your encryption algorithm.
How could you expect that an external zip manager recognizes your encrypted file as a valid zip file?
If you really want to use a password protected zip file then use a library that can do this for you without destroying the zip file structure.
I recommend this library DotNetZip
It is not possible to unzip a file if the format is not that of zip. Once you encrypt a file you the format is no longer zip.
But it is possible to perform both encryption and compression in C#. For better compression ratio you would need to compress the file first and then encrypt.
You can use GZipstream to compress and the code you have depicted to encrypt.