如何加密/解密以存储敏感数据(ASP.NET Web API项目)

时间:2022-03-22 17:53:45

I am currently developping a web service. As part of this web service, I am be able to securely store user password in a SQL DB, and be able to unencrypt password value to the end-user through HTTPS web service.

我目前正在开发一个Web服务。作为此Web服务的一部分,我能够在SQL DB中安全地存储用户密码,并能够通过HTTPS Web服务将密码值解密到最终用户。

It's the first time I have to deal with this requirement. I found many example based on symetric and/or asymetric encryption. However I don't understand to permanently store the password/key used to encrypt the data.

这是我第一次处理这个要求。我发现很多基于对称和/或不对称加密的例子。但是我不明白永久存储用于加密数据的密码/密钥。

For instance, if I do use a symetric encryption based on RijndaelManaged, how do I securely store the input parameters used for the encryption so that my web service can at a later time retrieve data for the SQL DB, and unencrypt them.

例如,如果我使用基于RijndaelManaged的对称加密,如何安全地存储用于加密的输入参数,以便我的Web服务稍后可以检索SQL DB的数据,并解密它们。

2 个解决方案

#1


3  

securely store user password in a SQL DB, and be able to unencrypt password value

在SQL DB中安全地存储用户密码,并且能够解密密码值

That's not secure. Passwords should never be encrypted; they should be hashed! With a salt and a hashing algorithm that is suited for pashword hashing.

这不安全。密码永远不应加密;他们应该被散列!使用盐和哈希算法,适用于pashword哈希。

#2


1  

Use this:

用这个:

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

}

You can use Encrypt and Decrypt methods for encryption and decryption

您可以使用Encrypt和Decrypt方法进行加密和解密

I used this on my projects...

我在我的项目中使用了这个......

#1


3  

securely store user password in a SQL DB, and be able to unencrypt password value

在SQL DB中安全地存储用户密码,并且能够解密密码值

That's not secure. Passwords should never be encrypted; they should be hashed! With a salt and a hashing algorithm that is suited for pashword hashing.

这不安全。密码永远不应加密;他们应该被散列!使用盐和哈希算法,适用于pashword哈希。

#2


1  

Use this:

用这个:

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

}

You can use Encrypt and Decrypt methods for encryption and decryption

您可以使用Encrypt和Decrypt方法进行加密和解密

I used this on my projects...

我在我的项目中使用了这个......