如果我每次都可以运行以下脚本,source ./script.sh但如果直接将其作为 执行,则大约 80% 的情况会失败./script.sh。
#!/bin/bash
signing_input="Hi."
signature=$(echo -n "$signing_input" | openssl dgst -sha256 -sign private.pem)
echo -n "$signing_input" | openssl dgst -sha256 -verify public.pem -signature <(echo -n "$signature")
Run Code Online (Sandbox Code Playgroud)
因此,如果我“获取”该内容或逐行运行,我总是会得到:Verified OK
...但是如果我在脚本中运行它,我通常但并不总是得到:Error verifying data
如果我先将签名保存到文件中,我会得到相同的结果。
我.pem这样生成文件:
openssl ecparam -name secp256k1 -genkey -noout -out private.pem
openssl ec -in private.pem -pubout -out public.pem
Run Code Online (Sandbox Code Playgroud)
...我是否每次重复使用它们或重新生成它们并不重要。
我在 Mac M1 上运行 iTerm2 和 zsh。
这真的是编程还是开发?我不确定,但除非投票界另有决定,否则我将其称为边界。
这是二进制数据——有时包括“空”(零值)字节。阶数非常接近 2^256(secp256k1 )的曲线组的 ECDSA 签名格式具有 6 个永远不为零的元数据字节、0-2 个填充字节(当存在时始终为零,并且至少存在一个 75% 减去) epsilon 的时间,几乎总是 64 字节,除了两个与均匀随机无法区分外,因此至少其中一个为零 1-(1-1/256)^62 = 21.5463% 的时间独立于填充字节 - - 因此 1-(1-.75)(1-.215463) = 80.3866% 是此类签名中至少有一个零字节的概率。
并且bash无法处理变量中的空字节,因此您的$signature值被破坏且错误,并且验证失败。当这种情况发生时,现代版本会bash发出警告——你是忽略了它,还是你的版本太古老了?
签名数据也有可能以换行字节(值 0x0A)(甚至多个)结尾,在这种情况下,命令替换会$(...)删除它(或它们)——但仅多于 1/256 ~ 0.4%,可以忽略不计,考虑到较早出现 null 的可能性,这只会增加大约 0.1% 的损坏几率。
当您source使用文件时,它是由zshNOT by bash(shebang 被忽略)执行的,并且zsh确实处理空字节,因此它大部分都可以工作 - 但在尾随换行符的 0.4% 情况下,zsh 也会失败。
如果您改为写入文件并读回,则这将始终在两个/所有 shell 中工作。或者,如果您编码(和解码)不使用空值(并忽略换行符)的形式,例如 base64:
signature=$(echo -n "$data" | openssl dgst -sha256 -sign private | openssl base64 -e)
echo -n "$data" | openssl dgst -sha256 -verify public -signature <(echo $signature | openssl base64 -d)
# base64 never contains chars that need quoting, and adding newline to it is fine
# (in fact the base64 -e command included a trailing newline which $(...) _removed_)
Run Code Online (Sandbox Code Playgroud)
十六进制也可以,但不能openssl单独完成,而且我不知道我可以依赖您的系统有哪些其他程序。
| 归档时间: |
|
| 查看次数: |
47 次 |
| 最近记录: |