Can't replicate simple hashing signature example from Amazon

Viewed 202

I'm trying to create the final step of this example in Flutter and I can't get it right for some reason: https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html

Using their Signing Key + String to sign they get this resulting signature: 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7

Using the exact same key / string to sign I end up with: fe52b221b5173b501c9863cec59554224072ca34c1c827ec5fb8a257f97637b1

Here is my code:

var testSigninKey =
'c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9';
var testStringToSign = 'AWS4-HMAC-SHA256' + '\n' +
      '20150830T123600Z'  + '\n' +
      '20150830/us-east-1/iam/aws4_request'  + '\n' +
      'f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59';    

var hmac1 = Hmac(sha256, utf8.encode(testSigninKey));
var digest1 = hmac1.convert(utf8.encode(testStringToSign));
print(digest1);
print(hex.encode(digestBytes.bytes));
//both print: fe52b221b5173b501c9863cec59554224072ca34c1c827ec5fb8a257f97637b1
2 Answers

The hmac1 calls expects you to use the signing key as is, not to use an encoded version of the hex string representation of it.

You should be able to properly construct the Hmac object with this:

var hmac1 = Hmac(sha256, hex.decode(testSigninKey));

Here is a complete example of my flutter code, referring to the s3 signature creation example: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html I know it's not perfect but it took me extremely long to figure it out. Maybe it helps someone.

import 'dart:convert';

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;

class AWS {

  var _algorithm = ["X-Amz-Algorithm", "AWS4-HMAC-SHA256"];
  final String _awsService = "s3";
  final String _aws4Request = "aws4_request";
  var _expires = ["X-Amz-Expires", "86400"];
  var _signedHeaders = ["X-Amz-SignedHeaders", "host"];

  var testbucket = "https://s3.amazonaws.com/examplebucket";
  var testfilePath = "/test.txt";
  var _testDate = ["X-Amz-Date", "20130524T000000Z"];
  var _testDateymd = 20130524;
  var _testRegion = "us-east-1";
  var _testCredential = [
    "X-Amz-Credential",
    "AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request"
  ];
  var testSecretkey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";

  testString() {
    var httpMethod = "GET";
    var canUri = testfilePath;
    var canQueryStr = Uri.encodeQueryComponent(_algorithm[0]) +
        "=" +
        Uri.encodeQueryComponent(_algorithm[1]) +
        "&" +
        Uri.encodeQueryComponent(_testCredential[0]) +
        "=" +
        Uri.encodeQueryComponent(_testCredential[1]) +
        "&" +
        Uri.encodeQueryComponent(_testDate[0]) +
        "=" +
        Uri.encodeQueryComponent(_testDate[1]) +
        "&" +
        Uri.encodeQueryComponent(_expires[0]) +
        "=" +
        Uri.encodeQueryComponent(_expires[1]) +
        "&" +
        Uri.encodeQueryComponent(_signedHeaders[0]) +
        "=" +
        Uri.encodeQueryComponent(_signedHeaders[1]);
// <CanonicalQueryString>\n
// <CanonicalHeaders>\n
// <SignedHeaders>\n
// <HashedPayload>
    var _canonicalRequest = httpMethod +
        "\n" +
        canUri +
        "\n" +
        canQueryStr +
        "\n" +
        "host:examplebucket.s3.amazonaws.com" +
        "\n" +
        "\n" +
        "host" +
        "\n" +
        "UNSIGNED-PAYLOAD";
    var bytes = utf8.encode(_canonicalRequest);

    var _stringToSign = "AWS4-HMAC-SHA256" +
        "\n" +
        "20130524T000000Z" +
        "\n" +
        "20130524/us-east-1/s3/aws4_request" +
        "\n" +
        sha256.convert(bytes).toString();
    print("String to sign: $_stringToSign");

//  HEX und HMAC signature

    List<int> _dateKey = utf8.encode("AWS4" + testSecretkey);
    List<int> _dateMsg = utf8.encode(_testDateymd.toString());
    Hmac dateHmac = Hmac(sha256, _dateKey);
    Digest dateDigest = dateHmac.convert(_dateMsg);

    String _dateRegionKey = dateDigest.toString();
    List<int> _dateRegionMsg = utf8.encode(_testRegion.toString());
    Hmac dateRegionHmac = Hmac(sha256, hex.decode(_dateRegionKey.toString()));
    Digest dateRegionDigest = dateRegionHmac.convert(_dateRegionMsg);

    String _dateRegionServiceKey = dateRegionDigest.toString();
    List<int> _dateRegionServiceMsg = utf8.encode(_awsService.toString());
    Hmac dateRegionServiceHmac =
        Hmac(sha256, hex.decode(_dateRegionServiceKey.toString()));
    Digest dateRegionServiceDigest =
        dateRegionServiceHmac.convert(_dateRegionServiceMsg);

    String _signingKey = dateRegionServiceDigest.toString();
    List<int> _signingKeyMsg = utf8.encode(_aws4Request.toString());
    Hmac _signingKeyHmac = Hmac(sha256, hex.decode(_signingKey.toString()));
    Digest _signingKeyDigest = _signingKeyHmac.convert(_signingKeyMsg);

    print("signing key: $_signingKeyDigest");

    var _signatureKey = _signingKeyDigest.toString();
    List<int> _signatureKeyMsg = utf8.encode(_stringToSign);
    Hmac _signatureHmac = Hmac(sha256, hex.decode(_signatureKey));
    var _signature = _signatureHmac.convert(_signatureKeyMsg);

    print("Signature: $_signature");
  }
}
Related