【发布时间】:2021-08-18 19:50:01
【问题描述】:
我的目标是集成一个API service,它希望我按照这些步骤生成签名。
- 检索您的 clientId。
- 用句点 (.) 分隔的 CURRENT UNIX 时间戳附加它
- 使用您收到的公钥使用 RSA 加密来加密此数据 - 这就是签名。
- 通过标头 X-Cf-Signature 传递此签名。
第 3 步是签名生成步骤。在我的 ruby 应用程序中,这就是我实现这些步骤的方式。
def dynamic_signature
raw_data = "#{client_id}.#{Time.now.to_i}"
filepath = "public_key.pem"
public_key = OpenSSL::PKey::RSA.new File.read(filepath)
Base64.strict_encode64(public_key.public_encrypt(raw_data)).encode("UTF-8")
end
但 API 服务拒绝此签名。他们在 php 中有代码 sn-p 示例,因此使用以下代码在 php 中尝试了此过程。我已经使用上面 ruby 代码中的变量来表示。
<?php
$plainData = <raw_data>;
$publicKey = <public_key.to_s>;
openssl_public_encrypt($plainData, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
echo base64_encode($encrypted);
?>
此签名被 API 服务接受。
我做了一些手动检查,两个 base64 输出明显不同。在 ruby 中,我尝试过使用和不使用 encode("UTF-8")。
有趣的是,以下语句返回 true,无论我执行 strict_encode64 或 encode64 还是在末尾附加 encode("UTF-8")。
base64_generated_in_ruby.bytes == base64_generated_in_php.bytes
我通过在 ruby 控制台中复制粘贴 base64 编码的字符串来进行此相等性检查。
我怀疑 base64 编码对这两种语言中的转义字符的工作方式不同。任何帮助表示赞赏。
编辑 1:添加示例。
- 我在 base64 中编码的 RSA 加密字符串。
"g\xF3\f%\xA2\xC0(\xCBYAw\x80\xA5 c\x9DR\xC7r\xFE\xAF \xADJ\xCBy\x8D\xC8kd#\xD3\x04L(\x9B\xC0V\n\xCD\xFF\xD4\rj\xF0\x12\x86\xEC5\xC6ev\xCEUD\x9B\xA2\xAD\x9F{\xC8\xF5\x8A\x00->\xB5\xA4f\x05\x9F\xE1\x81u\xB5\x87\xD4\xD7\xA7\xCC\xE0:\xC9\xF3,\x8D(\x10\xEC\\\xE8'\r\xFA\x14\x82\x8A\xCF_^\xAA\x94\x17\x15\xD0Qw\x18\xDB\xE7\t\xEEy\x9E04\x94\xDE\xFB\xF6\xEB:\xDF\x90\xDER\xEB\xF1c\xF2\x98\x00\x9CM\x16\xA6{\x12\xA8\xA2\xE7\x00\x89\xDE\xB4\x9C\xB1\xE9\x81\x9D\xB4\xC8~q\x8A\xBDu#\xD2\xD2\x19T\xE4H\x7F\x0E\xDF\xECV\x8E\rF\xF7\x12m\x1C\xFE-\xC2gO\x90\xEDp\x88\x1A\x1D\t4\xC2\r!\xD5Y\xC3\xBB\xB8*B%\x00\xDF\xE2s\x8A\x19j\xFB\xEBy\xD7\xD6\xF5\x06\x99\xEE\xEA\xE4\xA3\x83\x97\xDB\x95\xA2o\x86\x97c\xA8w\xAAb\xEF\x00e\xC4\b\xD3\xEB\xFB\x86\xF4\xE2!\xF1{\xA5\x80\xD7\xC4\xC4\x01,\xBFj-"
- 使用 ruby 作为
Base64.strict_encode64(rsa_string)
"Z/MMJaLAKMtZQXeApSBjnVLHcv6vIK1Ky3mNyGtkI9METCibwFYKzf/UDWrwEobsNcZlds5VRJuirZ97yPWKAC0+taRmBZ/hgXW1h9TXp8zgOsnzLI0oEOxc6CcN+hSCis9fXqqUFxXQUXcY2+cJ7nmeMDSU3vv26zrfkN5S6/Fj8pgAnE0WpnsSqKLnAInetJyx6YGdtMh+cYq9dSPS0hlU5Eh/Dt/sVo4NRvcSbRz+LcJnT5DtcIgaHQk0wg0h1VnDu7gqQiUA3+Jzihlq++t519b1Bpnu6uSjg5fblaJvhpdjqHeqYu8AZcQI0+v7hvTiIfF7pYDXxMQBLL9qLQ=="
- 使用php作为
base64_encode($rsa_string)
"Z/MMJaLAKMtZQXeApSBjnVLHcv6vIK1Ky3mNyGtkI9METCibwFYKzf/UDWrwEobsNcZlds5VRJuirZ97yPWKAC0+taRmBZ/hgXW1h9TXp8zgOsnzLI0oEOxc6CcN+hSCis9fXqqUFxXQUXcY2+cJ7nmeMDSU3vv26zrfkN5S6/Fj8pgAnE0WpnsSqKLnAInetJyx6YGdtMh+cYq9dSPS0hlU5Eh/Dt/sVo4NRvcSbRz+LcJnT5DtcIgaHQk0wg0h1VnDu7gqQiUA3+Jzihlq++t519b1Bpnu6uSjg5fblaJvhpdjqHeqYu8AZcRcYtPr+4b04iHxe6WA18TEASy/ai0="
【问题讨论】:
-
能否请您显示两个 base64 编码的字符串。 Base64 只编码字节,不关心编码。
-
我已经有一段时间没有做Ruby了,但不应该是
raw_data = "#{client_id}.#{Time.now.to_i}"吗?你错过了第二个#。 -
输出匹配直到最后一位的方式让我认为您可能存在填充不匹配。由于接受 PHP 版本,因此您的 Ruby 代码中的
public_encrypt()中可能缺少一个选项。 -
@sammitch 我的填充不匹配。我现在已经修好了。非常感谢!
-
如果这个问题得到解决,您能否回答您自己的问题(如果您认为它对其他人有用)或删除它?
标签: php ruby base64 escaping rsa