2
votes

Hi, I would like to have an example of AES encryption and decryption with Dart. I saw in Dart there are a library cipher

https://www.dartdocs.org/documentation/cipher/0.3.0/cipher.api/cipher.api-library.html

that can help to do that. But I have 2 problems here :

  • An simple example of encrypting a string, and decrypt it to get the initial string.

  • I need it to work with other AES library, assuming that they all follow the standard. In particular I have my frontend in Dart and backend in C++ which I plan to use crypto++ for that purpose. The point is in crypto++, the required input are the key and the Initialization Vector (IV), while in Dart/cipher, it doesn't seem to require the IV. I wonder if the input requirement are different, they couldn't work together.

Conclusion, if someone can help with an example of using Dart with any library (cipher/crypto) that can encrypt/decrypt a string with 2 inputs Key and IV, that will amazingly help me.

Thank you all

3
The Dart Cipher docs are a POS, they provide essentially no information thus interoperability is going to be difficult. From the docs: "most of the classes are ports of Bouncy Castle from Java to Dart" so you will have to go to the Bouncy Castle docs and try and figure out how they apply to Dart. Best case: do not use. - zaph

3 Answers

3
votes

I'm not going to supply a complete sample code, but if you want to use Dart crypto, you should be going with counter mode (CTR) encryption, simply because that seems to be the only actual AES cipher mode implemented by Dart.

CTR is also called SIC mode and the implementation can be found here. It helpfully uses a ParametersWithIV. If you would use a non-randomized nonce you should place it at the high order (leftmost, starting with byte index 0, as CTR mode is usually big endian) end of the IV.

2
votes

I finally get my encryption decryption example work, so I answer to my question. The easiest way is to use Salsa20 algorithm, then transform everything to hex string before serialize and send it.

  • encrypt data
  • encode IV to hex String
  • encode encrypted data to hex String
  • serialize all and send through the network
  • the other end of the network decode the hex string to get the IV and the encrypted data.
  • then use the same IV, same key (implicitly set to be the same) to decrypt the data

Below is the code encrypt/decrypt without sending through the network.

import "dart:typed_data";
import 'dart:convert';
import "package:cipher/cipher.dart";
import "package:cipher/impl/base.dart";

Uint8List StringToUint8List( String s ) {
  var ret = new Uint8List(s.length);
  for( var i=0 ; i<s.length ; i++ ) {
    ret[i] = s.codeUnitAt(i);
  }
  return ret;
}

/// UTF16 Decoding
String Uint8ListToString( Uint8List ui ) {
  String s = new String.fromCharCodes(ui);
  return s;
}

void main() {
    initCipher();
    final testStr = "Hello, i am a very very very very very very very very long string, please encrypte me";
    final ivStr  = "2urPAr4H"; // Need to have size 8
    final keyStr = "QuJuesMhcssE4e8Q4Kt1XCJW3tcpzcEI"; // Need to have size 32

    final _ivEncoded = UTF8.encode(ivStr);
    final _keyEncoded = UTF8.encode(keyStr);
    final _key = new KeyParameter(_keyEncoded);
    final params = new ParametersWithIV(_key,_ivEncoded);

    var cipher = new StreamCipher( "Salsa20" );
    cipher..reset()..init( true, params );
    var encryptedEncodedData = cipher.process( StringToUint8List(testStr) );
     var encryptedDataStr = Uint8ListToString(encryptedEncodedData);

    cipher..reset()..init( false, params );
    var dencryptedEncodedData = cipher.process( StringToUint8List(encryptedDataStr) );
    var dencryptedDataStr = Uint8ListToString(dencryptedEncodedData);
    //expect(testStr, dencryptedDataStr);
}
0
votes

For anyone coming here now, I wrote a custom package based off PointyCastle and written entirely in Dart which can greatly simplify AES for you.

https://pub.dev/packages/steel_crypt

It looks something like this implemented:

var FortunaKey = CryptKey().genFortuna(); //generate 32 byte key with Fortuna //you can also enter your own
var iv = CryptKey().genDart(16); //generate iv for AES with Dart Random.secure() //you can also enter your own
var aesEncrypter = AesCrypt(FortunaKey, 'cbc', 'pkcs7'); //generate AES CBC block encrypter with key and PKCS7 padding
String encrypted = aesEncrypter.encrypt('somedatahere', iv); //encrypt
String decrypted = aesEncrypter.decrypt(encrypted, iv); //decrypt

This solves any issues with inputs that may have occurred earlier.