Browse Source

workaround for supporting dart html/web.

coverage
Herbert Poul 4 years ago
parent
commit
f59b9a3511
  1. 1
      .idea/dictionaries/herbert.xml
  2. 2
      bin/kdbx.dart
  3. 69
      lib/src/internal/byte_utils.dart
  4. 1
      lib/src/kdbx_format.dart
  5. 2
      pubspec.yaml
  6. 2
      test/internal/test_utils.dart

1
.idea/dictionaries/herbert.xml

@ -7,6 +7,7 @@
<w>hmac</w> <w>hmac</w>
<w>kdbx</w> <w>kdbx</w>
<w>keepass</w> <w>keepass</w>
<w>uint</w>
</words> </words>
</dictionary> </dictionary>
</component> </component>

2
bin/kdbx.dart

@ -94,7 +94,7 @@ abstract class KdbxFileCommand extends Command<void> {
final keyFileData = final keyFileData =
keyFile == null ? null : await File(keyFile).readAsBytes(); keyFile == null ? null : await File(keyFile).readAsBytes();
Argon2FfiFlutter.resolveLibraryForceDynamic = true; Argon2.resolveLibraryForceDynamic = true;
final file = await KdbxFormat(Argon2FfiFlutter()).read( final file = await KdbxFormat(Argon2FfiFlutter()).read(
bytes, bytes,
Credentials.composite(ProtectedValue.fromString(password), keyFileData), Credentials.composite(ProtectedValue.fromString(password), keyFileData),

69
lib/src/internal/byte_utils.dart

@ -3,6 +3,14 @@ import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'dart:typed_data'; 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 { class ByteUtils {
static final _random = Random.secure(); static final _random = Random.secure();
@ -27,8 +35,13 @@ class ByteUtils {
list?.map((val) => toHex(val))?.join(' ') ?? '(null)'; list?.map((val) => toHex(val))?.join(' ') ?? '(null)';
} }
const dartWebWorkaround = true;
class ReaderHelper { 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; final Uint8List byteData;
int pos = 0; int pos = 0;
@ -72,10 +85,24 @@ class ReaderHelper {
int readUint8() => _nextByteBuffer(1).getUint8(0); int readUint8() => _nextByteBuffer(1).getUint8(0);
int readUint16() => _nextByteBuffer(2).getUint16(0, Endian.little); int readUint16() => _nextByteBuffer(2).getUint16(0, Endian.little);
int readUint32() => _nextByteBuffer(4).getUint32(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 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); Uint8List readBytes(int size) => _nextBytes(size);
@ -90,10 +117,17 @@ class ReaderHelper {
static int singleUint64(Uint8List bytes) => ReaderHelper(bytes).readUint64(); static int singleUint64(Uint8List bytes) => ReaderHelper(bytes).readUint64();
} }
class ReaderHelperDartWeb extends ReaderHelper {
ReaderHelperDartWeb(Uint8List byteData) : super._(byteData);
}
typedef LengthWriter = void Function(int length); typedef LengthWriter = void Function(int length);
class WriterHelper { 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; final BytesBuilder output;
@ -148,3 +182,30 @@ class WriterHelper {
return bytes.length; 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);
}
}

1
lib/src/kdbx_format.dart

@ -324,6 +324,7 @@ class KdbxFormat {
KdbxFormat([this.argon2]); KdbxFormat([this.argon2]);
final Argon2 argon2; final Argon2 argon2;
static bool dartWebWorkaround = false;
KdbxFile create( KdbxFile create(
Credentials credentials, Credentials credentials,

2
pubspec.yaml

@ -29,7 +29,7 @@ dependencies:
args: '>1.5.0 <2.0.0' args: '>1.5.0 <2.0.0'
prompts: '>=1.3.0 <2.0.0' prompts: '>=1.3.0 <2.0.0'
logging_appenders: '>=0.1.0 <1.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: dev_dependencies:
pedantic: '>=1.7.0 <2.0.0' pedantic: '>=1.7.0 <2.0.0'

2
test/internal/test_utils.dart

@ -13,7 +13,7 @@ final _logger = Logger('test_utils');
class TestUtil { class TestUtil {
static KdbxFormat kdbxFormat() { static KdbxFormat kdbxFormat() {
Argon2FfiFlutter.resolveLibraryForceDynamic = true; Argon2.resolveLibraryForceDynamic = true;
return KdbxFormat(Argon2FfiFlutter(resolveLibrary: (path) { return KdbxFormat(Argon2FfiFlutter(resolveLibrary: (path) {
final cwd = Directory('.').absolute.uri; final cwd = Directory('.').absolute.uri;
final p = cwd.resolve(path); final p = cwd.resolve(path);

Loading…
Cancel
Save