Base64 HMAC-SHA1 and MD5 encryption in Dart and Vuforia's VWS API

312 views
Skip to first unread message

Cristian Garcia

unread,
Jan 20, 2015, 10:24:38 PM1/20/15
to cl...@dartlang.org
To communicate with Vuforia through its VWS API I have to do some tricky stuff: first create this string

    StringToSign = 
      HTTP-Verb + "\n" +
      Content-MD5 + "\n" +
      Content-Type + "\n" +
      Date + "\n" +
      Request-Path;

where `Content-MD5` is the encryption of the request's body...

> (from the first boundary to the last one, including the boundary
> itself). For request types without request body, include the MD5 hash
> of an empty string which is “d41d8cd98f00b204e9800998ecf8427e”.

then with this string you have to perform the equivalent to this Java code

    Signature = Base64 (HMAC-SHA1 (server_secret_key, StringToSign));

where `server_secret_key` is a constant. Finally you have to plug that into an authorization header of this form

`Authorization: VWS {provision_access_key}:{Signature}`

I've got no experience with encryption, can anybody tell me how to do this in Dart?

Søren Gjesse

unread,
Jan 21, 2015, 3:08:29 AM1/21/15
to Cristian Garcia, cl...@dartlang.org
Answer on stackowerflow:

All the algorithms you need for this are in the dart crypto package.

import 'dart:io';

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

main() {
  var content = [65, 66, 67];
  var md5 = new crypto.MD5();
  md5.add(content);

  var verb = 'GET';
  var hash = crypto.CryptoUtils.bytesToHex(md5.close());
  var type = 'text/plain';
  var date = HttpDate.format(new DateTime.now());
  var path = '/request/path';
  var stringToSign = '$verb\n$hash\n$type\n$date\n$path';
  print(stringToSign);
  print('');

  var key = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  var hmac = new crypto.HMAC(new crypto.SHA1(), key);
  hmac.add(content);
  print(crypto.CryptoUtils.bytesToHex(hmac.close()));
}

Of cause you need to figure out the exact encoding of the different parts, e.g. the date. If just one bit is wrong in the input nothing works.

If you have some examples of input and output it is much easier to get the details right. E.g. test the MD5 of the empty string

print(crypto.CryptoUtils.bytesToHex(new crypto.MD5().close()));

Regards,
Søren Gjesse

---
Søren Gjesse
Software Engineer, Google Denmark
CVR nr. 28 86 69 84


--
You received this message because you are subscribed to the Google Groups "Dart Server-side and Cloud Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cloud+un...@dartlang.org.
Visit this group at http://groups.google.com/a/dartlang.org/group/cloud/.

Cristian Garcia

unread,
Jan 22, 2015, 4:24:14 PM1/22/15
to Søren Gjesse, cl...@dartlang.org
Thanks Soren! I still have a few doubts:

1) What function can convert my 
String jsonBody to yourList<int> content?
2) My 
server_secret_key is something like "a26b48...", not a List<int> like your key variable.
3) You are adding 
content to your hmac, but I am guessing that your intention was to add a List<int> representation of stringToSign, judging by the sample Java code.

Look at link on the Edit section of the SO post for more info.


ARISTA DEV
Cristian Garcia Escobar
Cofundador

Teléfono: (57 4) 584 31 79 | Móvil: (57) 314 862 79 78
Medellín - Colombia

Anders Holmgren

unread,
Jan 22, 2015, 4:56:09 PM1/22/15
to Cristian Garcia, Søren Gjesse, cl...@dartlang.org
String has a getter called something like charCodes that is the List<int> you are after

Cristian Garcia

unread,
Jan 22, 2015, 5:14:49 PM1/22/15
to Anders Holmgren, Søren Gjesse, cl...@dartlang.org
Hi Anders,

I've checked and the getter is called "codeUnits" and it 

Returns an unmodifiable list of the UTF-16 code units of this string.

Do the functions Soren uses work this that encoding? 

ARISTA DEV
Cristian Garcia Escobar
Cofundador

Teléfono: (57 4) 584 31 79 | Móvil: (57) 314 862 79 78
Medellín - Colombia

Anders Holmgren

unread,
Jan 22, 2015, 5:21:33 PM1/22/15
to Cristian Garcia, Søren Gjesse, cl...@dartlang.org
Yes I believe so. I used that in dart-jwt

Søren Gjesse

unread,
Jan 23, 2015, 2:51:02 AM1/23/15
to Cristian Garcia, cl...@dartlang.org
Cristian,

Answers inline. I updated the SO answer with these fixes as well.

On Thu, Jan 22, 2015 at 10:24 PM, Cristian Garcia <cgarc...@gmail.com> wrote:
Thanks Soren! I still have a few doubts:

1) What function can convert my 
String jsonBody to yourList<int> content?

This is all about choosing the correct encoding. In my sample the content is [65, 66, 67] which is the string 'ABC' in UTF-8 encoding. All crypto works with bytes, so you always have to agree on the encoding. In this case I assume that the encoding is the same as is used for the HTTP request body, which most likely will be UTF-8, that is content type application/json which should imply UTF-8.
 
2) My server_secret_key is something like "a26b48...", not a List<int> like your key variable.

This is the hexadecimal representation of the key with two hex digits for each byte

var keyStr = "a26b48..."
var key = [];
var key = [];
for (int i = 0; i < keyStr.length; i += 2) {
  key.add(int.parse(keyStr.substring(i, i + 2), radix: 16));
}
 

3) You are adding 
content to your hmac, but I am guessing that your intention was to add a List<int> representation of stringToSign, judging by the sample Java code.

Yes - good catch - this should be the UTF-8 encoded version of stringToSign
Reply all
Reply to author
Forward
0 new messages