2012-03-16 13 views
10

Tôi có một máy chủ tomcat chạy một số mã Java cho phép người dùng xác thực bằng cách sử dụng khóa API. Yêu cầu sử dụng HMAC được tạo bằng SHA256. Tôi có một máy khách Ruby mà tôi đang sử dụng để thực hiện yêu cầu và vì tôi mới sử dụng mã hóa Tôi đang gặp khó khăn trong việc tạo ra một HMAC phù hợp. Tôi đã cố gắng không làm cho URL đó an toàn và phù hợp. Vì vậy, tôi thực sự tự hỏi là làm thế nào tôi có thể có được khách hàng Ruby để phù hợp với phiên bản an toàn URL (kể từ khi tôi không thể thay đổi mã Java). Nó chỉ có thêm một ký tự = ở cuối. Cảm ơn trước sự giúp đỡ nào.Làm thế nào để có được Ruby tạo HMAC cho SHA256 đó là url an toàn để phù hợp với Java?

Đối với Ruby tôi đang sử dụng 1.9.3 và cho Java tôi đang sử dụng 6u31 cùng với thư viện commons-codec-1.6.jar từ 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); 
    } 
} 

Output

Ruby:

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

Java:

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

Trả lời

6

Ruby không loại bỏ các dấu '=' - nó không phải là một yêu cầu tuyệt đối, như bạn có thể đọc trong RFC 4648 nó chỉ nói rằng tháo gỡ chúng chỉ có thể được mong muốn trong ứng dụng nhất định . Nhưng ngoài ra nó được đảm bảo rằng mã hóa an toàn URL của Ruby sẽ giống hệt với mã hóa của Java.

Vì vậy, điều duy nhất để bạn có thể làm là lột các dấu '==', bạn có thể ví dụ sử dụng một regex:

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

Đó chính xác là những gì tôi cần. Tham chiếu đến RFC 4648 rất hữu ích và kỹ lưỡng. Tôi không biết dấu '=' là tùy chọn. Tôi đã thêm rằng mã regex và nó hoạt động. Cảm ơn bạn. – mvalley

Các vấn đề liên quan