Dart - Generate HMAC Signature

This tutorial has some examples of how to generate HMAC signature in Dart using various algorithms including MD5, SHA1, SHA224, SHA256, SHAA384, and SHA512.

HMAC (Hash-based Message Authentication Code) is a type of message authentication code that uses a hash function and a secrety key. It's usually used to check the authentity and the integrity of data. The hash function can be any cryptograhpic hash algorithm such as MD5 or SHA.

Computing HMAC Signature in Dart

If you are using Dart, the crypto package allows us to compute HMAC using popular algorithms. First, you need to provide the data and the key which should be a shared key, both as a List<int>

The next thing is creating an Hmac instance by calling the constructor. The instance needs to use a certain hash algoithm and a secret ey.

  Hmac(Hash hash, List<int> key)

Parameters:

  • Hash hash: function for computing the authentication digest
  • List<int> key: a shared secret key between the sender and the receiver

After that, use convert(bytes) to get the result with the data as the argument. The below example uses MD5 algorithm.

  var hmacMd5 = new Hmac(md5, key);

  Digest md5Result = hmacMd5.convert(bytes);

If you need to get the result in bytes, you can use the bytes property.

  md5Result.bytes

Here is the full code which uses various algorithms.

  var key = utf8.encode('password1234');
  var bytes = utf8.encode('woolhadotcom');
  import 'package:crypto/crypto.dart';
  import 'dart:convert';
  
  void main() {
    var key = utf8.encode('password1234');
    var bytes = utf8.encode('woolhadotcom');
  
    var hmacMd5 = new Hmac(md5, key);
    var hmacSha1 = new Hmac(sha1, key);
    var hmacSha224 = new Hmac(sha224, key);
    var hmacSha256 = new Hmac(sha256, key);
    var hmacSha384 = new Hmac(sha384, key);
    var hmacSha512 = new Hmac(sha512, key);
  
    Digest md5Result = hmacMd5.convert(bytes);
    Digest sha1Result = hmacSha1.convert(bytes);
    Digest sha224Result = hmacSha224.convert(bytes);
    Digest sha256Result = hmacSha256.convert(bytes);
    Digest sha384Result = hmacSha384.convert(bytes);
    Digest sha512Result = hmacSha512.convert(bytes);
  
    print('MD5: $md5Result');
    print('SHA1: $sha1Result');
    print('SHA224: $sha224Result');
    print('SHA256: $sha256Result');
    print('SHA384: $sha384Result');
    print('SHA512: $sha512Result');
  }
  

Output:

  MD5: 1348c546812d44e38b33982279e60465
  SHA1: 2464748357a84bd6f4fbc8d526458e48cce86ce8
  SHA224: a746f423301983f9cda1a4872033af84a75a9091c0fe8220187fa34e
  SHA256: 43488491ac66530590aa89978525a1c0794698c902c961d8e5b8eee41237a0ec
  SHA384: cc32a6d871c8d01dcf944d5ea04a3c5a26a79404337098868e8d7d02780f46f28f0423c243f61d5924b1500503eb1ad5
  SHA512: ea61d6cdaa165165788959df6903c1e26692ad2eab256bf04c9da282a4b6272800992ea2f09eba76853330f098e7956001b455d9f5be338c29caa49a5e72ddb8

Chunked Conversion

If the data is in multiple chunks, you may consider to use chunked conversion. Each Hmac has startChunkedConversion method. It takes an argument of type Sink<Digest>

  var output = new AccumulatorSink();

  var hmacSha512 = new Hmac(sha512, key);

  ByteConversionSink input = hmacSha512.startChunkedConversion(output);

Then, add each chunk to input using input.add(bytes);. After all chunks has been added, use input.close(); to close the sink. Output in hexadecimal string can be obtained using output.events.single. The output should be the same as the one using convert().

You can see the full example below.

  import 'package:crypto/crypto.dart';
  import 'package:convert/convert.dart';
  import 'dart:convert';

  void main() {
    List<int> bytesChunks = [
      utf8.encode('woolha'),
      utf8.encode('dot'),
      utf8.encode('com')
    ];
  
    var key = utf8.encode('password1234');
    var output = new AccumulatorSink();
  
    var hmacSha512 = new Hmac(sha512, key);
  
    ByteConversionSink input = hmacSha512.startChunkedConversion(output);
    bytesChunks.forEach((List bytes) { input.add(bytes); });
    input.close();
  
    Digest result = output.events.single;
  
    print('Result: $result');
  }

Output:

  Result: ea61d6cdaa165165788959df6903c1e26692ad2eab256bf04c9da282a4b6272800992ea2f09eba76853330f098e7956001b455d9f5be338c29caa49a5e72ddb8