简体   繁体   中英

Signing HTTP Requests with Hmac SHA1

The authorization schema of my REST API includes a HTTP header like this:

"Authorization: MyAuth: JWT_VALUE:207112ade53c795df43ce38e5251b41ded1791aa"

JWT_VALUE is a standard Json Web Token that also contains the encrypted API key as a custom claim. The second part after the colon is a signature generated by the client like this:

<script src='lib/hmac-sha1.js' type='text/javascript'></script>

...

var token = ...
var signature = CryptoJS.HmacSHA1(token + httpMethod + requestUrl + requestBody), apiKey);
headers["Authorization"] = "MyAuth " + token + ":" + signature;

The problem is that I'm unable to generate the same signature on the server; here is my Scala code:

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import org.apache.commons.codec.binary.Base64

...

val data = token + request.method + request.uri + request.body.asInstanceOf[AnyContent].asJson.getOrElse("")
val secret = ... // extract api key from token and decrypt it with app secret key

val singed = sign(data, secret)

if (signed != request.signature) {
  // error
  ...
}

...

def sign(data: String, secret: String): String = {
  val mac = Mac.getInstance("HmacSHA1")
  mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA1"))
  Base64.encodeBase64String(mac.doFinal(data))
}

Here is an example of what I get in my debugging sessions:

Incoming request signed by the server =========> um/TemuwSzboWD1D4kLRnFD6Sxk=
Signature generated by the client =============> 1c0567113a6bcc9f3715b83182d62e11aff52cec

As you can see the signature generated by the server with javax.crypto.Mac is shorter than the one generated by the client with CryptoJs .

As stated by Pavel, the problem was I used an HEX representation on the client and a BASE64 representation on the server. To fix the problem I just modified the client like this:

<script src='lib/hmac-sha1.js' type='text/javascript'></script>
<script src='lib/enc-base64-min.js' type='text/javascript'></script>

...

var token = ...
var signature = CryptoJS.HmacSHA1(token + httpMethod + requestUrl + requestBody), apiKey).toString(CryptoJS.enc.Base64);
headers["Authorization"] = "MyAuth " + token + ":" + signature;

;

Many thanks to Pavel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM