问题
Tool : OS-Windows 7 64bit, Visual Studio 2012, 4.5 .NET Framework. Language : C#.
I have created one console application. In this application I have used Data Encryption Algorithm (DES- Symmetric Algorithm) to encrypt and decrypt data.
Now in this approach, Private or secrete key is used. I want to secure this key from client/Hack. How can I secure it?
For now I have stored KEY to the registry, And read that key from registry to encryption and decryption when required. But from registry any knowledgeable developer like you guys can easily read key.
Below is my DES algorithm code(I got this code from MSDN):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace DES_Encrypt_Decrypt
{
public class Program
{
static void Main(string[] args)
{
var text = "This is Plain Text";
var encryptedText = CryptoGraphyExample.EncryptPlainTextToCipherText(text);
var decryptedText = CryptoGraphyExample.DecryptCipherTextToPlainText(encryptedText);
Console.WriteLine("Passed Text = " + text);
Console.WriteLine("EncryptedText = " + encryptedText);
Console.WriteLine("DecryptedText = " + decryptedText);
Console.ReadLine();
}
}
public class CryptoGraphyExample
{
private const string _securityKey = "MyComplexKey";
// This is my secret key and I want to secure it to the client machine.
public static string EncryptPlainTextToCipherText(string PlainText)
{
byte[] toEncryptedArray = UTF8Encoding.UTF8.GetBytes(PlainText);
MD5CryptoServiceProvider objMD5CryptoService = new MD5CryptoServiceProvider();
byte[] securityKeyArray = objMD5CryptoService.ComputeHash(UTF8Encoding.UTF8.GetBytes(_securityKey));
objMD5CryptoService.Clear();
var objTripleDESCryptoService = new TripleDESCryptoServiceProvider();
objTripleDESCryptoService.Key = securityKeyArray;
objTripleDESCryptoService.Mode = CipherMode.ECB;
objTripleDESCryptoService.Padding = PaddingMode.PKCS7;
var objCrytpoTransform = objTripleDESCryptoService.CreateEncryptor();
byte[] resultArray = objCrytpoTransform.TransformFinalBlock(toEncryptedArray, 0, toEncryptedArray.Length);
objTripleDESCryptoService.Clear();
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string DecryptCipherTextToPlainText(string CipherText)
{
byte[] toEncryptArray = Convert.FromBase64String(CipherText);
MD5CryptoServiceProvider objMD5CryptoService = new MD5CryptoServiceProvider();
byte[] securityKeyArray = objMD5CryptoService.ComputeHash(UTF8Encoding.UTF8.GetBytes(_securityKey));
objMD5CryptoService.Clear();
var objTripleDESCryptoService = new TripleDESCryptoServiceProvider();
objTripleDESCryptoService.Key = securityKeyArray;
objTripleDESCryptoService.Mode = CipherMode.ECB;
objTripleDESCryptoService.Padding = PaddingMode.PKCS7;
var objCrytpoTransform = objTripleDESCryptoService.CreateDecryptor();
byte[] resultArray = objCrytpoTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
objTripleDESCryptoService.Clear();
return UTF8Encoding.UTF8.GetString(resultArray);
}
}
}
回答1:
Some machines have a TPM (Trusted Platform Module) and some also have a keychain or keystore that leverages the TPM. Macs do as do some Windows machines. Just encryption a key moves the problem to securing the encryption key.
When you get code look to see if it is current, old bad code is rarely removed from the Internet. The MDN code is completely out of date in every respect.
Do not use DES, it is no longer consider secure and 3DES is archaic and not recommended for new work. Instead use AES. DES, 3DES and AES are all symmetric keys.
Do not use MD5, it is no longer considered secure, use at least SHA256 but for password derivation use a method that uses a salt and iteration count such as PBKDF2 (Password Based Derivation Function 2).
Do not use ECB mode, it too is insecure, see ECB mode, scroll down to the Penguin.
回答2:
You can have a look at another answer of mine:
- Where to store db passwords when using Windows .NET or ASP.NET applications
Or you can consider generating a key from a password, which you can use to encrypt the key itself:
- Create a Key from a Password / Random SALT (in C#)
Either way, you should not use DES any longer as it is not secure enough any more. Triple-DES is okay if you have no other option. I recommend to use AES with a key size of 256 bit if you require a secure symmetric algorithm.
In the former Documentation Beta - "stackoverflow.com/documentation", I had added some additional information (.Net Framework -> Encryption / Cryptography). Since Beta is offline, I will provide this information here:
Create a Key from a Password / Random SALT (in C#)
using System;
using System.Security.Cryptography;
using System.Text;
public class PasswordDerivedBytesExample
{
public static void Main(String[] args)
{
// Get a password from the user.
Console.WriteLine("Enter a password to produce a key:");
byte[] pwd = Encoding.Unicode.GetBytes(Console.ReadLine());
byte[] salt = CreateRandomSalt(7);
// Create a TripleDESCryptoServiceProvider object.
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
try
{
Console.WriteLine("Creating a key with PasswordDeriveBytes...");
// Create a PasswordDeriveBytes object and then create
// a TripleDES key from the password and salt.
PasswordDeriveBytes pdb = new PasswordDeriveBytes(pwd, salt);
// Create the key and set it to the Key property
// of the TripleDESCryptoServiceProvider object.
tdes.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", 192, tdes.IV);
Console.WriteLine("Operation complete.");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Clear the buffers
ClearBytes(pwd);
ClearBytes(salt);
// Clear the key.
tdes.Clear();
}
Console.ReadLine();
}
#region Helper methods
/// <summary>
/// Generates a random salt value of the specified length.
/// </summary>
public static byte[] CreateRandomSalt(int length)
{
// Create a buffer
byte[] randBytes;
if (length >= 1)
{
randBytes = new byte[length];
}
else
{
randBytes = new byte[1];
}
// Create a new RNGCryptoServiceProvider.
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
// Fill the buffer with random bytes.
rand.GetBytes(randBytes);
// return the bytes.
return randBytes;
}
/// <summary>
/// Clear the bytes in a buffer so they can't later be read from memory.
/// </summary>
public static void ClearBytes(byte[] buffer)
{
// Check arguments.
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
// Set each byte in the buffer to 0.
for (int x = 0; x < buffer.Length; x++)
{
buffer[x] = 0;
}
}
#endregion
}
This example is taken from MSDN.
It is a console demo, and it shows how to create a secure key based on a user-defined password, and how to create a random SALT based on the cryptographic random generator.
Notes:
The built-in function PasswordDeriveBytes uses the standard PBKDF1 algorithm to generate a key from the password. Per default, it uses 100 iterations to generate the key to slow down brute force attacks. The SALT generated randomly further strenghens the key.
The function CryptDeriveKey converts the key generated by PasswordDeriveBytes into a key compatible with the specified encryption algorithm (here "TripleDES") by using the specified hash algorithm (here "SHA1"). The keysize in this example is 192 bytes, and the initialization vector IV is taken from the triple-DES crypto provider
Usually, this mechanism is used to protect a stronger random generated key by a password, which encrypts large amount of data. You can also use it to provide multiple passwords of different users to give access to the same data (being protected by a different random key).
Unfortunately, CryptDeriveKey does currently not support AES. See here. NOTE: As a workaround, you can create a random AES key for encryption of the data to be protected with AES and store the AES key in a TripleDES-Container which uses the key generated by CryptDeriveKey. But that limits the security to TripleDES, does not take advantage of the larger keysizes of AES and creates a dependency to TripleDES.
来源:https://stackoverflow.com/questions/37676785/how-to-secure-private-keyof-triple-des-in-c-sharp-application