Ruby与OpenSSL命令行SHA1 RSA签名结果不一致问题排查
RSA-SHA1签名不一致?大概率是隐藏的换行符在搞鬼!
我之前也踩过这个坑,你的问题核心其实不是编码——而是直接字符串和文件里的内容字节不完全一致,最常见的原因就是文件里多了个换行符!
先排查最可能的原因:文件里的隐藏换行
你在命令行里执行cat data.txt显示是000,但实际保存文件时,很多编辑器会自动在末尾加换行符(LF,十六进制0x0a)。而Ruby里直接写的"000"是没有这个换行字节的,两者的原始数据不一样,签名结果自然不同。
验证这个很简单:
- 用十六进制查看工具看文件内容:
如果输出是hexdump -C data.txt30 30 30 0a,说明文件末尾有换行;而Ruby的"000"对应的十六进制是30 30 30,少了最后的0x0a。 - 你可以在Ruby里把字符串改成
"000\n"再签名,看看是不是和命令行生成的结果一致——大概率会匹配!
为什么编码排查没找到问题?
你提到转编码后还是不一致,因为换行符是ASCII范围内的字符,无论是UTF-8还是ASCII编码,它的字节值都是0x0a,转编码不会改变这个字节。所以编码不是问题,问题是有没有这个字节。
解决方案
- 确认文件的实际内容:用
od -c data.txt查看文件里的所有字符,包括空白和换行:
如果看到输出最后有od -c data.txt\n,就说明文件有换行。 - 让Ruby字符串匹配文件内容:
- 如果文件有换行,Ruby里就用
"000\n";如果是Windows下的CRLF换行(\r\n),就用"000\r\n"。
- 如果文件有换行,Ruby里就用
- 读取文件时避免自动转换换行:
用二进制模式读取文件,防止Ruby自动转换换行符(比如Windows下把CRLF转成LF):message = File.read(Rails.root.join('lib', 'payment', 'data.txt'), mode: 'rb')
补充验证
你可以对比两种方式的字节长度:
- Ruby里
"000".length是3;如果文件有换行,File.read(data.txt).length是4。
用message.bytes查看具体的字节值,就能一眼看出差异!
内容的提问来源于stack exchange,提问作者Geoffrey H
相关产品推荐
相关产品推荐

