I'm implementing a C# application that needs to save 10 IP addresses in it. So i think it is resource wasting if I integrate a database in to the application. I cannot use XML or text file because those addresses needs to be secure. I sow a suggestion to implement my own file format and use it.1. Is there any suggestion instead implement separate file format2.if there isn't any how to implement new file format and what is the best
Store it in a file and encrypt the file so that it is not readable by other programs.
You can either save details an sqlite database or in a file,
if you want to keep things as private then encrypt the file
Apply Salt on it and save them in Text File or Xml, when its encrypted there is no danger of being data not safe.
See this sample:
using System.Security.Cryptography;
public static string EncodePasswordToBase64(string password)
{ byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
return Convert.ToBase64String(inArray);
}
Hashing is applied using SHA1 to envcrypt the string in this method.
Encrypt the strings using a strong encryption. here 2 methods i like to use. It strongly encrypt and also add salt to it.
public static string EncryptString(string sData, string sKey)
{
// instance of the Rihndael.
RijndaelManaged RijndaelManagedCipher = new RijndaelManaged();
// string to byte array.
byte[] UnicodeText = System.Text.Encoding.Unicode.GetBytes(sData);
// adign dirt to the string to make it harder to guess using a dictionary attack.
byte[] Dirty = Encoding.ASCII.GetBytes(sKey.Length.ToString());
// The Key will be generated from the specified Key and dirt.
PasswordDeriveBytes FinalKey = new PasswordDeriveBytes(sKey, Dirty);
// Create a encryptor from the existing FinalKey bytes.
ICryptoTransform Encryptor = RijndaelManagedCipher.CreateEncryptor(FinalKey.GetBytes(32), FinalKey.GetBytes(16));
// Create a MemoryStream that is going to hold the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Create a CryptoStream
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
// write the encryption
cryptoStream.Write(UnicodeText, 0, UnicodeText.Length);
// write final blocks to the memory stream
cryptoStream.FlushFinalBlock();
// Convert to byte array the encrypted data
byte[] CipherBytes = memoryStream.ToArray();
// Close streams.
memoryStream.Close();
cryptoStream.Close();
// Convert to byte array to string
string EncryptedData = Convert.ToBase64String(CipherBytes);
// Return the encrypted string
return EncryptedData;
}
public static string DecryptString(string sData, string sKey)
{
// instance of rijndael
RijndaelManaged RijndaelCipher = new RijndaelManaged();
// convert to byte aray the encrypted data
byte[] EncryptedData = Convert.FromBase64String(sData);
// add dirt to the key like when encrypthing
byte[] Dirty = Encoding.ASCII.GetBytes(sKey.Length.ToString());
// get the finalkey o be used
PasswordDeriveBytes FinalKey = new PasswordDeriveBytes(sKey, Dirty);
// Create a decryptor with the key
ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(FinalKey.GetBytes(32), FinalKey.GetBytes(16));
// load to memory stream the encrypted data
MemoryStream memoryStream = new MemoryStream(EncryptedData);
// Create a CryptoStream on the memory stream holding the data
CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
// Length is unknown but need placeholder big enought for decrypted data
// we know the decrypted version cannot ever be longer than the crypted version
// since we added bunch of garbage to it so the length of encrypted data is safe to use
byte[] UnicodeText = new byte[EncryptedData.Length];
// Start decrypting
int DecryptedCount = cryptoStream.Read(UnicodeText, 0, UnicodeText.Length);
//close streams
memoryStream.Close();
cryptoStream.Close();
// load decrypted data to string
string DecryptedData = Encoding.Unicode.GetString(UnicodeText, 0, DecryptedCount);
// Return decrypted string
return DecryptedData;
}
Adding to this
now simply make a class like
public class Settings
{
public const string EncryptionKey = "somekey";
public List<string> IP = new List<string>();
public string getClassEncrypted()
{
return EncryptString(new JavaScriptSerializer().Serialize(this), EncryptionKey);
}
public Settings getClassDecrypted(string sClassEcrypted)
{
return new JavaScriptSerializer().Deserialize<Settings>(DecryptString(sClassEcrypted, EncryptionKey));
}
}
one the Ips are set in just write to a file the Settings.getClassEncrypted();
and then when it's time to get back the values only read the text file and load back up with something like this :
string sFileText = ...; // from the file saved
var setting = new Settings.getClassDecrypted(sFileText);
now you've got all classes you need to do it. And the class is even serialized
Related
Im trying to encrypt a large file (Camtasia.exe) with the AES encryption.
Now for some reason I get a "Out of Memory" Exception. Im really new to this and I don't know how I could possibly fix that. This is my code
I use this to call my encryption method.
bytes = File.ReadAllBytes("Camtasia.exe");
Cryptography.Encryption.EncryptAES(System.Text.Encoding.Default.GetString(bytes), encryptionKey);
This is the AES encryption itself
public static string EncryptAES(string content, string password)
{
byte[] bytes = Encoding.UTF8.GetBytes(content);
using (SymmetricAlgorithm crypt = Aes.Create())
using (HashAlgorithm hash = MD5.Create())
using (MemoryStream memoryStream = new MemoryStream())
{
crypt.Key = hash.ComputeHash(Encoding.UTF8.GetBytes(password));
// This is really only needed before you call CreateEncryptor the second time,
// since it starts out random. But it's here just to show it exists.
crypt.GenerateIV();
using (CryptoStream cryptoStream = new CryptoStream(
memoryStream, crypt.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(bytes, 0, bytes.Length);
}
string base64IV = Convert.ToBase64String(crypt.IV);
string base64Ciphertext = Convert.ToBase64String(memoryStream.ToArray());
return base64IV + "!" + base64Ciphertext;
}
}
Here is the error again that I get when calling the function "EncryptAES" at the top. I would be glad if someone could explain how this happens and how to solve it
https://imgur.com/xqcLsKW
You're reading the entire exe into memory, interpreting it as a UTF-16 string (??!), turning that back into UTF-8 bytes, and encrypting those. This converting to/from a string is horifically broken. An executable file is not a human-readable string, and even if it was, you're in a real muddle as to which encoding you're using. I think you can drop the whole string thing.
You're also reading the entire thing into memory (several times in fact, because of the whole string thing), which is wasteful. You don't need to do that: you can encrypt it bit-by-bit. To do this, use a Stream.
Something like this should work (untested): at least it gets the general concept across. We set up a series of streams which lets us read the data out of the input file bit-by-bit, and write them out to the output file bit-by-bit.
// The file we're reading from
using var inputStream = File.OpenRead("Camtasia.exe");
// The file we're writing to
using var outputStream = File.OpenWrite("EncryptedFile.txt");
using var HashAlgorithm hash = MD5.Create();
using var aes = Aes.Create();
aes.Key = hash.ComputeHash(Encoding.UTF8.GetBytes(password));
// Turn the IV into a base64 string, add "!", encode as UTF-8, and write to the file
string base64IV = Convert.ToBase64String(aes.IV) + "!";
byte[] base64IVBytes = Encoding.UTF8.GetBytes(base64IV);
outputStream.Write(base64IVBytes, 0, base64IVBytes.Length);
// Create a stream which, when we write bytes to it, turns those into
// base64 characters and writes them to outputStream
using var base64Stream = new CryptoStream(outputStream, new ToBase64Transform(), CryptoStreamMode.Write);
// Create a stream which, when we write bytes to it, encrypts them and sends them to
// base64Stream
using var encryptStream = new CryptoStream(base64Stream, aes.CreateEncryptor(), CryptoStreamMode.Write);
// Copy the entirety of our input file into encryptStream. This will encrypt them and
// push them into base64Stream, which will base64-encode them and push them into
// outputStream
inputStream.CopyTo(encryptStream);
Note, that using MD5 to derive key bytes isn't best practice. Use Rfc2898DeriveBytes.
Also note that you don't necessarily need to base64-encode the encrypted result before writing it to a file -- you can just write the encrypted bytes straight out. To go this, get rid of base64Stream, and tell the encryptStream to write straight to outputStream.
I am using this function to encrypt data in my UWP project:
public string Encrypt(string text, string key)
{
byte[] buffer = Encoding.UTF8.GetBytes(text);
byte[] sessionKey = Encoding.UTF8.GetBytes(key);
Aes myAes = Aes.Create();
myAes.Mode = CipherMode.ECB;
myAes.KeySize = 128;
myAes.Key = sessionKey;
myAes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = myAes.CreateEncryptor();
buffer = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
return Convert.ToBase64String (buffer);
}
But upon decrypting the data returned from Encrypt() , I get a different result (not equal to the text parameter of Encrypt() ). I am using the following code:
public string Decrypt(string text, string key)
{
byte[] buffer = Convert.FromBase64String(text);
byte[] sessionKey = Encoding.UTF8.GetBytes(key);
Aes myAes = Aes.Create();
myAes.Mode = CipherMode.ECB;
myAes.KeySize = 128;
myAes.Key = sessionKey;
myAes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = myAes.CreateDecryptor();
buffer = decryptor.TransformFinalBlock(buffer, 0, buffer.Length);
return Convert.ToBase64String(buffer);
}
I am using the same key for both encryption and decryption
UPDATE:
text parameter passed to Encrypt() : 450131283::0300DC98050044C406000100040052C40100626B02007E810900660F
Return text from Encrypt():
"lzkPu35Hq7j52IiMWRYSS6j7Vg84abVmhXmNpSxHShJDTbOqkZRFtsPZkEzTsjgRT4MzRHCQUS6MCiq1e5JCune4bZZi1nxxwHtEjZLKZ9E="
the same (above) value I pass to the Decrypt() method and I get the following:
"NDUwMTMxMjgzOjowMzAwREM5ODA1MDA0NEM0MDYwMDAxMDAwNDAwNTJDNDAxMDA2MjZCMDIwMDdFODEwOTAwNjYwRg=="
The problem is what you're doing with the end of the decryption:
return Convert.ToBase64String(buffer);
You actually want to convert the decrypted binary data back into a string in a way that mirrors the original way you converted it from a string into plaintext binary data, so you want:
return Encoding.UTF8.GetString(buffer);
This sort of problem is usually best addressed by looking at every step in the transformation chain each direction, and make sure that they're balanced. So it should look like this:
Text
(Encode with UTF-8)
Non-encrypted binary data
(Encrypt)
Encrypted binary data
(Convert to base64)
Encrypted data as base64 text
(Store or whatever...)
Encrypted data as base64 text
(Convert from base64)
Encrypted binary data
(Decrypt)
Non-encrypted binary data
(Decode with UTF-8)
Text
Where I've got "decode with UTF-8" you've got "Convert to base64" so the decoding steps don't match the encoding steps.
I am writing an application, which would receive encrypted byte array, consisting of file name and file bytes, with the following protocol: file_name_and_extension|bytes. Byte array is then decrypted and passing into Encoding.UTF8.getString(decrypted_bytes) would be preferable, because I would like to trim file_name_and_extension from the received bytes to save actual file bytes into file_name_and_extension.
I simplified my application, to only receive file bytes which are then passed into Encoding.UTF8.GetString() and back into byte array with Encoding.UTF8.getBytes(). After that, I am trying to write a zip file, but the file is invalid. It works when using ASCII or Base64.
private void Decryption(byte[] encryptedMessage, byte[] iv)
{
using (Aes aes = new AesCryptoServiceProvider())
{
aes.Key = receiversKey;
aes.IV = iv;
// Decrypt the message
using (MemoryStream decryptedBytes = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(decryptedBytes, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(encryptedMessage, 0, encryptedMessage.Length);
cs.Close();
string decryptedBytesString = Encoding.UTF8.GetString(decryptedBytes.ToArray()); //corrupts the zip
//string decryptedBytesString = Encoding.ASCII.GetString(decryptedBytes.ToArray()); //works
//String decryptedBytesString = Convert.ToBase64String(decryptedBytes.ToArray()); //works
byte[] fileBytes = Encoding.UTF8.GetBytes(decryptedBytesString);
//byte[] fileBytes = Encoding.ASCII.GetBytes(decryptedBytesString);
//byte[] fileBytes = Convert.FromBase64String(decryptedBytesString);
File.WriteAllBytes("RECEIVED\\received.zip", fileBytes);
}
}
}
}
Because one shouldn't try to interpret raw bytes as symbols in some encoding unless he actually knows/can deduce the encoding used.
If you receive some nonspecific raw bytes, then process them as raw bytes.
But why it works/doesn't work?
Because:
Encoding.Ascii seems to ignore values greater than 127 and return them as they are. So no matter the encoding/decoding done, raw bytes will be the same.
Base64 is a straightforward encoding that won't change the original data in any way.
UTF8 - theoretically with those bytes not being proper UTF8 string we may have some conversion data loss (though it would more likely result in an exception). But the most probable reason is a BOM being added during Encoding.UTF8.GetString call that would remain there after Encoding.UTF8.GetBytes.
In any case, I repeat - do not encode/decode anything unless it is actually string data/required format.
I am writing an iPhone application that needs to encrypt a password using AES encryption. I have found many different examples for AES encryption but I'm finding that the implementation differs from sample to sample. This would be fine if I controlled the decryption process as well, but I do not - I need to send the encrypted password to a .NET API, which will decrypt the password using .NET code.
I am including the C# code below. Can someone point me in the right direction, or even better, provide some Objective-C code for encrypting an NSString which will work with this C# code?
The sharedSecret I have been provided with is 126 characters in length, so I'm assuming this is 128-bit encryption. Or should the sharedSecret then be 128 characters?
public class Crypto
{
private static byte[] _salt = Encoding.ASCII.GetBytes("SALT GOES HERE");
/// <summary>
/// Encrypt the given string using AES. The string can be decrypted using
/// DecryptStringAES(). The sharedSecret parameters must match.
/// </summary>
/// <param name="plainText">The text to encrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for encryption.</param>
public static string EncryptStringAES(string plainText, string sharedSecret)
{
if (string.IsNullOrEmpty(plainText))
throw new ArgumentNullException("plainText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
string outStr = null; // Encrypted string to return
RijndaelManaged aesAlg = null; // RijndaelManaged object used to encrypt the data.
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
// Create a RijndaelManaged object
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
// prepend the IV
msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return outStr;
}
/// <summary>
/// Decrypt the given string. Assumes the string was encrypted using
/// EncryptStringAES(), using an identical sharedSecret.
/// </summary>
/// <param name="cipherText">The text to decrypt.</param>
/// <param name="sharedSecret">A password used to generate a key for decryption.</param>
public static string DecryptStringAES(string cipherText, string sharedSecret)
{
if (string.IsNullOrEmpty(cipherText))
throw new ArgumentNullException("cipherText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
// Declare the RijndaelManaged object
// used to decrypt the data.
RijndaelManaged aesAlg = null;
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
try
{
// generate the key from the shared secret and the salt
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
// Create the streams used for decryption.
byte[] bytes = Convert.FromBase64String(cipherText);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
// Get the initialization vector from the encrypted stream
aesAlg.IV = ReadByteArray(msDecrypt);
// Create a decrytor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
return plaintext;
}
private static byte[] ReadByteArray(Stream s)
{
byte[] rawLength = new byte[sizeof(int)];
if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length)
{
throw new SystemException("Stream did not contain properly formatted byte array");
}
byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)];
if (s.Read(buffer, 0, buffer.Length) != buffer.Length)
{
throw new SystemException("Did not read byte array properly");
}
return buffer;
}
}
The shared secret's length is not relevant to the bit length of the key in this case. You can see here how the C# is deriving the key with Rfc2898DeriveBytes:
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt);
RFC 2898 defines the PKCS5 standard (which means PBKDF2). Based on Microsoft's documentation it looks like the default iteration count is 1000, so you've got the shared secret, the salt, and the iteration count. If you plug that into another PBKDF2 implementation that will give you the raw key you need to use to encrypt.
It next creates a RijndaelManaged object (Rijndael was the name of AES before it was standardized) and gets the default key size in bits (which it then divides by 8 to get the bytes). It then gets that many bytes from the key variable. If you find out the default key size for this class then that's the size of the AES key.
(Incidentally, when creating one of these objects the documentation states that a random IV is generated and that it defaults to CBC so we can assume that from here on)
Next it writes the length of the IV, then the IV itself.
msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
After all that it writes the ciphertext and the entire blob is complete.
On the decrypt side it does mostly the same thing in reverse. First it derives the key, then it grabs the whole encrypted blob and feeds it to ReadByteArray, which extracts the IV. Then it uses the key + IV to decrypt.
Implementing this in Objective-C shouldn't be too difficult given a sample encrypted blob and the shared secret!
If you send passwords - you doing it wrong.
Never send a password even in encrypted form, it is a security vulnerability: you have to maintain client and server to use the latest encryption/decryption library. You must be sure that the key is not compromised, you need to update the key from time to time, and hence transfer it both to server and client. You must use different keys for different passwords. You have to be sure that server is secured and not compromised, you need to know that you actually speak to the server etc etc.
Instead, create a strong cryptographic hash (a one-way function) of a password and send that over a secured channel. It would also mean that on the server side you never store passwords at all.
I encrypted a file using DES then After decrypting it successfully at the server and using
System.IO.File.WriteAllBytes(#"c:\test\" + fileName, decryptedFile);
method the file data changed a little it the text is "Encrypting and Decrypting usind DES blah blah blah blah"
the text in the end file after decrypting is " k$nlng and Decrypting usind DES blah blah blah blah"
and i also tried this:
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(#"C:\Test\" + fileName, FileMode.Create)))
{
binWriter.Write(decryptedFile);
}
the text still not the same
encrypting by :
public byte [] DESEncrypt(byte [] fileBytes)
{
CryptoStreamMode mode = CryptoStreamMode.Write;
// Set up streams and encrypt
MemoryStream memStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memStream,
cryptoProvider.CreateEncryptor(cryptoProvider.Key, cryptoProvider.Key), mode);
cryptoStream.Write(fileBytes, 0, fileBytes.Length);
cryptoStream.FlushFinalBlock();
// Read the encrypted message from the memory stream
byte[] encryptedMessageBytes = new byte[memStream.Length];
memStream.Position = 0;
memStream.Read(encryptedMessageBytes, 0, encryptedMessageBytes.Length);
MessageBox.Show("encrypted DES");
return encryptedMessageBytes;
}
decrypting by:
static public byte[] DESdecrypt(byte [] fileBytes)
{
ICryptoTransform decryptor = cryptoProvider.CreateDecryptor();
byte[] originalAgain = decryptor.TransformFinalBlock(fileBytes, 0, fileBytes.Length);
return originalAgain;
}
Thanks
You are passing the same value for your "key" and "iv" value. Each time you call the function, your "iv" value gets updated (thus, your key gets changed).
So you basically are doing this:
key = "key"
Encrypt (key, key)
-- key has now changed.
What you need to do is:
key = "key"
iv = copy of key
Encrypt (key, iv)
hard to say, not an expert on the subject but compare your bytes before encrypting and after encrypting and decrypting. If they are identical no issues with the process. WriteALLBytes might not be the only thing. think MIME type . a similar issue is i had to specifically say what type of file i am saving.