Store and retrieve AES key to file - c#

how do you store AES key to file and then retrieve it?
I have tried saving it as string to a text file then retrieve it back and convert it to byte, but the decryption never works…
using (var provider = new AesCryptoServiceProvider())
{
var cryptoTransform = provider.CreateEncryptor();
Key = provider.Key;
IV = provider.IV;
string key_string = Encoding.ASCII.GetString(Key);
File.WriteAllText(#"C:\Documents\AES\Key.txt", key_string);
string string_key = System.IO.File.ReadAllText(#"C:\Documents\AES\Key.txt");
testKey_bytes = Encoding.ASCII.GetBytes(string_key); ;

As mentioned before you can save it using File.WriteAllBytes() and read it back using File.ReadAllBytes().
But you also have to store the IV (at least in CBC mode). This can be done via the BinaryReader and BinaryWriter. Please be assured that your key will be stored in a safe place:
private static void SaveIVAndKey(AesCryptoServiceProvider provider)
{
using (FileStream fileStream = new FileStream("YourKeyFile.txt", FileMode.OpenOrCreate, FileAccess.Write))
{
using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
{
binaryWriter.Write(provider.IV.Length);
binaryWriter.Write(provider.IV);
binaryWriter.Write(provider.Key.Length);
binaryWriter.Write(provider.Key);
}
}
}
To read it back in, you can use the following method:
private static void LoadIVAndKey(AesCryptoServiceProvider provider)
{
using (FileStream fileStream = new FileStream("YourKeyFile.txt", FileMode.Open, FileAccess.Read))
{
using (BinaryReader binaryReader = new BinaryReader(fileStream))
{
provider.IV = binaryReader.ReadBytes(binaryReader.ReadInt32());
provider.Key = binaryReader.ReadBytes(binaryReader.ReadInt32());
}
}
}

I've managed to work it out:)
File.WriteAllBytes(#"C:\Documents\AES\Key.txt", Key.ToArray());
testKey_bytes = File.ReadAllBytes(#"C:\Documents\AES\Key.txt");

Related

How to read contents of MemoryStream, fed by a cryptostream

I am working on some AES encryption in C#. I have a similar decryption method which functions flawlessly, however, no matter what I try I cannot read the encrypted contents of the MemoryStream
I have tried a few different ways of reading,
ms.Position = 0;
return new StreamReader(ms, Encoding.ASCII).ReadToEnd()
OR
using (StreamReader sr = new StreamReader(cs)) {
return sr.ReadToEnd();
}
OR
byte[] enc = ms.ToArray();
string ret=null;
foreach (byte b in enc) {
ret += b.ToString();
}
Here's the snippet from the code.
using (AesManaged aesMan = new AesManaged()) {
if (keystr.Length == aesSize/8)
{
//Its a valid key
aesMan.KeySize = aesSize;
aesMan.Key = Encoding.UTF8.GetBytes(keystr);
aesMan.IV = Encoding.UTF8.GetBytes(ivstr);
ICryptoTransform encryptor aesMan.CreateEncryptor(aesMan.Key, aesMan.IV);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(inpstr);
using (StreamReader sr = new StreamReader(ms)) {
return sr.ReadToEnd();
}
}
}
I get various errors, such as the stream is not readable, or that it cannot read a closed stream, as well as a blank string being returned.
Has anyone got any ideas? I'm at a loss
Most of those stream functions like StreamReader, StreamWriter, etc., close the underlying stream when you Dispose() them. Try not disposing them until you are done, or using the constructors that allow you to chose not to close the underlying stream. In rare cases, I've had to implement a dummy wrapper around a stream to prevent closing the underlying stream

Encryption of file using algorithm Salsa20

I'm doing my homework. It's connected with encryption of file.
I use algorithm Salsa20
Here's my code:
using (var salsa = new Salsa20.Salsa20())
{
using (var fstream_out = new FileStream(filePath, FileMode.Truncate, FileAccess.ReadWrite, FileShare.Write))
{
salsa.Key = key;
salsa.IV = iv;
using (var cstream = new CryptoStream(fstream_out, salsa.CreateEncryptor(), CryptoStreamMode.Write))
{
var bytes = File.ReadAllBytes(filePath);
cstream.Write(bytes, 0, 1000000);
}
}
}
When I try to encrypt file, there's exception "The process cannot access the file because it is being used by another process."
What's wrong?

Handle Convert.ToBase64String out of memory exception when converting to string

When I try to do the following with .zip folder witch contains some videos I get out of memory exeption.
Byte[] bytes = File.ReadAllBytes(#"C:\folderWithVideos.zip");
String base64File= Convert.ToBase64String(bytes);//<----- out of memory exception
How to handle this exception properly? I mean without try-catch, I have tried something like:
String base64File;
if (bytes.Length <= System.Int32.MaxValue)
base64File = Convert.ToBase64String(bytes);
But it didn't helped, but bytes.Length <= 255 did helped, but I'm not sure that 255 is the right number.
Based on the code shown in the blog the following code works.
// using System.Security.Cryptography
private void ConvertLargeFile()
{
//encode
var filein = #"C:\Users\test\Desktop\my.zip";
var fileout = #"C:\Users\test\Desktop\Base64Zip";
using (FileStream fs = File.Open(fileout, FileMode.Create))
using (var cs = new CryptoStream(fs, new ToBase64Transform(),
CryptoStreamMode.Write))
using (var fi = File.Open(filein, FileMode.Open))
{
fi.CopyTo(cs);
}
// the zip file is now stored in base64zip
// and decode
using (FileStream f64 = File.Open(fileout, FileMode.Open))
using (var cs = new CryptoStream(f64, new FromBase64Transform(),
CryptoStreamMode.Read))
using (var fo = File.Open(filein + ".orig", FileMode.Create))
{
cs.CopyTo(fo);
}
// the original file is in my.zip.orig
// use the commandlinetool
// fc my.zip my.zip.orig
// to verify that the start file and the encoded and decoded file
// are the same
}
he code uses standard classes found in System.Security.Cryptography namespace and uses a CryptoStream and the FromBase64Transform and its counterpart ToBase64Transform

Encrypting a ZipPackage Stream in Memory

I am using .NET 4.0 and trying to do the following:
Create a System.IO.Packaging.Package in Memory
Add Items to the package
encrypt package before it is written to file.
I tried to create a MemoryStream and add the files to it by:
using (var memoryZip = Package.Open(_memoryStream, FileMode.Open))
{
var partUri = PackUriHelper.CreatePartUri(_fileUri);
var part = memoryZip.CreatePart(
partUri,
String.Empty,
CompressionOption.NotCompressed);
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
fileStream.CopyTo(packagePart.GetStream());
}
}
Then I tried to encrypt it and saved it to a file:
_key = new DESCryptoServiceProvider
{
Key = Encoding.ASCII.GetBytes(_password);
IV = Encoding.ASCII.GetBytes(_password);
}
var fileStream = File.Open(_fileName, FileMode.Create, FileAccess.Write);
var cryptoStream = new CryptoStream(streamToFile, _key.CreateEncryptor(), CryptoStreamMode.Write);
//Convert filestream to byte[]
var streamAsBytes = new byte[(_memoryStream.Length)];
_memoryStream.Read(streamAsBytes, 0, streamAsBytes.Length);
//Encrypt
cryptoStream.Write(streamAsBytes, 0, streamAsBytes.Length);
fileStream.Close();
cryptoStream.Flush();
cryptoStream.Close();
However, when I go to decrypt it:
var fileStream = new FileStream(_zipFileName, FileMode.Open, FileAccess.Read);
var cryptoStream = new CryptoStream(fileStream, _key.CreateDecryptor(), CryptoStreamMode.Read);
using(var zipPackage = Package.Open(cryptoStream, FileMode.Open))
I get a FileFormatException: "File contains corrupted data."
This isn't the same message you would get if decryption failed. I would expect that the stream that went in during encryption is the same one as the one that came out so any idea why the package would be corrupted?

How do I do a SHA1 File Checksum in C#?

How do I use the SHA1CryptoServiceProvider() on a file to create a SHA1 Checksum of the file?
using (FileStream fs = new FileStream(#"C:\file\location", FileMode.Open))
using (BufferedStream bs = new BufferedStream(fs))
{
using (SHA1Managed sha1 = new SHA1Managed())
{
byte[] hash = sha1.ComputeHash(bs);
StringBuilder formatted = new StringBuilder(2 * hash.Length);
foreach (byte b in hash)
{
formatted.AppendFormat("{0:X2}", b);
}
}
}
formatted contains the string representation of the SHA-1 hash. Also, by using a FileStream instead of a byte buffer, ComputeHash computes the hash in chunks, so you don't have to load the entire file in one go, which is helpful for large files.
With the ComputeHash method. See here:
ComputeHash
Example snippet:
using(var cryptoProvider = new SHA1CryptoServiceProvider())
{
string hash = BitConverter
.ToString(cryptoProvider.ComputeHash(buffer));
//do something with hash
}
Where buffer is the contents of your file.
If you are already reading the file as a stream, then the following technique calculates the hash as you read it. The only caveat is that you need to consume the whole stream.
class Program
{
static void Main(string[] args)
{
String sourceFileName = "C:\\test.txt";
Byte[] shaHash;
//Use Sha1Managed if you really want sha1
using (var shaForStream = new SHA256Managed())
using (Stream sourceFileStream = File.Open(sourceFileName, FileMode.Open))
using (Stream sourceStream = new CryptoStream(sourceFileStream, shaForStream, CryptoStreamMode.Read))
{
//Do something with the sourceStream
//NOTE You need to read all the bytes, otherwise you'll get an exception ({"Hash must be finalized before the hash value is retrieved."})
while(sourceStream.ReadByte() != -1);
shaHash = shaForStream.Hash;
}
Console.WriteLine(Convert.ToBase64String(shaHash));
}
}
Also you can try:
FileStream fop = File.OpenRead(#"C:\test.bin");
string chksum = BitConverter.ToString(System.Security.Cryptography.SHA1.Create().ComputeHash(fop));

Categories