Подтвердить что ты не робот

Как получить Ruby, созданный HMAC для SHA256, который безопасен для соответствия Java?

У меня есть сервер tomcat, на котором запущен некоторый Java-код, который позволяет пользователям аутентифицироваться с помощью ключа API. Запрос использует HMAC, созданный с SHA256. У меня есть клиент Ruby, который я использую, чтобы сделать запрос, и поскольку я новичок в шифровании, мне сложно с этим справиться, чтобы создать соответствующий HMAC. Я попытался не сделать его URL безопасным, и это соответствует. Поэтому мне действительно интересно, как я могу заставить клиента Ruby соответствовать безопасной версии URL (так как я не могу изменить код Java). Он просто получил дополнительный символ в конце. Заранее благодарим за любую помощь.

Для Ruby я использую 1.9.3, а для Java я использую 6u31 вместе с библиотекой commons-codec-1.6.jar от apache.

код

Ruby:

require "openssl"
require "base64"

json_str = "{'community':'LG7B734A', 'login_id':'user1', 'time':'1331928899'}"
digest = OpenSSL::Digest::Digest.new("sha256")
key = [ "4cc45e4258121c3fec84147673e1bd88e51b1c177aafcfa2da72bd4655c9f933" ]
hmac = OpenSSL::HMAC.digest(digest, key.pack("H*"), json_str)

encoded_url_safe = Base64.urlsafe_encode64(hmac)
encoded = Base64.encode64(hmac)

puts("Encoded (Url Safe): " + encoded_url_safe)
puts("Encoded           : " + encoded)

Java:

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Mac;

public class ExampleHMAC
{
    public static void main(String[] args) throws Exception
    {
        String key = "4cc45e4258121c3fec84147673e1bd88e51b1c177aafcfa2da72bd4655c9f933";
        byte[] keyBytes = Hex.decodeHex(key.toCharArray());

        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(keySpec);

        String jsonStr = "{'community':'LG7B734A', 'login_id':'user1', 'time':'1331928899'}";
        byte[] hmacBytes = mac.doFinal(jsonStr.getBytes());

        String encodedUrlSafe = Base64.encodeBase64URLSafeString(hmacBytes);
        String encoded = Base64.encodeBase64String(hmacBytes);

        System.out.println("Encoded (Url Safe): " + encodedUrlSafe);
        System.out.println("Encoded           : " + encoded);
    }
}

Выход

Ruby:

Encoded (Url Safe): QgYLqGm1M4qozdEjGC_CnJ8CdBm2jQpsU85kSWFcjKM=
Encoded           : QgYLqGm1M4qozdEjGC/CnJ8CdBm2jQpsU85kSWFcjKM=

Java:

Encoded (Url Safe): QgYLqGm1M4qozdEjGC_CnJ8CdBm2jQpsU85kSWFcjKM
Encoded           : QgYLqGm1M4qozdEjGC/CnJ8CdBm2jQpsU85kSWFcjKM=
4b9b3361

Ответ 1

Ruby не удаляет конечный '=' - это не абсолютное требование, как вы можете прочитать в RFC 4648, он просто утверждает, что удаление их может быть желательно в некоторых приложениях. Но кроме этого гарантируется, что Ruby URL-безопасное кодирование будет точно таким же, как Java.

Итак, единственное, что вам нужно сделать, это снять с конца "==", вы могли бы, например, использовать регулярное выражение:

encoded_url_safe_.gsub!(/=+$/, "")