diff --git a/.idea/dictionaries/herbert.xml b/.idea/dictionaries/herbert.xml
index c942ae1..eeea0d7 100644
--- a/.idea/dictionaries/herbert.xml
+++ b/.idea/dictionaries/herbert.xml
@@ -7,6 +7,7 @@
hmac
kdbx
keepass
+ uint
\ No newline at end of file
diff --git a/bin/kdbx.dart b/bin/kdbx.dart
index 45a3277..8df3366 100644
--- a/bin/kdbx.dart
+++ b/bin/kdbx.dart
@@ -94,7 +94,7 @@ abstract class KdbxFileCommand extends Command {
final keyFileData =
keyFile == null ? null : await File(keyFile).readAsBytes();
- Argon2FfiFlutter.resolveLibraryForceDynamic = true;
+ Argon2.resolveLibraryForceDynamic = true;
final file = await KdbxFormat(Argon2FfiFlutter()).read(
bytes,
Credentials.composite(ProtectedValue.fromString(password), keyFileData),
diff --git a/lib/src/internal/byte_utils.dart b/lib/src/internal/byte_utils.dart
index 5ae1966..2517872 100644
--- a/lib/src/internal/byte_utils.dart
+++ b/lib/src/internal/byte_utils.dart
@@ -3,6 +3,14 @@ import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
+import 'package:kdbx/kdbx.dart';
+
+/// A bitmask that limits an integer to 32 bits.
+const mask32 = 0xFFFFFFFF;
+
+/// The number of bytes in a 32-bit word.
+const bytesPerWord = 4;
+
class ByteUtils {
static final _random = Random.secure();
@@ -27,8 +35,13 @@ class ByteUtils {
list?.map((val) => toHex(val))?.join(' ') ?? '(null)';
}
+const dartWebWorkaround = true;
+
class ReaderHelper {
- ReaderHelper(this.byteData) : lengthInBytes = byteData.lengthInBytes;
+ factory ReaderHelper(Uint8List byteData) => KdbxFormat.dartWebWorkaround
+ ? ReaderHelper(byteData)
+ : ReaderHelper._(byteData);
+ ReaderHelper._(this.byteData) : lengthInBytes = byteData.lengthInBytes;
final Uint8List byteData;
int pos = 0;
@@ -72,10 +85,24 @@ class ReaderHelper {
int readUint8() => _nextByteBuffer(1).getUint8(0);
int readUint16() => _nextByteBuffer(2).getUint16(0, Endian.little);
int readUint32() => _nextByteBuffer(4).getUint32(0, Endian.little);
- int readUint64() => _nextByteBuffer(8).getUint64(0, Endian.little);
+ int readUint64() {
+ if (!dartWebWorkaround) {
+ return _nextByteBuffer(8).getUint64(0, Endian.little);
+ } else {
+ final lo = readUint32();
+ final hi = readUint32();
+ return hi << 32 + lo;
+ }
+ }
int readInt32() => _nextByteBuffer(4).getInt32(0, Endian.little);
- int readInt64() => _nextByteBuffer(8).getInt64(0, Endian.little);
+ int readInt64() {
+ if (!dartWebWorkaround) {
+ return _nextByteBuffer(8).getInt64(0, Endian.little);
+ } else {
+ return readUint64();
+ }
+ }
Uint8List readBytes(int size) => _nextBytes(size);
@@ -90,10 +117,17 @@ class ReaderHelper {
static int singleUint64(Uint8List bytes) => ReaderHelper(bytes).readUint64();
}
+class ReaderHelperDartWeb extends ReaderHelper {
+ ReaderHelperDartWeb(Uint8List byteData) : super._(byteData);
+}
+
typedef LengthWriter = void Function(int length);
class WriterHelper {
- WriterHelper([BytesBuilder output]) : output = output ?? BytesBuilder();
+ factory WriterHelper([BytesBuilder output]) => KdbxFormat.dartWebWorkaround
+ ? WriterHelperDartWeb(output)
+ : WriterHelper._(output);
+ WriterHelper._([BytesBuilder output]) : output = output ?? BytesBuilder();
final BytesBuilder output;
@@ -148,3 +182,30 @@ class WriterHelper {
return bytes.length;
}
}
+
+class WriterHelperDartWeb extends WriterHelper {
+ WriterHelperDartWeb([BytesBuilder output]) : super._(output);
+
+ @override
+ void writeUint64(int value, [LengthWriter lengthWriter]) {
+ lengthWriter?.call(8);
+
+ final _endian = Endian.little;
+ final highBits = value >> 32;
+ final lowBits = value & mask32;
+ final byteData = ByteData(8);
+ if (_endian == Endian.big) {
+ byteData.setUint32(0, highBits, _endian);
+ byteData.setUint32(0 + bytesPerWord, lowBits, _endian);
+ } else {
+ byteData.setUint32(0, lowBits, _endian);
+ byteData.setUint32(0 + bytesPerWord, highBits, _endian);
+ }
+ _write(byteData);
+ }
+
+ @override
+ void writeInt64(int value, [LengthWriter lengthWriter]) {
+ writeUint64(value, lengthWriter);
+ }
+}
diff --git a/lib/src/kdbx_format.dart b/lib/src/kdbx_format.dart
index efa72b3..acac4e2 100644
--- a/lib/src/kdbx_format.dart
+++ b/lib/src/kdbx_format.dart
@@ -324,6 +324,7 @@ class KdbxFormat {
KdbxFormat([this.argon2]);
final Argon2 argon2;
+ static bool dartWebWorkaround = false;
KdbxFile create(
Credentials credentials,
diff --git a/pubspec.yaml b/pubspec.yaml
index 453fcf8..f3c6da2 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -29,7 +29,7 @@ dependencies:
args: '>1.5.0 <2.0.0'
prompts: '>=1.3.0 <2.0.0'
logging_appenders: '>=0.1.0 <1.0.0'
- argon2_ffi_base: '>=0.1.0 <1.0.0'
+ argon2_ffi_base: '>=0.1.4+2 <1.0.0'
dev_dependencies:
pedantic: '>=1.7.0 <2.0.0'
diff --git a/test/internal/test_utils.dart b/test/internal/test_utils.dart
index b097e75..08ccb1d 100644
--- a/test/internal/test_utils.dart
+++ b/test/internal/test_utils.dart
@@ -13,7 +13,7 @@ final _logger = Logger('test_utils');
class TestUtil {
static KdbxFormat kdbxFormat() {
- Argon2FfiFlutter.resolveLibraryForceDynamic = true;
+ Argon2.resolveLibraryForceDynamic = true;
return KdbxFormat(Argon2FfiFlutter(resolveLibrary: (path) {
final cwd = Directory('.').absolute.uri;
final p = cwd.resolve(path);