I'm using Flutter_Sodium version 0.2.0 and tried to generate an Argon2id13 password hash using the sensitive parameter set.
My system parameter were:
Flutter 2.2.1
Dart 2.13.1
Sodium version: 1.0.18
Android 11: sdk_gphone_x86_arm-userdebug 11 RSR1.201013.001 6903271 dev-keys
This is the code I used to generate the hash (the full code follows at the end):
printC('Generate a 32 byte long encryption key with Argon2id in sensitive mode');
printC('Sodium version: ' + Sodium.versionString);
printC('Dart version: ' + Platform.version);
final passphrase = 'secret passphrase';
printC('passphrase: ' + passphrase);
var salt16Byte = generateSalt16Byte();
printC('salt (Base64): ' + base64Encoding(salt16Byte));
final outlen = 32;
final passwd = utf8.encoder.convert(passphrase);
final opslimit = Sodium.cryptoPwhashOpslimitSensitive;
final memlimit = Sodium.cryptoPwhashMemlimitSensitive;
final alg = Sodium.cryptoPwhashAlgArgon2id13;
printC('opsLimit: ' + Sodium.cryptoPwhashOpslimitSensitive.toString());
printC('memLimit: ' + Sodium.cryptoPwhashMemlimitSensitive.toString());
final hash =
Sodium.cryptoPwhash(outlen, passwd, salt16Byte, opslimit, memlimit, alg);
printC('hash (Base64): ' + base64Encoding(hash));
I'm using the constants Sodium.cryptoPwhashOpslimitSensitive and Sodium.cryptoPwhashMemlimitSensitive for opsLimit and memLimit.
The code fails with an Exception caught by gesture: SodiumException crypto_pwhash failed with -1 (full stack see below:):
I/flutter ( 9661): Generate a 32 byte long encryption key with Argon2id in sensitive mode
I/flutter ( 9661): Sodium version: 1.0.18
I/flutter ( 9661): Dart version: 2.13.1 (stable) (Fri May 21 12:45:36 2021 +0200) on "android_ia32"
I/flutter ( 9661): passphrase: secret passphrase
I/flutter ( 9661): salt (Base64): tVcZQuWbpNxGrvJ45H5Q8Q==
I/flutter ( 9661): opsLimit: 4
I/flutter ( 9661): memLimit: 1073741824
======== Exception caught by gesture ===============================================================
The following SodiumException object was thrown while handling a gesture:
crypto_pwhash failed with -1
When the exception was thrown, this was the stack:
#0 Result.mustSucceed (package:flutter_sodium/src/extensions.dart:48:7)
#1 Sodium.cryptoPwhash (package:flutter_sodium/src/sodium.dart:1087:12)
#2 _MyWidgetState.runYourMainDartCode (package:dartprojectspointycastle/CrossPlatformCryptography/LibsodiumArgon2idSensitiveIssue.dart:136:12)
#3 _MyWidgetState.build.<anonymous closure> (package:dartprojectspointycastle/CrossPlatformCryptography/LibsodiumArgon2idSensitiveIssue.dart:82:21)
#4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#87d41
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(300.3, 727.6)
finalLocalPosition: Offset(35.2, 10.3)
button: 1
sent tap down
====================================================================================================
full code (it's a simple console app, just press "run the code"):
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Console'),
),
body: MyWidget(),
),
);
}
}
// widget class
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// state variable
String _textString = 'press the button "run the code"';
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
'console output',
style: TextStyle(fontSize: 30),
),
Expanded(
flex: 1,
child: new SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Padding(
padding: EdgeInsets.fromLTRB(10, 5, 10, 5),
child: Text(_textString,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: 'Courier',
color: Colors.black,
))),
),
),
Container(
child: Row(
children: <Widget>[
SizedBox(width: 10),
Expanded(
child: ElevatedButton(
child: Text('clear console'),
onPressed: () {
clearConsole();
},
),
),
SizedBox(width: 10),
Expanded(
child: ElevatedButton(
child: Text('extra Button'),
onPressed: () {
runYourSecondDartCode();
},
),
),
SizedBox(width: 10),
Expanded(
child: ElevatedButton(
child: Text('run the code'),
onPressed: () {
runYourMainDartCode();
},
),
),
SizedBox(width: 10),
],
),
),
],
);
}
void clearConsole() {
setState(() {
_textString = ''; // will add additional lines
});
}
void printC(_newString) {
setState(() {
_textString =
_textString + _newString + '\n';
});
print(_newString); // extra output on Console
}
/* ### instructions ###
place your code inside runYourMainDartCode and print it to the console
using printC('your output to the console');
clearConsole() clears the actual console
place your code that needs to be executed additionally inside
runYourSecondDartCode and start it with "extra Button"
*/
void runYourMainDartCode() {
clearConsole();
printC('Generate a 32 byte long encryption key with Argon2id in sensitive mode');
printC('Sodium version: ' + Sodium.versionString);
printC('Dart version: ' + Platform.version);
final passphrase = 'secret passphrase';
printC('passphrase: ' + passphrase);
var salt16Byte = generateSalt16Byte();
printC('salt (Base64): ' + base64Encoding(salt16Byte));
final outlen = 32;
final passwd = utf8.encoder.convert(passphrase);
final opslimit = Sodium.cryptoPwhashOpslimitSensitive;
final memlimit = Sodium.cryptoPwhashMemlimitSensitive;
final alg = Sodium.cryptoPwhashAlgArgon2id13;
printC('opsLimit: ' + Sodium.cryptoPwhashOpslimitSensitive.toString());
printC('memLimit: ' + Sodium.cryptoPwhashMemlimitSensitive.toString());
final hash =
Sodium.cryptoPwhash(outlen, passwd, salt16Byte, opslimit, memlimit, alg);
printC('hash (Base64): ' + base64Encoding(hash));
}
Uint8List generateSalt16Byte() {
return Sodium.randombytesBuf(16);
}
String base64Encoding(Uint8List input) {
return base64.encode(input);
}
void runYourSecondDartCode() {
printC('execute additional code');
}
}