我目前正在開發一個web服務。作爲此Web服務的一部分,我能夠將用戶密碼安全地存儲在SQL數據庫中,並且能夠通過HTTPS Web服務向最終用戶解密密碼值。如何加密/解密敏感數據存儲(ASP.NET Web API項目)
這是我第一次處理這個需求。我發現了許多基於對稱和/或不對稱加密的示例。但我不明白永久存儲用於加密數據的密碼/密鑰。例如,如果我使用基於RijndaelManaged的對稱加密,如何安全地存儲用於加密的輸入參數,以便我的Web服務稍後可以檢索SQL DB的數據並解密它們。
我目前正在開發一個web服務。作爲此Web服務的一部分,我能夠將用戶密碼安全地存儲在SQL數據庫中,並且能夠通過HTTPS Web服務向最終用戶解密密碼值。如何加密/解密敏感數據存儲(ASP.NET Web API項目)
這是我第一次處理這個需求。我發現了許多基於對稱和/或不對稱加密的示例。但我不明白永久存儲用於加密數據的密碼/密鑰。例如,如果我使用基於RijndaelManaged的對稱加密,如何安全地存儲用於加密的輸入參數,以便我的Web服務稍後可以檢索SQL DB的數據並解密它們。
安全地存儲用戶密碼的SQL數據庫,並能夠解密方法 密碼值
這並不安全。密碼絕不應加密;他們應該是哈希!用鹽和hashing algorithm that is suited for pashword hashing。
一般來說,我當然會同意你的看法。但你可以看到我的應用程序作爲密碼管理存儲服務...我需要讓用戶存儲密碼...並檢索它們作爲這種情況下,哈希不是一個選項。 – sylbae
有*必須*是一個祕密組件,它不是祕密,如果它在同一臺機器上(不管你怎麼想)。如果您正在製作密碼存儲服務,則您有一個帳戶密碼和存儲的密碼。如果您使用純文本帳戶密碼來加密存儲的密碼並僅存儲帳戶密碼的散列,則應該沒問題。 –
我已經通過這種方法遠遠更好的更安全的結果,所以他們是 – rogue39nin
使用此:
public class Crypto
{
#region enums, constants & fields
//types of symmetric encyption
public enum CryptoTypes
{
encTypeDES = 0,
encTypeRC2,
encTypeRijndael,
encTypeTripleDES
}
private const string CRYPT_DEFAULT_PASSWORD = "yourDefaultPassword"; //"CB06cfE507a1";
private const CryptoTypes CRYPT_DEFAULT_METHOD = CryptoTypes.encTypeRijndael;
private byte[] mKey = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
private byte[] mIV = {65, 110, 68, 26, 69, 178, 200, 219};
private byte[] SaltByteArray = {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76};
private CryptoTypes mCryptoType = CRYPT_DEFAULT_METHOD;
private string mPassword = CRYPT_DEFAULT_PASSWORD;
#endregion
#region Constructors
public Crypto()
{
calculateNewKeyAndIV();
}
public Crypto(CryptoTypes CryptoType)
{
this.CryptoType = CryptoType;
}
#endregion
#region Props
/// <summary>
/// type of encryption/decryption used
/// </summary>
public CryptoTypes CryptoType
{
get
{
return mCryptoType;
}
set
{
if (mCryptoType != value)
{
mCryptoType = value;
calculateNewKeyAndIV();
}
}
}
/// <summary>
/// Passsword Key Property.
/// The password key used when encrypting/decrypting
/// </summary>
public string Password
{
get
{
return mPassword;
}
set
{
if (mPassword != value)
{
mPassword = value;
calculateNewKeyAndIV();
}
}
}
#endregion
#region Encryption
/// <summary>
/// Encrypt a string
/// </summary>
/// <param storeName="inputText">text to encrypt</param>
/// <returns>an encrypted string</returns>
public string Encrypt(string inputText)
{
//declare a new encoder
UTF8Encoding UTF8Encoder = new UTF8Encoding();
//get byte representation of string
byte[] inputBytes = UTF8Encoder.GetBytes(inputText);
//convert back to a string
return Convert.ToBase64String(EncryptDecrypt(inputBytes,true));
}
/// <summary>
/// Encrypt string with user defined password
/// </summary>
/// <param storeName="inputText">text to encrypt</param>
/// <param storeName="password">password to use when encrypting</param>
/// <returns>an encrypted string</returns>
public string Encrypt(string inputText, string password)
{
this.Password = password;
return this.Encrypt(inputText);
}
/// <summary>
/// Encrypt string acc. to cryptoType and with user defined password
/// </summary>
/// <param storeName="inputText">text to encrypt</param>
/// <param storeName="password">password to use when encrypting</param>
/// <param storeName="cryptoType">type of encryption</param>
/// <returns>an encrypted string</returns>
public string Encrypt(string inputText, string password, CryptoTypes cryptoType)
{
mCryptoType = cryptoType;
return this.Encrypt(inputText,password);
}
/// <summary>
/// Encrypt string acc. to cryptoType
/// </summary>
/// <param storeName="inputText">text to encrypt</param>
/// <param storeName="cryptoType">type of encryption</param>
/// <returns>an encrypted string</returns>
public string Encrypt(string inputText, CryptoTypes cryptoType)
{
this.CryptoType = cryptoType;
return this.Encrypt(inputText);
}
#endregion
#region Decryption
/// <summary>
/// decrypts a string
/// </summary>
/// <param storeName="inputText">string to decrypt</param>
/// <returns>a decrypted string</returns>
public string Decrypt(string inputText)
{
//declare a new encoder
UTF8Encoding UTF8Encoder = new UTF8Encoding();
//get byte representation of string
byte[] inputBytes = Convert.FromBase64String(inputText);
//convert back to a string
return UTF8Encoder.GetString(EncryptDecrypt(inputBytes,false));
}
/// <summary>
/// decrypts a string using a user defined password key
/// </summary>
/// <param storeName="inputText">string to decrypt</param>
/// <param storeName="password">password to use when decrypting</param>
/// <returns>a decrypted string</returns>
public string Decrypt(string inputText, string password)
{
this.Password = password;
return Decrypt(inputText);
}
/// <summary>
/// decrypts a string acc. to decryption type and user defined password key
/// </summary>
/// <param storeName="inputText">string to decrypt</param>
/// <param storeName="password">password key used to decrypt</param>
/// <param storeName="cryptoType">type of decryption</param>
/// <returns>a decrypted string</returns>
public string Decrypt(string inputText, string password, CryptoTypes cryptoType)
{
mCryptoType = cryptoType;
return Decrypt(inputText,password);
}
/// <summary>
/// decrypts a string acc. to the decryption type
/// </summary>
/// <param storeName="inputText">string to decrypt</param>
/// <param storeName="cryptoType">type of decryption</param>
/// <returns>a decrypted string</returns>
public string Decrypt(string inputText, CryptoTypes cryptoType)
{
this.CryptoType = cryptoType;
return Decrypt(inputText);
}
#endregion
#region Symmetric Engine
/// <summary>
/// performs the actual enc/dec.
/// </summary>
/// <param storeName="inputBytes">input byte array</param>
/// <param storeName="Encrpyt">wheather or not to perform enc/dec</param>
/// <returns>byte array output</returns>
private byte[] EncryptDecrypt(byte[] inputBytes, bool Encrpyt)
{
//get the correct transform
ICryptoTransform transform = getCryptoTransform(Encrpyt);
//memory stream for output
MemoryStream memStream = new MemoryStream();
try
{
//setup the cryption - output written to memstream
CryptoStream cryptStream = new CryptoStream(memStream,transform,CryptoStreamMode.Write);
//write data to cryption engine
cryptStream.Write(inputBytes,0,inputBytes.Length);
//we are finished
cryptStream.FlushFinalBlock();
//get result
byte[] output = memStream.ToArray();
//finished with engine, so close the stream
cryptStream.Close();
return output;
}
catch (Exception e)
{
//throw an error
throw new Exception("Error in symmetric engine. Error : " + e.Message,e);
}
}
/// <summary>
/// returns the symmetric engine and creates the encyptor/decryptor
/// </summary>
/// <param storeName="encrypt">whether to return a encrpytor or decryptor</param>
/// <returns>ICryptoTransform</returns>
private ICryptoTransform getCryptoTransform(bool encrypt)
{
SymmetricAlgorithm SA = selectAlgorithm();
SA.Key = mKey;
SA.IV = mIV;
if (encrypt)
{
return SA.CreateEncryptor();
}else
{
return SA.CreateDecryptor();
}
}
/// <summary>
/// returns the specific symmetric algorithm acc. to the cryptotype
/// </summary>
/// <returns>SymmetricAlgorithm</returns>
private SymmetricAlgorithm selectAlgorithm()
{
SymmetricAlgorithm SA;
switch (mCryptoType)
{
case CryptoTypes.encTypeDES:
SA = DES.Create();
break;
case CryptoTypes.encTypeRC2:
SA = RC2.Create();
break;
case CryptoTypes.encTypeRijndael:
SA = Rijndael.Create();
break;
case CryptoTypes.encTypeTripleDES:
SA = TripleDES.Create();
break;
default:
SA = TripleDES.Create();
break;
}
return SA;
}
/// <summary>
/// calculates the key and IV acc. to the symmetric method from the password
/// key and IV size dependant on symmetric method
/// </summary>
private void calculateNewKeyAndIV()
{
//use salt so that key cannot be found with dictionary attack
PasswordDeriveBytes pdb = new PasswordDeriveBytes(mPassword,SaltByteArray);
SymmetricAlgorithm algo = selectAlgorithm();
mKey = pdb.GetBytes(algo.KeySize/8);
mIV = pdb.GetBytes(algo.BlockSize/8);
}
#endregion
}
/// <summary>
/// Hashing class. Only static members so no need to create an instance
/// </summary>
public class Hashing
{
#region enum, constants and fields
//types of hashing available
public enum HashingTypes
{
SHA, SHA256, SHA384, SHA512, MD5
}
#endregion
#region static members
public static string Hash(String inputText)
{
return ComputeHash(inputText,HashingTypes.MD5);
}
public static string Hash(String inputText, HashingTypes hashingType)
{
return ComputeHash(inputText,hashingType);
}
/// <summary>
/// returns true if the input text is equal to hashed text
/// </summary>
/// <param storeName="inputText">unhashed text to test</param>
/// <param storeName="hashText">already hashed text</param>
/// <returns>boolean true or false</returns>
public static bool isHashEqual(string inputText, string hashText)
{
return (Hash(inputText) == hashText);
}
public static bool isHashEqual(string inputText, string hashText, HashingTypes hashingType)
{
return (Hash(inputText,hashingType) == hashText);
}
#endregion
#region Hashing Engine
/// <summary>
/// computes the hash code and converts it to string
/// </summary>
/// <param storeName="inputText">input text to be hashed</param>
/// <param storeName="hashingType">type of hashing to use</param>
/// <returns>hashed string</returns>
private static string ComputeHash(string inputText, HashingTypes hashingType)
{
HashAlgorithm HA = getHashAlgorithm(hashingType);
//declare a new encoder
UTF8Encoding UTF8Encoder = new UTF8Encoding();
//get byte representation of input text
byte[] inputBytes = UTF8Encoder.GetBytes(inputText);
//hash the input byte array
byte[] output = HA.ComputeHash(inputBytes);
//convert output byte array to a string
return Convert.ToBase64String(output);
}
/// <summary>
/// returns the specific hashing alorithm
/// </summary>
/// <param storeName="hashingType">type of hashing to use</param>
/// <returns>HashAlgorithm</returns>
private static HashAlgorithm getHashAlgorithm(HashingTypes hashingType)
{
switch (hashingType)
{
case HashingTypes.MD5 :
return new MD5CryptoServiceProvider();
case HashingTypes.SHA :
return new SHA1CryptoServiceProvider();
case HashingTypes.SHA256 :
return new SHA256Managed();
case HashingTypes.SHA384 :
return new SHA384Managed();
case HashingTypes.SHA512 :
return new SHA512Managed();
default :
return new MD5CryptoServiceProvider();
}
}
#endregion
}
您可以使用加密和解密方法進行加密和解密
我用這對我的項目...
如果你使用這個,請確保將IV和鹽更改爲不同的值! –
加密和安全性都非常難題,在嘗試自己實施任何事情之前,你應該確保你理解了正確的話題。至少如果這是爲了在生產中使用! :-) –