匹配在RubyonRails和JavaScript中加密的签名标头

Matching Signed Headers Encrypted in Ruby on Rails and JavaScript

本文关键字:加密 RubyonRails JavaScript      更新时间:2023-09-26

我正在使用ApiAuth gem(如此处所示)对我的请求进行签名。我还使用CryptoJS(如这里所示)编写了自己的JavaScript代码,通过将ApiAuth生成的加密头与我的代码生成的头进行检查来提供身份验证。

以下是ApiAuth Gem:的代码片段

def hmac_signature(headers, secret_key, options)
  if options[:with_http_method]
    canonical_string = headers.canonical_string_with_http_method(options[:override_http_method])
  else
    canonical_string = headers.canonical_string
  end
  digest = OpenSSL::Digest.new('sha1')
  b64_encode(OpenSSL::HMAC.digest(digest, secret_key, canonical_string))
end

以下是我用JavaScript编写的等效代码:

function hmacSignature(request, appSecret) {
 return CryptoJS.HmacSHA1(canonicalString(request), appSecret).toString(CryptoJS.enc.Base64);}

这两个不会生成相同的加密头。我尝试使用jsSHA做同样的事情,虽然jsSHA和CryptoJS生成的加密头是相同的,但它们与ApiAuth生成的不匹配。

请帮我想办法把它做好。

编辑:

将规范字符串作为"消息",将appSecret作为"秘密",我从ApiAuth和CryptoJS中得到了相同的值,即:

DK9kn+7klT2Hv5A6wRdsReAo3xY=

我已经发现,我的原始代码中的问题即将出现,因为我的JS代码中设置的时间戳和ApiAuth中设置的不匹配。

我解决了我的问题,并编写了这个答案,希望它能帮助其他人寻找这个问题的解决方案。

  1. 让我首先说,无论是用Ruby、JS还是任何其他语言加密,这两种加密都应该是相同的
  2. 重要的是要检查发送到两个地方的输入的每一部分是否完全相同

当我检查我对JS文件和gem的输入时,我意识到由于某种原因,时间戳(我在JS文件中设置的)没有正确发送到gem。

我一步一步地调试代码,找出了错误的地方。我在下面概述了一些可能的问题:

  1. 我在JS中设置时间戳如下

    request.headers["DATE"]

我意识到这一设置不正确,所以我不得不将"DATE"更改为"DATE1",并相应地更改其余代码。这起到了作用。

  1. 其次,我发送的时间戳与gem所期望的HTTP GST类型的时间戳不兼容。这是发送时间戳时必须记住的另一件事