Scenario - I have multiple files on my server and as per policy we can keep only encrypted files. We are doing some data migration, for this we have to move these files on to cloud and as per documentations Base64 is the best way to transfer encrypted data over network. I am new in encryption and stuck between this. Let me know if this help you.
How to save file in base64 format?
================================================================
I am new in Encryption and got below code from net and trying to encrypting files using RijndaelManaged and the following code is working fine
public static void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = #"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch
{
}
}
When I try to decrypt using Convert.FromBase64String, it returns an error
public static string DecryptFile(string inputFile)
{
var myRijndael = new RijndaelManaged { Key = _key, IV = _key, Padding = PaddingMode.PKCS7 };
_decryptor = myRijndael.CreateDecryptor(myRijndael.Key, myRijndael.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(inputFile)))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, _decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
return srDecrypt.ReadToEnd();
}
}
}
}
Please help me to solve this issue
I found this code in a website
private void EncryptFile(string inputFile)
{
string password = #"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = inputFile + ".enc";
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
cs.WriteByte((byte)data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
I have two problems with it. First one is the password part. I have a function which generates random strings:
public string CreatePassword(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890*!=?&/";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--){
res.Append(valid[rnd.Next(valid.Length)]);
}
return res.ToString();
}
When I edit the code like this:
string password = CreatePassword(8);
It works. But when I increase the password size (like 10) I get this error:
An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
Is there way to increase password lenght? Or can we consider it safe with 8 lenght?
Other question:
my output file is inputFile + ".enc" When I delete ".enc" Part I got "this file using by another process" error. How can write encrypted one to original one?
RijndaelManaged has rules. Below command used for preparing algorithm:
RMCrypto.CreateEncryptor(key, key)
First param is secret key and it must be 128, 192, or 256 bits. Second param is IV. In given example, key and IV used as same. Password text convert to byte with unicode so it is length 16 byte = 128 bit. So if you use different size then rule you get error.
You can check below article much better:
Encrypting & Decrypting a String in C#
I have decrypted and saved an mp3 file into a blob storage.
However, when I decrypt and download the file I cant play it. I used an Mp3 validation tool which says "unknown file format". I believe it is the decryption that does not work since it works to download an unencrypted Mp3 file. Below I first show the encryption code within its Azure webjob function. The I show the decryption method and the method using it. I have removed handling of keys and such or clarity.
Encrypt
public static void EncryptBlob(
[BlobTrigger("callstest/{name}")]
[Blob("callstest/{name}", FileAccess.Read)] Stream blobInput,
[Blob("encryptedcalls/{name}.vega", FileAccess.Write)] Stream blobOutput)
{
try
{
var password = "myKey123";
var ue = new UnicodeEncoding();
var key = ue.GetBytes(password);
var rmCrypto = new RijndaelManaged {Padding = PaddingMode.None};
using (var cs = new CryptoStream(blobOutput,
rmCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write))
{
int data;
while ((data = blobInput.ReadByte()) != -1)
cs.WriteByte((byte)data);
}
}
catch
{
Trace.TraceError("an error occured during encryption of the file-get the name?");
}
}
AdminController
public async Task<ActionResult> DownloadMp3FromUrl()
{
var file = await _recordingService.GetRecordingFromUrl();
var fileName = "filetest.mp3";
return File(file,"audio/mpeg", fileName);
}
Recording Service handler
public async Task<byte[]> GetRecordingFromUrl()
{
var container = _blobClient.GetContainerReference("encryptedcalls");
var blockBlob = container.GetBlockBlobReference("SearchFiles.mp3.vega");
try
{
var password = "myKey123";
var ue = new UnicodeEncoding();
var key = ue.GetBytes(password);
var rmCrypto = new RijndaelManaged { Padding = PaddingMode.None };
using (var stream = new MemoryStream())
{
blockBlob.FetchAttributes();
blockBlob.DownloadToStream(stream, null, null);
using (var cs = new CryptoStream(stream, rmCrypto.CreateDecryptor(key, key), CryptoStreamMode.Read))
{
int data;
while ((data = stream.ReadByte()) != -1)
cs.WriteByte((byte)data);
return stream.ToArray();
}
}
}
catch
{
Trace.TraceError("an error occured during encryption of the file-get the name?");
}
return null;
}
You're trying to write the decrypted data back into the source-stream in your Recording Service handler. This will never work. I'm amazed this doesn't throw an exception.
You need to set up your input stream, pass it into a decrypting CryptoStream, then write that to another output stream:
using (var inStream = new MemoryStream())
using (var outStream = new MemoryStream())
{
blockBlob.FetchAttributes();
blockBlob.DownloadToStream(inStream, null, null);
using (var cryptoStream = new CryptoStream(
inStream, rmCrypto.CreateDecryptor(key, key), CryptoStreamMode.Read))
{
cryptoStream.CopyTo(outStream);
return outStream.ToArray();
}
}
As an aside, the implementation as you've presented it here is full of security issues:
Don't use a non-padded cipher. You can leak information this way.
Don't generate your key from a password. Use a cryptographically secure RNG to generate your keys.
If you must use a string as your key's password, use Rfc2898DeriveBytes to generate a cryptographically secure random key from the password.
Absolutely do not use your symmetric key as your IV. This is really, really bad practice. The IV is used to randomize the cipher's output - it is not a secret in the same way as the key, and should be unique to each 'message' (or file) being encrypted.
This question already has answers here:
How to create a password protected file in C#
(2 answers)
Closed 9 years ago.
Am having a FILE named Sample. It may be of any type(.txt/.doc/.docx/.pdf/....). Now I want to set a password for that file. If it is possible just help me with code's.
You can Encrypt the file using your own passwort or with generated keys (See the documentation)
Example from MSDN:
class Class1
{
// Call this function to remove the key from memory after use for security
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")]
public static extern bool ZeroMemory(IntPtr Destination, int Length);
// Function to Generate a 64 bits Key.
static string GenerateKey()
{
// Create an instance of Symetric Algorithm. Key and IV is generated automatically.
DESCryptoServiceProvider desCrypto =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();
// Use the Automatically generated key for Encryption.
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}
static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
FileStream fsInput = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
FileStream fsEncrypted = new FileStream(sOutputFilename,
FileMode.Create,
FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,
desencrypt,
CryptoStreamMode.Write);
byte[] bytearrayinput = new byte[fsInput.Length];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}
static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}
static void Main()
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;
// Get the Key for the file to Encrypt.
sSecretKey = GenerateKey();
// For additional security Pin the key.
GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );
// Encrypt the file.
EncryptFile(#"C:\MyData.txt",
#"C:\Encrypted.txt",
sSecretKey);
// Decrypt the file.
DecryptFile(#"C:\Encrypted.txt",
#"C:\Decrypted.txt",
sSecretKey);
// Remove the Key from memory.
ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
gch.Free();
}
}
}
You cannot set a password on every file in order to restrict it from opening. However, you can protect file contents by using encryption.
See this link for Encryption & Decryption in C# http://support.microsoft.com/kb/307010
I have created a few little programs that export data to a text file using StreamWriter and then I read them back in using StreamReader. This works great and does what I need it to do but I was wondering if there was a way that I could save this information without the user being able to access or modify it either intentionally or unintentionally. An example of something I would have in a text file would be if a checkbox was ticked, when you tick it it outputs "Ticked" to a text file, when the program is re - opened I know what state the form was in when it was closed. I obviously don't want to keep using text files. Does anyone have any ideas on how I can easily store this information without the user being able to modify it? Thank you very much.
The simplest way is to Base-64 encode/decode this text. This is not secure, but will prevent a casual user from modifying the data.
static public string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
static public string DecodeFrom64(string encodedData)
{
byte[] encodedDataAsBytes
= System.Convert.FromBase64String(encodedData);
string returnValue =
System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
return returnValue;
}
EDIT: Real encryption
#region Encryption
string passPhrase = "Pasword"; // can be any string
string saltValue = "sALtValue"; // can be any string
string hashAlgorithm = "SHA1"; // can be "MD5"
int passwordIterations = 7; // can be any number
string initVector = "~1B2c3D4e5F6g7H8"; // must be 16 bytes
int keySize = 256; // can be 192 or 128
private string Encrypt(string data)
{
byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
byte[] buffer = Encoding.UTF8.GetBytes(data);
byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
RijndaelManaged managed = new RijndaelManaged();
managed.Mode = CipherMode.CBC;
ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes);
MemoryStream stream = new MemoryStream();
CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
stream2.Write(buffer, 0, buffer.Length);
stream2.FlushFinalBlock();
byte[] inArray = stream.ToArray();
stream.Close();
stream2.Close();
return Convert.ToBase64String(inArray);
}
private string Decrypt(string data)
{
byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
byte[] buffer = Convert.FromBase64String(data);
byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
RijndaelManaged managed = new RijndaelManaged();
managed.Mode = CipherMode.CBC;
ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes);
MemoryStream stream = new MemoryStream(buffer);
CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
byte[] buffer5 = new byte[buffer.Length];
int count = stream2.Read(buffer5, 0, buffer5.Length);
stream.Close();
stream2.Close();
return Encoding.UTF8.GetString(buffer5, 0, count);
}
#endregion
You should call ProtectedData.Protect to encrypt the data using a per-user key.
Note that it wouldn't be very hard for a skilled user to decrypt and modify the data.
Anything that your program does on the user's machine can be done by the user too.
You can add a checksum or hash to the file - if the file contents doesn't agree with the checksum, you know it was tampered with.
If it is important that users can't read the contents of the file, you can encrypt it.
I don't believe you can make a file that can't be tampered with (a savvy user could use a hex editor and change it, for example) - the best you can do is detect such tampering.
You can use the Ionic zip libraries to zip those text files. If necessary you could also use features of Ionic zip like password protection and encryption. And you'll still be able to open the file (with zipping applications like, for example, 7zip) manually yourself using the same settings you used to create it in the first place.
If a program can access the information, a user usually can too. However you can produce data the user will not immediately understand.
I would start by creating a class that holds all state information you want to save, isolating the problem. Coincidentally, the BinaryFormatter class will then allow you to easily save and load this class to/from a file. I don't know if it's results are "unreadable enough" - if not, apply Base64 encoding like Leon mentioned.
While you could base64 encode or even fully encrypt your configuration data (with SHA1 or MD5) as already suggested, I think good practice would be to work with the framework classes dealing with configuration data (Configuration under the System.Configuration namespace) and it's built in ability to encrypt data (via the ProtectSection method of the ConfigurationSection class).
First of all you should declare and initialize an instance:
using System.Configuration;
...
static void Main(string[] args)
{
Configuration config;
config = ConfigurationManager.OpenExeConfiguration(/*path to config file*/); //Use ConfigurationManager.OpenMachineConfiguration(/*path to config file*/) when opening machine configuration
...
After that you need to define a custom configuration section that defines your configuration (msdn example)
Once you've done that you just need to initialize an instance of your custom configuration section and add it to the configuration file using this code:
isTicked = config.Sections.Add("isTicked", customSection);
To encrypt the section you just added use this code (with further examples in both VB.NET and C# found here):
config.Sections["isTicked"].SectionInformation.ProtectSection("protection provider");
The "DPAPIProtectedConfigurationProvider" and "RSAProtectedConfigurationProvider" are built in by default.
Once you want to decrypt the section use this code:
config.Sections["isTicked"].SectionInformation.UnprotectSection();
To stress a point - encryption and decryption both take effect only after you save the configuration file
To save the file, use the code:
config.Save(); //config.SaveAs("string") is also available
Further information about the relevant classes and methods can be found in the msdn, starting with the Configuration class page linked above.
Try this code to encrypt and decrypt your text!
It is quite easy and strong I think...
public static class Crypto
{
private static readonly byte[] IVa = new byte[] { 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
public static string Encrypt(this string text, string salt)
{
try
{
using (Aes aes = new AesManaged())
{
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
aes.IV = aes.Key;
using (MemoryStream encryptionStream = new MemoryStream())
{
using (CryptoStream encrypt = new CryptoStream(encryptionStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
byte[] cleanText = Encoding.UTF8.GetBytes(text);
System.Diagnostics.Debug.WriteLine(String.Concat("Before encryption text data size: ", text.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Before encryption byte data size: ", cleanText.Length.ToString()));
encrypt.Write(cleanText, 0, cleanText.Length);
encrypt.FlushFinalBlock();
}
byte[] encryptedData = encryptionStream.ToArray();
string encryptedText = Convert.ToBase64String(encryptedData);
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted text data size: ", encryptedText.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted byte data size: ", encryptedData.Length.ToString()));
return encryptedText;
}
}
}
catch(Exception e)
{
return String.Empty;
}
}
public static string Decrypt(this string text, string salt)
{
try
{
using (Aes aes = new AesManaged())
{
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(salt));
aes.Key = deriveBytes.GetBytes(128 / 8);
aes.IV = aes.Key;
using (MemoryStream decryptionStream = new MemoryStream())
{
using (CryptoStream decrypt = new CryptoStream(decryptionStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
byte[] encryptedData = Convert.FromBase64String(text);
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted text data size: ", text.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("Encrypted byte data size: ", encryptedData.Length.ToString()));
decrypt.Write(encryptedData, 0, encryptedData.Length);
decrypt.Flush();
}
byte[] decryptedData = decryptionStream.ToArray();
string decryptedText = Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
System.Diagnostics.Debug.WriteLine(String.Concat("After decryption text data size: ", decryptedText.Length.ToString()));
System.Diagnostics.Debug.WriteLine(String.Concat("After decryption byte data size: ", decryptedData.Length.ToString()));
return decryptedText;
}
}
}
catch(Exception e)
{
return String.Empty;
}
}
}
Just to add another implementation of Leon's answer, and following the
Microsoft docs
Here a class example that encrypts and decrypts strings
public static class EncryptionExample
{
#region internal consts
internal const string passPhrase = "pass";
internal const string saltValue = "salt";
internal const string hashAlgorithm = "MD5";
internal const int passwordIterations = 3; // can be any number
internal const string initVector = "0123456789abcdf"; // must be 16 bytes
internal const int keySize = 64; // can be 192 or 256
#endregion
#region public static Methods
public static string Encrypt(string data)
{
string res = string.Empty;
try
{
byte[] bytes = Encoding.ASCII.GetBytes(initVector);
byte[] rgbSalt = Encoding.ASCII.GetBytes(saltValue);
byte[] buffer = Encoding.UTF8.GetBytes(data);
byte[] rgbKey = new PasswordDeriveBytes(passPhrase, rgbSalt, hashAlgorithm, passwordIterations).GetBytes(keySize / 8);
RijndaelManaged managed = new RijndaelManaged();
managed.Mode = CipherMode.CBC;
ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes);
byte[] inArray = null;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, transform, CryptoStreamMode.Write))
{
csEncrypt.Write(buffer, 0, buffer.Length);
csEncrypt.FlushFinalBlock();
inArray = msEncrypt.ToArray();
res = Convert.ToBase64String(inArray);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Encrypt " + ex);
}
return res;
}
public static string Decrypt(string data)
{
string res = string.Empty;
try
{
byte[] bytes = Encoding.ASCII.GetBytes(initVector);
byte[] rgbSalt = Encoding.ASCII.GetBytes(saltValue);
byte[] buffer = Convert.FromBase64String(data);
byte[] rgbKey = new PasswordDeriveBytes(passPhrase, rgbSalt, hashAlgorithm, passwordIterations).GetBytes(keySize / 8);
RijndaelManaged managed = new RijndaelManaged();
managed.Mode = CipherMode.CBC;
ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes);
using (MemoryStream msEncrypt = new MemoryStream(buffer))
{
using (CryptoStream csDecrypt = new CryptoStream(msEncrypt, transform, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
res = srDecrypt.ReadToEnd();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Decrypt " + ex);
}
return res;
}
}
By the way, here is the "salt value" definition that I had googled to find out what it was.
Salt value
If an attacker does not know the password, and is trying to guess it with a brute-force attack, then every password he tries has to be tried with each salt value. So, for a one-bit salt (0 or 1), this makes the encryption twice as hard to break in this way.
Preventing unintentional string modification can be done using a checksum, as pointed in this answer.
However, it's quite easy to generate such a checksum, as they are not that many widely used algorithms.
Thus that doesn't protect you against intentional modification.
To prevent that, people use digital signatures. That allows anyone to verify your data hasn't be tampered, but only you (the owner of the private secret) can generate the signature.
Here is an example in C#.
However, as others pointed out, you need to embed your private key somewhere in your binary, and a (not so) skilled programmer will be able to retrieve it, even if you obfuscate your .net dll or you make that in a separate native process.
That would be enough for most concerns though.
If you are really concerned by security, then you need to move on the cloud, and execute the code on a machine you own.