Postgres:如何通过每4个字节进行异或来将16个字节转换为4个字节

时间:2016-03-16 19:36:07

标签: postgresql cryptography md5 xor

我有一个16字节的md5哈希,我需要"折叠"使用XOR转换为4字节数据:{1st 4 bytes} XOR {2nd 4 bytes} XOR {3rd 4 bytes} XOR {4th 4 字节}。然后我需要将结果转换为Hex形式(8个字符串)。

我正在生成这样的哈希(解码为十六进制,因为它似乎更容易处理):

SELECT decode(md5('test'), 'hex');

但就我而言。我不知道将16字节散列分成4个4字节值的最佳方法,然后对这些4字节值进行异或。

2 个答案:

答案 0 :(得分:0)

不幸的是,docs对于使用位字符串值可以做什么有点模糊,但提到了substring函数(sytax在string functions page上),可以使用从中提取部分:

select i1 # i2 # i3 # i4
from   cast('x' || md5('test') as bit(128)) bits,
       cast(substring(bits from 97 for 32) as int4) i1,
       cast(substring(bits from 65 for 32) as int4) i2,
       cast(substring(bits from 33 for 32) as int4) i3,
       cast(substring(bits from  1 for 32) as int4) i4

注意:低位在其位串表示中具有更高的索引,f.ex。

select 3::bit(32)
-- will yield '00000000000000000000000000000011'

答案 1 :(得分:0)

在花了一些时间理解this回答之后,我能够想出这个:

CREATE OR REPLACE FUNCTION compressed_md5(var_txt TEXT) RETURNS TEXT
AS $$
DECLARE
  var_hash BYTEA;
  var_compressedHash BYTEA;
  var_offset INTEGER;
BEGIN
  var_hash := decode(md5(var_txt), 'hex');
  var_compressedHash := decode('00000000', 'hex'); -- prepopulate with some 4-byte data
  FOR var_offset IN 0..3 LOOP
    var_compressedHash := set_byte(var_compressedHash, var_offset,
                                   get_byte(var_hash, var_offset) #
                                   get_byte(var_hash, var_offset + 4) #
                                   get_byte(var_hash, var_offset + 8) #
                                   get_byte(var_hash, var_offset + 12));
  END LOOP;
  RETURN encode(var_compressedHash, 'hex');
END;
$$ LANGUAGE plpgsql;

SELECT compressed_md5('test');

结果:

"a35742cb"