Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.
This repository was archived by the owner on Jan 20, 2023. It is now read-only.

Argon2id in sensitive mode gives SodiumException crypto_pwhash failed with -1 #65

@java-crypto

Description

@java-crypto

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');
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions