加密用户的记录索引

时间:2013-03-12 17:03:54

标签: c# .net asp.net-mvc cryptography

我的ASP.NET MVC Web应用程序代表用户创建一些数据,并将其存储在具有数字主键的记录中的SQL数据库中。我通过主键访问数据。

我希望经过身份验证的用户能够导航到包含(数字)主键的URL,但我不想公开实际的键值。因此,在我看来,我想要加密数字密钥(使用对称加密算法),密码由我的代码中加入的字符串和登录用户的UserID组成。结果URL看起来像:https://foo.com/123abc,其中“123abc”是加密的键值(从字节转换为字符)。理论上(对我的初学者大脑)这个加密的值,即使被恶意方获取,也没有用,除非该方可以使用用户的凭据登录我的网站。

问题1:这是做这种事的正确方法,而且 问题2:知道这些内容的人能否指出我可以用于此目的的简单对称加密API。

3 个答案:

答案 0 :(得分:2)

您可以在SQL表中添加一个列并将其类型设置为uniqueidentifier,并将其值设置为NEWID()然后将其显示给用户,而不是使用PK,此解决方案将具有最少的开销,而仍然提供一个看似随机的系列,你可以稍后再绑定给那个用户。

ALTER TABLE foo ADD foobar uniqueIdentifier default newid();

http://msdn.microsoft.com/en-us/library/ms187942.aspx

答案 1 :(得分:1)

整数的对称加密会非常容易破解你甚至可能都不会打扰。现在,你可以通过Base64编码或者类似的东西对它进行加盐或混淆,但是,这仍然是毫无意义的。数据库主键不是敏感数据。没有访问数据库就没有意义,如果他们可以访问数据库,那么通过他们的id查找特定用户绝对是你的问题。即使是对称加密也会给你的应用程序带来很大的开销,而这些开销根本就没有必要。

如果你真的不想暴露PK,那么在URL中使用其他类似用户名的东西,然后按用户查找用户。

答案 2 :(得分:0)

你可以这样做,当然。

将salt存储在会话中,每次随机生成一个或使用会话ID作为salt。

以下是两种可以使用salt加密/解密字符串值的方法。您可以使用盐代替初始矢量。

public static string Encrypt(string PlainText, string Password, string Salt,
 string HashAlgorithm = "SHA1", int PasswordIterations = 16, string InitialVector = "Initial Vector", int KeySize = 256)
{  
    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
    byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
    byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
    PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
    byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
    RijndaelManaged SymmetricKey = new RijndaelManaged();
    SymmetricKey.Mode = CipherMode.CBC;

    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);

    MemoryStream MemStream = new MemoryStream();
    CryptoStream cryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    cryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    cryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();

    MemStream.Close();
    cryptoStream.Close();
    Encryptor.Dispose();
    Encryptor = null;

    return Convert.ToBase64String(CipherTextBytes);
}


public static string Decrypt(string CipherText, string Password, string Salt,
    string HashAlgorithm = "SHA1", int PasswordIterations = 16, string InitialVector = "Initial Vector", int KeySize = 256)
{ 
    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
    byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
    byte[] CipherTextBytes = Convert.FromBase64String(CipherText);
    PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
    byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
    RijndaelManaged SymmetricKey = new RijndaelManaged();
    SymmetricKey.Mode = CipherMode.CBC;

    ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream(CipherTextBytes);
    CryptoStream cryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read);
    byte[] PlainTextBytes = new byte[CipherTextBytes.Length];

    int ByteCount = cryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);

    MemStream.Close();
    cryptoStream.Close();
    Decryptor.Dispose();
    Decryptor = null;

    return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount);
}