【发布时间】:2011-06-30 23:12:03
【问题描述】:
我在 SQL Server 2008 r2 中有用户表。还没有加密,但我想至少加密密码,直到应用程序准备好可以更好地处理这个问题。我可以这样做吗?怎么做?手动加密密码。
【问题讨论】:
标签: sql-server sql-server-2008 encryption
我在 SQL Server 2008 r2 中有用户表。还没有加密,但我想至少加密密码,直到应用程序准备好可以更好地处理这个问题。我可以这样做吗?怎么做?手动加密密码。
【问题讨论】:
标签: sql-server sql-server-2008 encryption
您可以使用 SQL Server 加密列,(请参阅:http://msdn.microsoft.com/en-us/library/ms179331.aspx 了解演练)。
您也可以使用服务器本身提供的密钥。
使用此方法的风险是,如果您必须进行数据恢复并将数据库移动到不同的服务器,则无法解密该列(需要重置密码)。
【讨论】:
注意:密码散列不适用于 2 路加密(流氓 dba 可以解密)。它旨在以一种允许验证的方式对其进行散列,而无需向任何人简单地显示密码。在某些方面可取低甚至中等级别的冲突,因此它允许密码通过(不幸的是其他变体)但有冲突你永远无法知道真正的密码到底是什么。
INSERT INTO <tbl> (..., passwd) values (...., HashBytes('SHA1', @password))
验证密码时,您获取密码的哈希
SELECT HashBytes('SHA1', @password);
并将其与输入进行比较。
【讨论】:
您实际上并不想对其进行加密,而是对其使用哈希函数。除非有强烈要求访问未加密的密码。
【讨论】:
我们可以创建一些简单的 sql 函数来加密和解密您网页中的密码列:
代码:加密
`CREATE FUNCTION [dbo].[ENCRYPT]
(
@DB_ROLE_PASSWORD VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE
@STR_LEN NUMERIC(10),
@ENCRYPTED_PASSWORD VARCHAR(100),
@TRIAL_CHARACTER VARCHAR(1),
@TRIAL_NUMBER NUMERIC(4)
SET @ENCRYPTED_PASSWORD = NULL
SET @STR_LEN =LEN(@DB_ROLE_PASSWORD)
DECLARE
@I INT
SET @I = 1
DECLARE
@LOOP$BOUND INT
SET @LOOP$BOUND = @STR_LEN
WHILE @I <= @LOOP$BOUND
BEGIN
/* * SSMA WARNING MESSAGES: * O2SS0273: ORACLE SUBSTR FUNCTION AND SQL SERVER SUBSTRING FUNCTION MAY GIVE DIFFERENT RESULTS. */
SET @TRIAL_CHARACTER = SUBSTRING(@DB_ROLE_PASSWORD, @I, 1)
SET @TRIAL_NUMBER = ASCII(@TRIAL_CHARACTER)
IF (@TRIAL_NUMBER % 2) = 0
SET @TRIAL_NUMBER = @TRIAL_NUMBER - 6
ELSE
SET @TRIAL_NUMBER = @TRIAL_NUMBER - 8
SET @TRIAL_CHARACTER = CHAR(CAST(@TRIAL_NUMBER + @I AS INT))
SET @ENCRYPTED_PASSWORD = ISNULL(@ENCRYPTED_PASSWORD, '') + ISNULL(@TRIAL_CHARACTER, '')
SET @I = @I + 1
END
RETURN @ENCRYPTED_PASSWORD
END`
代码:解密
`CREATE FUNCTION [dbo].[DECRYPT]
(
@DB_ROLE_PASSWORD VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE
@STR_LEN NUMERIC(10),
@DECRYPTED_PASSWORD VARCHAR(100),
@TRIAL_CHARACTER VARCHAR(1),
@TRIAL_NUMBER NUMERIC(4),
@CHECK_CHARACTER VARCHAR(1),
@V_DB_ROLE_PASSWORD VARCHAR(100)
SET @V_DB_ROLE_PASSWORD = @DB_ROLE_PASSWORD
SET @DECRYPTED_PASSWORD = NULL
SET @STR_LEN = LEN(@V_DB_ROLE_PASSWORD)
DECLARE
@I INT
SET @I = 1
DECLARE
@LOOP$BOUND INT
SET @LOOP$BOUND = @STR_LEN
WHILE @I <= @LOOP$BOUND
BEGIN
/*
* SSMA WARNING MESSAGES:
* O2SS0273: ORACLE SUBSTR FUNCTION AND SQL SERVER SUBSTRING FUNCTION MAY GIVE DIFFERENT RESULTS.
*/
SET @TRIAL_CHARACTER = SUBSTRING(@V_DB_ROLE_PASSWORD, @I, 1)
SET @TRIAL_NUMBER = ASCII(@TRIAL_CHARACTER) - @I
IF (@TRIAL_NUMBER % 2) = 0
SET @TRIAL_NUMBER = @TRIAL_NUMBER + 6
/*-IE EVEN*/
ELSE
SET @TRIAL_NUMBER = @TRIAL_NUMBER + 8
/*-IE ODD*/
SET @DECRYPTED_PASSWORD = ISNULL(@DECRYPTED_PASSWORD,'') + ISNULL(CHAR(CAST(@TRIAL_NUMBER AS INT)), '')
SET @I = @I + 1
END
RETURN @DECRYPTED_PASSWORD
END`
【讨论】:
【讨论】:
如果您的唯一任务是验证用户输入的密码是否正确,则不应加密密码。您应该改为散列它们。您可以使用任何算法对其进行哈希处理,但我建议使用 MD5,因为它非常安全。1 :)
例如:
public string EncodePassword(string originalPassword)
{
//Declarations
Byte[] originalBytes;
Byte[] encodedBytes;
MD5 md5;
//Instantiate MD5CryptoServiceProvider, get bytes for original password and compute hash (encoded password)
md5 = new MD5CryptoServiceProvider();
originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
encodedBytes = md5.ComputeHash(originalBytes);
//Convert encoded bytes back to a 'readable' string
return BitConverter.ToString(encodedBytes);
}
1 编辑(不是原始答案作者):密码的 MD5 是considered insecure,应该使用更健壮的算法。在阅读本文时,您应该对当代算法进行研究。 This post 可能是一个很好的起点。
【讨论】: