首页 > 解决方案 > 从 base 64 字符串转换时出错

问题描述

我正在尝试加密和解密存储在 SQL 中的密码。解码时出现错误输入不是有效的 Base-64 字符串,因为它包含非 base 64 字符、两个以上的填充字符或填充字符中的非法字符。在 System.Convert.FromBase64_Decode。

解密代码:

string userEmail = Email1.Text;
string userPass = passW.Text;
SqlConnection sqlcon = new SqlConnection("My connection")
string query = "Select * from users Where email= '" + userEmail + "'";
SqlDataAdapter sda = new SqlDataAdapter(query, sqlcon);
DataTable dtbl = new DataTable()
sda.Fill(dtbl);
if (dtbl.Rows.Count == 1)
{
    string savedPasswordHash = dtbl.Rows[0][1].ToString();
    savedPasswordHash.Replace("-", "");
    byte[] hashBytes = Convert.FromBase64String(savedPasswordHash);
    byte[] salt = new byte[16];
    Array.Copy(hashBytes, 0, salt, 0, 16);
    var pbkdf2 = new Rfc2898DeriveBytes(userPass, salt, 10000);
    byte[] hash = pbkdf2.GetBytes(20);
    int ok = 1;
    for (int i = 0; i < 20; i++)
        if (hashBytes[i + 16] != hash[i])
            ok = 0;
            if (ok == 1) //good creds & redirect

加密代码:

byte[] salt1;
new RNGCryptoServiceProvider().GetBytes(salt1 = new byte[16]);
var pbkdf21 = new Rfc2898DeriveBytes(EmailTextBox.Text, salt1, 10000); 

byte[] hash1 = pbkdf21.GetBytes(20);
byte[] hashBytes1 = new byte[36];

Array.Copy(salt1, 0, hashBytes1, 0, 16);
Array.Copy(hash1, 0, hashBytes1, 16, 20);

string savedPasswordHash1 = Convert.ToBase64String(hashBytes1);
string commString = $"UPDATE users SET NewPassword = ('{savedPasswordHash1}') where Email = ('{email2}')";
using (SqlConnection connect = new SqlConnection(constring))
{
    using (SqlCommand comm = new SqlCommand())
    {
        comm.Connection = connect;
        comm.CommandText = commString;
        connect.Open();
        comm.ExecuteNonQuery();
        connect.Close();
    } 

列的数据类型是nvarchar

标签: c#sqlasp.net

解决方案


好的,问题出在您的 SQL 代码中。你不应该像这样在查询中添加值。这会产生 SQL 注入攻击的巨大风险以及您面临的那种问题。

base64 字符串可能包含不打算转到查询字符串的字符。

所以像这样改变加密:

string commString = "UPDATE users SET NewPassword = @PasswordHash where Email = @Email";
using (SqlConnection connect = new SqlConnection(constring))
{
    using (SqlCommand comm = new SqlCommand())
    {
        comm.Connection = connect;
        comm.CommandText = commString;
        comm.Parameters.AddWithValue("PasswordHash", savedPasswordHash1);
        comm.Parameters.AddWithValue("Email", email2);
        connect.Open();
        comm.ExecuteNonQuery();
        connect.Close();
    } 
}

您也可以简化命令创建,但我不想改变两件事。您可以稍后修复它。

- 编辑 -

来来回回之后,很明显问题出在解密而不是加密部分。您按照我上面所说的去做,否则您的代码处于严重危险之中。

string savedPasswordHash = dtbl.Rows[0][27].ToString(); //Change 1 to 27

同时删除下一行

//savedPasswordHash.Replace("-", ""); (Remove)

推荐阅读