我需要确保字符串以已知的字符编码进行编码。到目前为止,我对MS SQL Server的研究和测试表明,所记录的编码是'UCS-2',但实际编码(在服务器上)是'UCS-2LE'。
这似乎不太可靠。我喜欢的是PERL,Node或大多数内容中的ENCODE
函数,因此无论升级或设置更改如何,我的哈希函数都将处理已知输入。
我们可以将散列字符串限制为HEX,因此在最坏的情况下,我们可以手动将16个可能的输入字符映射到正确的字节。有人对此提出建议吗?
这是我正在使用的PERL:
use Digest::SHA qw/sha256/;
use Encode qw/encode/;
$seed = 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA';
$string = '123456789';
$target = '57392CD6A5192B6185C5999EB23D240BB7CEFD26E377D904F6FEF262ED176F97';
$encoded = encode('UCS-2LE', $seed.$string);
$sha256 = uc(unpack("H*", sha256($encoded)));
print "$target\n$sha256\n";
哪个匹配MS SQL:
HASHBYTES('SHA_256', 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789')
但我真正想要的是:
HASHBYTES('SHA_256', ENCODE('UCS2-LE', 'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789'))
因此,无论MS SQL将输入字符串编码为什么,HASHBYTES
将始终在已知的字节数组上运行。
答案 0 :(得分:0)
SQL Server仅对声明为nvarchar
的列,变量和文字使用UCS-2。在所有其他情况下,它使用8位ASCII和当前数据库的编码,除非另有说明(例如,使用collate
子句)。
因此,您必须指定Unicode文字:
select HASHBYTES('SHA_256', N'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789');
或者,您可以使用nvarchar
数据类型的变量或表列:
-- Variable
declare @var nvarchar(128) = N'DDFF5D36-F14D-495D-BAA6-3688786D6CFA123456789';
select HASHBYTES('SHA_256', @var);
-- Table column
declare @t table(
Value nvarchar(128)
);
insert into @t
select @var;
select HASHBYTES('SHA_256', t.Value)
from @t t;
P.S。当然,由于Wintel是一个小端平台,SQL Server使用与OS /硬件相同版本的编码。除非SQL Server 2017中出现新的东西,否则无法在本机中本地获得big-endian表示。