Browse Source

support for chacha20 encryption.

remove-cryptography-dependency
Herbert Poul 5 years ago
parent
commit
c8b49e6b5c
  1. 16
      lib/src/kdbx_format.dart
  2. BIN
      test/chacha20.kdbx
  3. 45
      test/kdbx4_test.dart
  4. BIN
      test_output_chacha20.kdbx

16
lib/src/kdbx_format.dart

@ -5,6 +5,7 @@ import 'dart:typed_data';
import 'package:convert/convert.dart' as convert; import 'package:convert/convert.dart' as convert;
import 'package:crypto/crypto.dart' as crypto; import 'package:crypto/crypto.dart' as crypto;
import 'package:cryptography/cryptography.dart' as cryptography;
import 'package:kdbx/kdbx.dart'; import 'package:kdbx/kdbx.dart';
import 'package:kdbx/src/crypto/argon2.dart'; import 'package:kdbx/src/crypto/argon2.dart';
import 'package:kdbx/src/crypto/key_encrypter_kdf.dart'; import 'package:kdbx/src/crypto/key_encrypter_kdf.dart';
@ -285,8 +286,8 @@ class KdbxBody extends KdbxNode {
return result; return result;
} else if (cipherId == CryptoConsts.CIPHER_IDS[Cipher.chaCha20].uuid) { } else if (cipherId == CryptoConsts.CIPHER_IDS[Cipher.chaCha20].uuid) {
_logger.fine('We need chacha20'); _logger.fine('We need chacha20');
// TODO can we combine this with _encryptV3? return kdbxFile.kdbxFormat
throw UnsupportedError('Unsupported cipher chacha20 for kdbx 4.x'); .transformContentV4ChaCha20(header, compressedBytes, cipherKey);
} else { } else {
throw UnsupportedError('Unsupported cipherId $cipherId'); throw UnsupportedError('Unsupported cipherId $cipherId');
} }
@ -509,12 +510,21 @@ class KdbxFormat {
return result; return result;
} else if (cipherId == CryptoConsts.CIPHER_IDS[Cipher.chaCha20].uuid) { } else if (cipherId == CryptoConsts.CIPHER_IDS[Cipher.chaCha20].uuid) {
_logger.fine('We need chacha20'); _logger.fine('We need chacha20');
throw UnsupportedError('chacha20 not yet supported $cipherId'); // throw UnsupportedError('chacha20 not yet supported $cipherId');
return transformContentV4ChaCha20(header, encrypted, cipherKey);
} else { } else {
throw UnsupportedError('Unsupported cipherId $cipherId'); throw UnsupportedError('Unsupported cipherId $cipherId');
} }
} }
Uint8List transformContentV4ChaCha20(
KdbxHeader header, Uint8List encrypted, Uint8List cipherKey) {
final encryptionIv = header.fields[HeaderFields.EncryptionIV].bytes;
final key = cryptography.SecretKey(cipherKey);
final nonce = cryptography.SecretKey(encryptionIv);
return cryptography.chacha20.decrypt(encrypted, key, nonce: nonce);
}
// Uint8List _transformDataV4Aes() { // Uint8List _transformDataV4Aes() {
// } // }

BIN
test/chacha20.kdbx

Binary file not shown.

45
test/kdbx4_test.dart

@ -88,6 +88,12 @@ void main() {
Credentials.composite(ProtectedValue.fromString('asdf'), keyFile)); Credentials.composite(ProtectedValue.fromString('asdf'), keyFile));
expect(file.body.rootGroup.entries, hasLength(1)); expect(file.body.rootGroup.entries, hasLength(1));
}); });
test('Reading chacha20', () async {
final data = await File('test/chacha20.kdbx').readAsBytes();
final file =
kdbxFormat.read(data, Credentials(ProtectedValue.fromString('asdf')));
expect(file.body.rootGroup.entries, hasLength(1));
});
}); });
group('Writing', () { group('Writing', () {
test('Create and save', () { test('Create and save', () {
@ -98,22 +104,8 @@ void main() {
header: KdbxHeader.createV4(), header: KdbxHeader.createV4(),
); );
final rootGroup = kdbx.body.rootGroup; final rootGroup = kdbx.body.rootGroup;
{ _createEntry(kdbx, rootGroup, 'user1', 'LoremIpsum');
final entry = KdbxEntry.create(kdbx, rootGroup); _createEntry(kdbx, rootGroup, 'user2', 'Second Password');
rootGroup.addEntry(entry);
entry.setString(KdbxKey('Username'), PlainValue('user1'));
entry.setString(
KdbxKey('Password'), ProtectedValue.fromString('LoremIpsum'));
}
{
final entry = KdbxEntry.create(kdbx, rootGroup);
rootGroup.addEntry(entry);
entry.setString(KdbxKey('Username'), PlainValue('user2'));
entry.setString(
KdbxKey('Password'),
ProtectedValue.fromString('Second Password'),
);
}
final saved = kdbx.save(); final saved = kdbx.save();
final loadedKdbx = kdbxFormat.read( final loadedKdbx = kdbxFormat.read(
@ -126,5 +118,26 @@ void main() {
final file = final file =
kdbxFormat.read(data, Credentials(ProtectedValue.fromString('asdf'))); kdbxFormat.read(data, Credentials(ProtectedValue.fromString('asdf')));
}); });
test('write chacha20', () async {
final data = await File('test/chacha20.kdbx').readAsBytes();
final file =
kdbxFormat.read(data, Credentials(ProtectedValue.fromString('asdf')));
expect(file.body.rootGroup.entries, hasLength(1));
_createEntry(file, file.body.rootGroup, 'user1', 'LoremIpsum');
// and try to write it.
final output = file.save();
expect(output, isNotNull);
File('test_output_chacha20.kdbx').writeAsBytesSync(output);
}); });
});
}
KdbxEntry _createEntry(
KdbxFile file, KdbxGroup group, String username, String password) {
final entry = KdbxEntry.create(file, group);
group.addEntry(entry);
entry.setString(KdbxKey('UserName'), PlainValue(username));
entry.setString(KdbxKey('Password'), ProtectedValue.fromString(password));
return entry;
} }

BIN
test_output_chacha20.kdbx

Binary file not shown.
Loading…
Cancel
Save