将MS SQL哈希文本转换为Postgres哈希文本

问题描述 投票:3回答:1

我正在努力将所有数据库从MS SQL服务器迁移到Postgres。在这个过程中,我正在编写Postgres中的等效代码,以产生在MS SQL中获得的相同散列文本。

以下是我在MS SQL中的代码:

DECLARE @HashedText nvarchar(50) 
DECLARE @InputText nvarchar(50) = 'password'

DECLARE @HashedBytes varbinary(20) -- maximum size of SHA1 output

SELECT @HashedBytes = HASHBYTES('SHA1', @InputText)

SET @HashedText = CONVERT(nvarchar(50), @HashedBytes, 2)

SELECT @HashedText

这产生了值E8F97FBA9104D1EA5047948E6DFB67FACD9F5B73

以下是用Postgres编写的等效代码:

DO
$$
DECLARE v_InputText VARCHAR = 'password';
DECLARE v_HashedText  VARCHAR;
DECLARE v_HashedBytes BYTEA;

BEGIN 
  SELECT 
         ENCODE(DIGEST(v_InputText, 'SHA1'), 'hex')
  INTO
         v_HashedBytes;

  v_HashedText := CAST(v_HashedBytes AS VARCHAR);

  RAISE INFO 'Hashed Text: %', v_HashedText;
END;
$$;

这产生了值5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

花了一些时间后,我才明白在MS SQL中用'VARCHAR'替换数据类型'NVARCHAR'会产生与Postgres相同的结果。

现在的问题是在MS SQL中我们已经有密码哈希并存储在数据库中,如上所示。我无法将MS SQL中的散列文本转换为Postgres,也无法在Postgres中生成相同的散列文本,因为Postgres不支持UTF-16 unicode。

所以,我只是想知道是否有可能遵循解决方案?

  1. 将MS SQL中生成的十六进制值转换为等效于使用VARCHAR数据类型生成的十六进制值(在Postgres中为相同值)
  2. 在Postgres中将UTF8文本转换为UTF16文本(甚至通过任何类型的扩展)并生成十六进制值,这些值等同于在MS SQL中生成的值
postgresql hash
1个回答
2
投票

让我们依次看看你的建议:

  1. 将MS SQL中生成的十六进制值转换为等效于使用VARCHAR数据类型生成的十六进制值(在Postgres中为相同值)

这归结为将用户的密码从UTF-16转换为UTF-8(或其他编码)并重新散列它。要做到这一点,你需要知道用户的密码,从理论上讲,你不需要 - 这就是首先对它进行哈希处理的重点。

在实践中,您使用的是未加盐的SHA1哈希值,其中存在大型预先计算的表格,并且使用GPU优化算法可以实现蛮力。因此,“灰帽子”选项将破解所有用户的密码,并重新哈希。

如果你这样做,使用salt和更好的哈希函数重新哈希它们以及将它们转换为UTF-8可能是明智的。

  1. 在Postgres中将UTF8文本转换为UTF16文本(甚至通过任何类型的扩展)并生成十六进制值,这些值等同于在MS SQL中生成的值

从理论上讲,这更简单,只需要一个例程来进行字符串转换。但是,正如您所发现的,Postgres中没有内置支持。

对于任何完全由ASCII字符组成的字符串,转换很简单:在字符串的每个字节之前插入一个NULL字节(hex 00)。但这会破坏使用不在此范围内的字符的任何密码。

另一种方法是将生成哈希的责任移出数据库:

  1. 从数据库中检索哈希。
  2. 确保用户的输入在应用程序中表示为UTF-16,并计算其哈希值。
  3. 如果有效,您现在可以使用更好的算法生成新哈希(因为您知道用户刚刚键入的密码),并将其存储在DB而不是旧哈希中。
  4. 一旦所有活动用户至少登录一次,您将没有剩余的SHA1哈希值,并且可以完全删除对它们的支持。
© www.soinside.com 2019 - 2024. All rights reserved.