2

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?

Edit

More info about this on Setting Up the API

Cristian Garcia
  • 9,630
  • 6
  • 54
  • 75
  • 2
    It seems https://pub.dartlang.org/packages/cipher provides what you need but I have no idea how to use it (didn't use it myself yet) – Günter Zöchbauer Jan 21 '15 at 05:52
  • You can have a look at the code I had used in a recent project on [this answer](https://stackoverflow.com/a/63924363/5345736) – Kamran Bashir Sep 16 '20 at 16:31

1 Answers1

5

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

import 'dart:convert';
import 'dart:io';

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

main() {
  var contentStr = '{x:"y"}';
  var content = UTF8.encode(contentStr);
  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 keyStr = "0102030405060708090a0b0c0d0e0f";
  var key = [];
  for (int i = 0; i < keyStr.length; i += 2) {
    key.add(int.parse(keyStr.substring(i, i + 2), radix: 16));
  }
  var hmac = new crypto.HMAC(new crypto.SHA1(), key);
  hmac.add(UTF8.encode(stringToSign));
  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()));
sgjesse
  • 3,793
  • 14
  • 17
  • Thanks Soren! I still have a few doubts. 1) What function can convert my `String jsonBody` to your `List content`? 2) My `server_secret_key` is something like `a26b48...`, not a `List` like your `key` variable. 3) You are adding `content` to your `hmac`, but I am guessing that your intention was to add a `List` representation of `stringToSign`, judging by the sample Java code. Look at link on the Edit section of the post for more info, . – Cristian Garcia Jan 22 '15 at 00:31
  • Updated the code to do: 1) Encode the string body using UTF-8. 2) Decode the key from a hex-string into bytes. 3) Yes - good catch - fixed that to do UTF-8 encoding of `stringToSign`. When getting this to work having a set of "known good" input/output data makes it much easier to see when you got it right. – sgjesse Jan 23 '15 at 07:48