【问题标题】:Output difference with successive RSA encryption and base64 encoding in php and rubyphp和ruby中连续RSA加密和base64编码的输出差异
【发布时间】:2021-08-18 19:50:01
【问题描述】:

我的目标是集成一个API service,它希望我按照这些步骤生成签名。

  1. 检索您的 clientId。
  2. 用句点 (.) 分隔的 CURRENT UNIX 时间戳附加它
  3. 使用您收到的公钥使用 RSA 加密来加密此数据 - 这就是签名。
  4. 通过标头 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_encode64encode64 还是在末尾附加 encode("UTF-8")

base64_generated_in_ruby.bytes == base64_generated_in_php.bytes

我通过在 ruby​​ 控制台中复制粘贴 base64 编码的字符串来进行此相等性检查。

我怀疑 base64 编码对这两种语言中的转义字符的工作方式不同。任何帮助表示赞赏。

编辑 1:添加示例。

  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-"
  1. 使用 ruby​​ 作为Base64.strict_encode64(rsa_string)
"Z/MMJaLAKMtZQXeApSBjnVLHcv6vIK1Ky3mNyGtkI9METCibwFYKzf/UDWrwEobsNcZlds5VRJuirZ97yPWKAC0+taRmBZ/hgXW1h9TXp8zgOsnzLI0oEOxc6CcN+hSCis9fXqqUFxXQUXcY2+cJ7nmeMDSU3vv26zrfkN5S6/Fj8pgAnE0WpnsSqKLnAInetJyx6YGdtMh+cYq9dSPS0hlU5Eh/Dt/sVo4NRvcSbRz+LcJnT5DtcIgaHQk0wg0h1VnDu7gqQiUA3+Jzihlq++t519b1Bpnu6uSjg5fblaJvhpdjqHeqYu8AZcQI0+v7hvTiIfF7pYDXxMQBLL9qLQ=="
  1. 使用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


【解决方案1】:

ruby public_encrypt 方法默认不包含填充参数。使用public_encrypt(raw_data, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING) 添加相关的填充参数。在提供的 php 代码中明确提到了提交的填充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 2015-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-15
    • 2011-04-26
    相关资源
    最近更新 更多