如何在Ruby中生成有效的ES256签名

时间:2019-07-25 06:27:20

标签: ruby cryptography jwt mapkit

我正在集成Map Web Snapshot(用于Web的Apple MapKit SDK的一部分),在这里我需要在查询参数中附加URL的签名。文档中的示例代码演示了如何使用NPM的jwa软件包来实现这一目标。

// Required modules.
const { readFileSync } = require("fs");
const { sign } = require("jwa")("ES256");

/* Read your private key from the file system. (Never add your private key
 * in code or in source control. Always keep it secure.)
 */ 
const privateKey = readFileSync("[file_system_path]");
// Replace the team ID and key ID values with your actual values.
const teamId = "[team ID]";
const keyId = "[key ID]";

// Creates the signature string and returns the full Snapshot request URL including the signature.
function sign(params) {
    const snapshotPath = `/api/v1/snapshot?${params}`;
    const completePath = `${snapshotPath}&teamId=${teamId}&keyId=${keyId}`;
    const signature = sign(completePath, privateKey);
    // In this example, the jwa module returns the signature as a Base64 URL-encoded string.

    // Append the signature to the end of the request URL, and return.
    return `${completePath}&signature=${signature}`;
}

// Call the sign function with a simple map request.
sign("center=apple+park") 

// The return value expected is: "/api/v1/snapshot?center=apple+park&teamId=[team ID]&keyId=[key ID]&signature=[base64_url_encoded_signature]"

我想实现相同的目的,但是要使用Ruby。

key_id = ENV['MAPKIT_KEY_ID']
team_id = ENV['MAPKIT_TEAM_ID']
private_key = OpenSSL::PKey::EC.new(ENV['MAPKIT_PRIVATE_KEY'])

def sign(params)
  snapshot_path = "/api/v1/snapshot?#{params}"
  complete_path = "#{snapshot_path}&teamId=#{team_id}&keyId=#{key_id}"
  signature = JWT::Signature.sign('ES256', complete_path, private_key)
  "#{complete_path}&signature=#{signature}"
end

但是,从对JWT::Signature.sign的调用中得到的输出不是我期望的。在JavaScript示例中,我始终会获得86个字符串-类似于T9ENYiGPQHoRQXkNMLlidCL0lrwTR1mra9cIurhAiprdZpM7a-74mNh3DOYXi--FvPOxdUW0Omr-6jo3FWyLFQ。在Ruby示例中,我得到了完全不同的东西-"\x95\xA7\x8A4L\x82>\f_\u0002\xBC_1~;\xAE\xBF\xE5\xC5\u0019W\x86\xDEwG\u0004i\x93CYX\xD2\u0018\x84\\\xD9\xFDf\x877\xF7|rnf\u007FV\xF2<\xA2\u0010\u0003f\xE3)\x8A6n,\f\u0011\xB7#\xDE"

我是在使用ES256在Ruby中对字符串签名的正确方法吗?或者我需要做什么才能在Ruby中获得预期的结果?

2 个答案:

答案 0 :(得分:1)

“ base64url”您的signature变量,如下所示:

signature = Base64.urlsafe_encode64(JWT::Signature.sign('ES256', complete_path, private_key))

答案 1 :(得分:1)

@Casper和@endemic是正确的,因为这是编码问题。

如果要坚持使用宝石,可以使用Base64.urlsafe_encode64JWT::Base64.url_encode

signature = JWT::Signature.sign('ES256', complete_path, private_key)
JWT::Base64.url_encode(signature)