2014-11-22 33 views
11

Sto tentando di scrivere un client API di Amazon Product Advertising in Elixir. La guida per lo sviluppatore descrive the process for signing an API request in cui è necessario creare un hash HMAC-SHA26 utilizzando la richiesta e la "chiave di accesso segreta". Questa è la funzione che ho scritto per gestire la firma della richiesta:Come si genera una stringa HMAC in Elixir?

defp sign_request(url) do 
    url_parts = URI.parse(url) 
    request = "GET\n" <> url_parts.host <> "\n" <> url_parts.path <> "\n" <> url_parts.query 
    url <> "&Signature=" <> :crypto.hmac(:sha256, 'ThisIsMySecretAccessKey', request) 
end 

L'url passata nella funzione simile a questa: http://webservice.amazon.com/onca/xml?AssociateTag=ThisIsMyAssociateTag&AWSAccessKeyId=ThisIsMyAWSAccessKeyId&Keywords=stuff&Operation=ItemSearch&SearchIndex=Apparel&Service=AWSECommerceService&Timestamp=2014-11-22T12%3A00%3A00Z&Validate=True&Version=2013-08-01

Il problema che sto avendo è che, mentre :crypto.hmac/3 restituisce un binario, quel binario non è una stringa; passando il valore restituito a String.valid?/1 restituisce false. Pertanto, non riesco a concatenare il valore restituito alla fine della stringa dell'URL per firmare la richiesta.

Sto usando :crypto.hmac/3 in modo errato? C'è qualcosa che mi manca? C'è un modo alternativo che dovrei fare su questo?

+1

Si consiglia inoltre di considerare di usare stringa interpolazione in elisir. http://elixir-lang.org/getting_started/2.html#2.4-strings Può semplificare un po 'il tuo codice. –

risposta

24

Quando si utilizza :crypto.hmac/3 la sua base di ritorno 16 intero in formato binario, il tuo problema potrebbe essere risolto in questo modo:

:crypto.hmac(:sha256, "key", "The quick brown fox jumps over the lazy dog") 
|> Base.encode16 

Questo è partita esempio dalla https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Examples_of_HMAC_.28MD5.2C_SHA1.2C_SHA256.29

+5

O forse usa Base.encode16 (: crypto.hmac (: sha256, "chiave", "La rapida volpe marrone salta sul cane pigro") |> Base.encode16) – sasajuric

+0

Ho usato la soluzione che @sasajuric ha proposto nel suo commento perché è una linea in meno ed è più facile da leggere. –

+3

Questo non è lo stesso di quello che c'è nella risposta. La differenza è la stessa tra 'hmac_bytes |> Base.encode16' e' hmac_bytes |> Base.encode16 |> Base.encode16'. La codifica due volte sembra fuori luogo. – pkoch