2012-03-16 5 views
10

Ho un server tomcat che esegue un codice Java che consente agli utenti di autenticarsi utilizzando una chiave API. La richiesta utilizza un HMAC creato con SHA256. Ho un client Ruby che sto usando per fare la richiesta e dal momento che sono nuovo alla crittografia, sto avendo difficoltà a fargli generare un HMAC corrispondente. Ho provato a non renderlo URL sicuro, e che corrisponde. Quindi mi chiedo davvero come posso far sì che il client di Ruby corrisponda alla versione sicura per l'URL (dato che non posso modificare il codice Java). Alla fine ha un carattere extra =. Grazie in anticipo per qualsiasi aiuto.Come ottenere Ruby generato HMAC per SHA256 che è sicuro da url per abbinare Java?

Per Ruby sto usando 1.9.3 e per Java sto usando 6u31 insieme alla libreria commons-codec-1.6.jar da apache.

Codice

Rubino:

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); 
    } 
} 

uscita

Rubino:

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

Java:

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

risposta

6

Ruby non rimuovere il trailing '=' - non è un requisito assoluto, come si può leggere in RFC 4648 si afferma solo che la loro rimozione potrebbe essere desiderabile in certe applicazioni . Ma a parte questo è garantito che la codifica URL-safe di Ruby sarà esattamente la stessa di Java.

Quindi l'unica cosa da fare per voi è spogliano il trailing '==', si potrebbe ad esempio utilizzare un'espressione regolare:

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

Questo è esattamente quello che mi serviva. Il riferimento a RFC 4648 è stato molto utile e approfondito. Non sapevo che il trailing '=' fosse opzionale. Ho aggiunto il codice regex e funziona. Grazie. – mvalley