Search code examples
scalaamazon-web-servicesplayframeworkamazon-cloudsearch

SignatureDoesNotMatch Aws CloudSearch scala


I keep getting:

"#SignatureDoesNotMatch","error":{"message":"[Deprecated: Use the outer message field] The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

from trying to do a get request to cloudsearch. I verified that my Canonical String and String-to-Sign match the ones sent back from the error message everytime now, but I keep getting the error. Im assuming my signature itself isn't being processed correctly. But hard to nail it down.

  def getHash(key:Array[Byte]): String = {
    try
    {
      val md = MessageDigest.getInstance("SHA-256").digest(key)
      md.map("%02x".format(_)).mkString.toLowerCase()
    }
    catch
      {
        case e: Exception => ""
      }
  }

.

   def HmacSHA256(data:String, key:Array[Byte]): Array[Byte] =  {
    val algorithm="HmacSHA256";
    val mac = Mac.getInstance(algorithm);
    mac.init(new SecretKeySpec(key, algorithm));
    mac.doFinal(data.getBytes("UTF8"));
   }

.

...
val algorithm = "AWS4-HMAC-SHA256"
val credential_scope = date + "/us-west-1/cloudsearch/aws4_request"

val string_to_sign = algorithm + "\n" +  dateTime + "\n" +  credential_scope + "\n" +  getHash(canonical_request)


val kSecret = ("AWS4" + config.getString("cloud.secret")).getBytes("utf-8")
val kDate = HmacSHA256(date.toString, kSecret)
val kRegion = HmacSHA256("us-west-1",kDate)
val kService = HmacSHA256("cloudsearch",kRegion)
val kSigning = HmacSHA256("aws4_request",kService)
val signing_key = kSigning
val signature = getHash(HmacSHA256(string_to_sign, kSigning))

val authorization_header = algorithm + " " + "Credential=" + config.getString("cloud.key") + "/" + credential_scope + ", " +  "SignedHeaders=" + signed_headers + ", " + "Signature=" + signature

val complexHolder = holder.withHeaders(("x-amz-date",dateTime.toString))
.withHeaders(("Authorization",authorization_header))
.withRequestTimeout(5000)
.get()
val response = Await.result(complexHolder, 10 second)

Solution

  • I just released a helper library to sign your HTTP requests to AWS: https://github.com/ticofab/aws-request-signer . Hope it helps!