如何计算文本的真实 SHA1?
How to calculate the real SHA1 of a text?
与 一样(请参阅此处的详细信息),我正在使用
SELECT encode(digest(x::text::bytea, 'sha1'), 'hex') FROM xtmp;
没解决,和原来的哈希不一样。。。可能是::text
强制内部表示用\n
符号,所以一个解决方案会直接转换成bytea
,但这是无效的演员表。
其他解决方法也不是解决方案,
SELECT encode(digest( replace(x::text,'\n',E'\n')::bytea, 'sha1' ), 'hex')
FROM xtmp
...我尝试 CREATE TABLE btmp (x bytea)
和 COPY btmp FROM '/tmp/test.xml' ( FORMAT binary )
,但错误 ("unknown COPY file signature").
简单的解决方法!添加一个“\n”.
SELECT encode(digest((x::text||E'\n')::bytea, 'sha1'), 'hex') FROM xtmp;
但真正的问题是在不剪切最后一个“\n”(最后一个 EOL)的情况下获取原始文件...让我们看看 :
处的函数
INSERT INTO xtmp (x)
SELECT array_to_string(array_agg(x),E'\n')::xml FROM ttmp
;
这里是 "bug"(解决 COPY
后不会将完整文件加载到一行一个字段中)。
array_to_string()
没有添加最后一个 EOL,所以通过 || E'\n'
连接修复了错误。
注意事项
检查其他假设并为测试套件提供一个好的解决方案。
POSIX规则不是问题...
行尾 (EOL) 是 POSIX 文件系统(和非二进制模式)的一项义务,请参阅 this answer about EOL。我们可以想象像 "string and file representations differ by an EOL" 这样的东西……我们可以检查一下吗?它有什么不同?
我们可以通过终端显示无"string vs file"问题,无EOL怪癖:
printf "<root/>" > original1.xml
printf "<root/>\n" > original2.xml
sha1sum original*.xml
printf "<root/>" | openssl sha1
printf "<root/>\n" | openssl sha1
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d original1.xml
a05d91cbf0902b0fe341c979e9fc18fc69813f55 original2.xml
(stdin)= 062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
(stdin)= a05d91cbf0902b0fe341c979e9fc18fc69813f55
所以sha1sum
没有使用额外的EOL,字符串和文件是一些。
现在SQL,同样的结论:
SELECT encode(digest('<root/>'::bytea, 'sha1'), 'hex') ;
SELECT encode(digest(E'<root/>\n'::bytea, 'sha1'), 'hex') ;
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
a05d91cbf0902b0fe341c979e9fc18fc69813f55
更好的测试套件的解决方案
对于这个简单的 load/save text 过程,COPY
命令很丑陋,让我们使用直接的 getfile 函数代替:
CREATE FUNCTION getfile(p_file text) RETURNS text AS $$
with open(args[0],"r") as content_file:
content = content_file.read()
return content
$$ LANGUAGE PLpythonU;
SELECT encode(digest( getfile('/tmp/original1.xml') ::bytea, 'sha1'), 'hex') ;
SELECT encode(digest( getfile('/tmp/original2.xml') ::bytea, 'sha1'), 'hex') ;
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
a05d91cbf0902b0fe341c979e9fc18fc69813f55
完美 (!),现在没有 EOL 问题。
与
SELECT encode(digest(x::text::bytea, 'sha1'), 'hex') FROM xtmp;
没解决,和原来的哈希不一样。。。可能是::text
强制内部表示用\n
符号,所以一个解决方案会直接转换成bytea
,但这是无效的演员表。
其他解决方法也不是解决方案,
SELECT encode(digest( replace(x::text,'\n',E'\n')::bytea, 'sha1' ), 'hex')
FROM xtmp
...我尝试 CREATE TABLE btmp (x bytea)
和 COPY btmp FROM '/tmp/test.xml' ( FORMAT binary )
,但错误 ("unknown COPY file signature").
简单的解决方法!添加一个“\n”.
SELECT encode(digest((x::text||E'\n')::bytea, 'sha1'), 'hex') FROM xtmp;
但真正的问题是在不剪切最后一个“\n”(最后一个 EOL)的情况下获取原始文件...让我们看看
INSERT INTO xtmp (x)
SELECT array_to_string(array_agg(x),E'\n')::xml FROM ttmp
;
这里是 "bug"(解决 COPY
后不会将完整文件加载到一行一个字段中)。 array_to_string()
没有添加最后一个 EOL,所以通过 || E'\n'
连接修复了错误。
注意事项
检查其他假设并为测试套件提供一个好的解决方案。
POSIX规则不是问题...
行尾 (EOL) 是 POSIX 文件系统(和非二进制模式)的一项义务,请参阅 this answer about EOL。我们可以想象像 "string and file representations differ by an EOL" 这样的东西……我们可以检查一下吗?它有什么不同?
我们可以通过终端显示无"string vs file"问题,无EOL怪癖:
printf "<root/>" > original1.xml
printf "<root/>\n" > original2.xml
sha1sum original*.xml
printf "<root/>" | openssl sha1
printf "<root/>\n" | openssl sha1
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d original1.xml
a05d91cbf0902b0fe341c979e9fc18fc69813f55 original2.xml
(stdin)= 062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
(stdin)= a05d91cbf0902b0fe341c979e9fc18fc69813f55
所以sha1sum
没有使用额外的EOL,字符串和文件是一些。
现在SQL,同样的结论:
SELECT encode(digest('<root/>'::bytea, 'sha1'), 'hex') ;
SELECT encode(digest(E'<root/>\n'::bytea, 'sha1'), 'hex') ;
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
a05d91cbf0902b0fe341c979e9fc18fc69813f55
更好的测试套件的解决方案
对于这个简单的 load/save text 过程,COPY
命令很丑陋,让我们使用直接的 getfile 函数代替:
CREATE FUNCTION getfile(p_file text) RETURNS text AS $$
with open(args[0],"r") as content_file:
content = content_file.read()
return content
$$ LANGUAGE PLpythonU;
SELECT encode(digest( getfile('/tmp/original1.xml') ::bytea, 'sha1'), 'hex') ;
SELECT encode(digest( getfile('/tmp/original2.xml') ::bytea, 'sha1'), 'hex') ;
结果
062c3db8ce3458fc3ccaf2f930bf663d8ce31d7d
a05d91cbf0902b0fe341c979e9fc18fc69813f55
完美 (!),现在没有 EOL 问题。