Herbert Poul
3 years ago
6 changed files with 116 additions and 6 deletions
@ -0,0 +1,38 @@
|
||||
import 'dart:typed_data'; |
||||
|
||||
import 'package:argon2_ffi_base/argon2_ffi_base.dart'; |
||||
import 'package:pointycastle/export.dart' as pc; |
||||
import 'package:pointycastle/pointycastle.dart' as pc; |
||||
|
||||
/// Dart-only implementation using pointycastle's Argon KDF. |
||||
class PointyCastleArgon2 extends Argon2 { |
||||
const PointyCastleArgon2(); |
||||
|
||||
@override |
||||
bool get isFfi => false; |
||||
|
||||
@override |
||||
bool get isImplemented => true; |
||||
|
||||
pc.KeyDerivator argon2Kdf() => pc.Argon2BytesGenerator(); |
||||
|
||||
@override |
||||
Uint8List argon2(Argon2Arguments args) { |
||||
final kdf = argon2Kdf(); |
||||
kdf.init(pc.Argon2Parameters( |
||||
args.type, |
||||
args.salt, |
||||
desiredKeyLength: args.length, |
||||
iterations: args.iterations, |
||||
memory: args.memory, |
||||
lanes: args.parallelism, |
||||
version: args.version, |
||||
)); |
||||
return kdf.process(args.key); |
||||
} |
||||
|
||||
@override |
||||
Future<Uint8List> argon2Async(Argon2Arguments args) { |
||||
return Future.value(argon2(args)); |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'package:kdbx/kdbx.dart'; |
||||
import 'package:kdbx/src/kdbx_header.dart'; |
||||
|
||||
import 'package:logging/logging.dart'; |
||||
import 'package:test/test.dart'; |
||||
|
||||
import 'internal/test_utils.dart'; |
||||
|
||||
final _logger = Logger('kdbx4_test_pointycastle'); |
||||
|
||||
void main() { |
||||
// ignore: unused_local_variable |
||||
final testUtil = TestUtil(); |
||||
final kdbxFormat = KdbxFormat(); |
||||
if (kdbxFormat.argon2.isFfi) { |
||||
throw StateError('Expected non-ffi implementation.'); |
||||
} |
||||
_logger.fine('argon2 implementation: ${kdbxFormat.argon2}'); |
||||
group('Reading pointycastle argon2', () { |
||||
test('pc: Reading kdbx4_keeweb', () async { |
||||
final data = await File('test/kdbx4_keeweb.kdbx').readAsBytes(); |
||||
final file = await kdbxFormat.read( |
||||
data, Credentials(ProtectedValue.fromString('asdf'))); |
||||
final firstEntry = file.body.rootGroup.entries.first; |
||||
final pwd = firstEntry.getString(KdbxKeyCommon.PASSWORD)!.getText(); |
||||
expect(pwd, 'def'); |
||||
}); |
||||
}); |
||||
group('Writing pointycastle argon2', () { |
||||
test('Create and save', () async { |
||||
final credentials = Credentials(ProtectedValue.fromString('asdf')); |
||||
final kdbx = kdbxFormat.create( |
||||
credentials, |
||||
'Test Keystore', |
||||
header: KdbxHeader.createV4(), |
||||
); |
||||
final rootGroup = kdbx.body.rootGroup; |
||||
_createEntry(kdbx, rootGroup, 'user1', 'LoremIpsum'); |
||||
_createEntry(kdbx, rootGroup, 'user2', 'Second Password'); |
||||
final saved = await kdbx.save(); |
||||
|
||||
final loadedKdbx = await kdbxFormat.read( |
||||
saved, Credentials(ProtectedValue.fromString('asdf'))); |
||||
_logger.fine('Successfully loaded kdbx $loadedKdbx'); |
||||
File('test_v4x.kdbx').writeAsBytesSync(saved); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
KdbxEntry _createEntry( |
||||
KdbxFile file, KdbxGroup group, String username, String password) { |
||||
final entry = KdbxEntry.create(file, group); |
||||
group.addEntry(entry); |
||||
entry.setString(KdbxKeyCommon.USER_NAME, PlainValue(username)); |
||||
entry.setString(KdbxKeyCommon.PASSWORD, ProtectedValue.fromString(password)); |
||||
return entry; |
||||
} |
Loading…
Reference in new issue