Binary_checksum()& SQL Server中的checksum()函数?

时间:2018-03-18 06:28:16

标签: sql-server tsql hash checksum

SQL Server提供了Checksum(),Binary_Checksum() CHECKSUM_AVG()函数,以根据表达式或列列表构建哈希索引。那么这可以帮助确定行是否已经改变。然后可以使用该机制来识别记录是否已经更新。

但我发现了很多碰撞的例子,它们为不同的值生成相同的哈希值。我们如何识别这些功能的碰撞条件。

任何人都必须知道用于生成/计算哈希的算法或技术。????

2 个答案:

答案 0 :(得分:2)

根据sqlTeam上的CHECKSUM weakness explained文章:

  

SQL Server中的内置CHECKUM函数基于一系列4位左旋转xor运算。

由Peter Larsson发布的forum post from 2006(在文章中也链接)包括计算校验和的SQL用户定义函数。该帖子的作者声称与SQL Server的内置功能100%兼容(我自己没有对其进行过测试)。

如果链接失效,这里是相关部分的副本:

使用text / varchar / image数据,使用SELECT BINARY_CHECKSUM('abcdefghijklmnop')dbo.fnPesoBinaryChecksum('abcdefghijklmnop')进行调用 对于整数数据,请使用SELECT BINARY_CHECKSUM(123)dbo.fnPesoBinaryChecksum(CAST(123 AS VARBINARY))进行通话 我还没弄明白如何计算大于255的整数的校验和。

CREATE FUNCTION dbo.fnPesoBinaryChecksum
(
    @Data IMAGE
)
RETURNS INT
AS

BEGIN
    DECLARE @Index INT,
        @MaxIndex INT,
        @SUM BIGINT,
        @Overflow TINYINT

    SELECT  @Index = 1,
        @MaxIndex = DATALENGTH(@Data),
        @SUM = 0

    WHILE @Index <= @MaxIndex
        SELECT  @SUM = (16 * @SUM) ^ SUBSTRING(@Data, @Index, 1),
            @Overflow = @SUM / 4294967296,
            @SUM = @SUM - @Overflow * 4294967296,
            @SUM = @SUM ^ @Overflow,
            @Index = @Index + 1

    IF @SUM > 2147483647
        SET @SUM = @SUM - 4294967296
    ELSE IF @SUM BETWEEN 32768 AND 65535
        SET @SUM = @SUM - 65536
    ELSE IF @SUM BETWEEN 128 AND 255
        SET @SUM = @SUM - 256

    RETURN @SUM
END
  

实际上这是对MS功能的改进,因为它接受TEXT和IMAGE数据。

CREATE FUNCTION [dbo].[fnPesoTextChecksum]
(
    @Data TEXT
)
RETURNS INT
AS

BEGIN
    DECLARE @Index INT,
        @MaxIndex INT,
        @SUM BIGINT,
        @Overflow TINYINT

    SELECT  @Index = 1,
        @MaxIndex = DATALENGTH(@Data),
        @SUM = 0

    WHILE @Index <= @MaxIndex
        SELECT  @SUM = (16 * @SUM) ^ ASCII(SUBSTRING(@Data, @Index, 1)),
            @Overflow = @SUM / 4294967296,
            @SUM = @SUM - @Overflow * 4294967296,
            @SUM = @SUM ^ @Overflow,
            @Index = @Index + 1

    IF @SUM > 2147483647
        SET @SUM = @SUM - 4294967296
    ELSE IF @SUM BETWEEN 32768 AND 65535
        SET @SUM = @SUM - 65536
    ELSE IF @SUM BETWEEN 128 AND 255
        SET @SUM = @SUM - 256

    RETURN  @SUM
END

另一个好的读物是Thomas Kejser的Exploring Hash Functions In SQL Server,作者在sql server中检查内置的哈希函数,以提高质量。

答案 1 :(得分:-1)

BINARY_CHECKSUM的PHP实现:

$input = 'binary string';
$sum = 0;
for ($i = 0; $i < strlen($input); $i++) {
    $sum = ($sum << 4) ^ ord($in[$i]);
    $sum = ($sum & 0xffffffff) ^ ($sum >> 32);
}
return $sum > 0x7fffffff ? $sum - 0x100000000 : $sum;