
HMAC in Go, Python, Ruby, PHP, and Node.js - wilsonfiifi
http://blog.turret.io/hmac-in-go-python-ruby-php-and-nodejs/
======
tptacek
If some of these dev environments required you to implement HMAC yourself from
the SHA2 primitive, I'd see some of the value of a "Rosetta Code"-style page
for it. But all of these are just examples of calling into the environment's
library interface for HMAC. In fact, except for Golang, all of these examples
are essentially just calling into OpenSSL's HMAC.

Also:

* Do not use string/buffer comparison functions to verify HMAC. In incredibly common error.

* Do not use human-intelligible strings as HMAC keys. HMAC keys are like AES keys: fully random; they should come from /dev/urandom.

* Do not embed HMAC keys in your source code!

Ultimately: I'm not sure I understand the impulse behind pages like this. It's
clear that the authors aren't domain experts (that's fine; they're probably
better programmers than the crypto domain experts are). They know they aren't
getting everything perfect. In fact: _they know some of the examples on their
own page have flaws_ , because they were corrected about timing attacks and
only fixed Python.

Crypto bugs in your own code are one thing, but propagating crypto bugs to
other people's code seems much worse.

~~~
tlb
> HMAC keys are like AES keys: fully random; they should come from
> /dev/urandom.

I've been using pwgen -s: based on /dev/urandom, but typeable. My
understanding was that it first took a hash of the key, so as long as the
total entropy was high it was fine for it to be ASCII.

~~~
tptacek
Sure. ASCII isn't the problem; structure is. You already know the attack: take
a sample MAC (built with a very, very fast MAC function) and aim a permutating
dictionary at it.

------
voidlogic
Gah, Go pet peave, they could just use a map literal (good for short low-perf
code).

Or even better perf/safety wise:

    
    
      type Payload struct {
        Name string `json:"name"`
        Category string `json:"category"`
        Action string `json:"action"`
        Where string `json:"where"`
        Timestamp int64 `json:"timestamp,string"`
      }
      payload := Payload{
        Name: "joe smith",
        Category: "people",
        Action: "transport"
        Where: "pluto",
        Timestamp: time.Now().Unix(),
      }
      jsonBytes, err := json.Marshal(&payload)
    

This code doesn't allocate heap for payload, is much faster and typesafe...

P.S. And could be shorter, but I was trying to be clear.

------
thenrich99
Original author here -- thanks to everyone for the feedback. Some time has
passed since this was originally written and the remaining languages were
never updated to improve the safety of the signature verifications.

The original reasoning behind this post was to provide a single reference for
signature generation and verification in some common languages -- something I
struggled to locate myself. Admittedly, I should've provided warnings about
using simple and hardcoded keys in the examples, which were done that way for
readability.

While there is still a lot of debate about the ability to perform true
constant-time comparisons in many of these languages
([https://bugs.python.org/issue15061](https://bugs.python.org/issue15061),
[https://github.com/joyent/node/issues/8560](https://github.com/joyent/node/issues/8560))
I agree that for those who would be otherwise using the unsafe string
comparisons, the benefits certainly outweigh the slightly added complexity.

The updated gists are available in the post to anyone with comments or
improvements.

Cheers!

------
fdomig
There might be a chance of timing attacks against such "security". A secure
system should never depend on obscurity.

~~~
sarciszewski
Node.js example:

    
    
        return new Buffer(sig).toString('base64') == signature;
    

PHP example:

    
    
        return hash_hmac("sha512", $string_to_verify, $shared_secret) == $signature;
    

Yeah, like fdomig said: timing attacks. The Python example included a
mitigation. PHP includes hash_equals() and a constant time comparison in
Javascript isn't difficult to write.

Possibly also, the Ruby example:

    
    
        return OpenSSL::HMAC.digest('sha512', shared_secret, string_to_verify) == signature
    

(I don't write Ruby so I don't know if this is overloadable somewhere.)

~~~
beefhash
> (I don't write Ruby so I don't know if this is overloadable somewhere.)

Ruby allows overriding the == operator[1], but OpenSSL::HMAC.digest returns an
instance of String[2], rather than returning a special subclass of string or
some other kind of special HMAC-representing class overloading ==.

[1] [http://docs.ruby-
lang.org/en/2.2.0/syntax/methods_rdoc.html#...](http://docs.ruby-
lang.org/en/2.2.0/syntax/methods_rdoc.html#label-Method+Names)

[2] [http://ruby-
doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL...](http://ruby-
doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/HMAC.html#method-c-digest)

~~~
vidarh
To be pedantic, in Ruby, the fact that an object is of class String is _not_
sufficient evidence that a method has not been overloaded (they can be
overloaded via the objects eigenclass), though you're probably right.

~~~
Freaky
Even if it did (and it doesn't, I checked), you're probably still better off
doing it explicitly since it's easier to audit, less likely to differ across
implementations, and less error prone (e.g. swap the order of the comparison
and you're back to plain old String#==).

------
jakejake
Adding a nonce to the request and storing it is a good idea to add to prevent
replay attacks. Especially in the case of OAuth where some implementations
hash the query string but don't hash the request body - which could allow all
kinds of mischief without even cracking the secret key.

~~~
thenrich99
In this scenario a replay attack is limited to a 30s window during which the
timestamp is valid. Depending on the implementation, this may or may not
suffice, in which case an nonce would definitely be an improvement albeit with
the added complexity.

