Herbert Poul
5 years ago
11 changed files with 345 additions and 39 deletions
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration"> |
||||
<state> |
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" /> |
||||
</state> |
||||
</component> |
@ -0,0 +1,91 @@
|
||||
import 'dart:async'; |
||||
import 'dart:io'; |
||||
|
||||
import 'package:args/args.dart'; |
||||
import 'package:args/command_runner.dart'; |
||||
import 'package:kdbx/src/crypto/protected_value.dart'; |
||||
import 'package:kdbx/src/kdbx_format.dart'; |
||||
import 'package:kdbx/src/kdbx_header.dart'; |
||||
import 'package:logging/logging.dart'; |
||||
import 'package:logging_appenders/logging_appenders.dart'; |
||||
import 'package:prompts/prompts.dart' as prompts; |
||||
|
||||
final _logger = Logger('kdbx'); |
||||
|
||||
void main(List<String> arguments) { |
||||
exitCode = 0; |
||||
|
||||
final runner = KdbxCommandRunner('kdbx', 'Kdbx Utility'); |
||||
runner.run(arguments).catchError((dynamic error, StackTrace stackTrace) { |
||||
if (error is! UsageException) { |
||||
return Future<dynamic>.error(error, stackTrace); |
||||
} |
||||
print(error); |
||||
exit(64); |
||||
return null; |
||||
}); |
||||
|
||||
// final inputFile = args['input'] as String; |
||||
// if (inputFile == null) { |
||||
// print('Missing Argument --input'); |
||||
// print(parser.usage); |
||||
// exitCode = 1; |
||||
// return; |
||||
// } |
||||
_logger.info('done.'); |
||||
} |
||||
|
||||
class KdbxCommandRunner extends CommandRunner<void> { |
||||
KdbxCommandRunner(String executableName, String description) : super(executableName, description) { |
||||
argParser.addFlag('verbose', abbr: 'v'); |
||||
addCommand(CatCommand()); |
||||
} |
||||
|
||||
@override |
||||
Future<void> runCommand(ArgResults topLevelResults) { |
||||
PrintAppender().attachToLogger(Logger.root); |
||||
Logger.root.level = Level.INFO; |
||||
if (topLevelResults['verbose'] as bool) { |
||||
Logger.root.level = Level.ALL; |
||||
} |
||||
return super.runCommand(topLevelResults); |
||||
} |
||||
} |
||||
|
||||
abstract class KdbxFileCommand extends Command<void> { |
||||
KdbxFileCommand() { |
||||
argParser.addOption( |
||||
'input', |
||||
abbr: 'i', |
||||
help: 'Input kdbx file', |
||||
valueHelp: 'foo.kdbx', |
||||
); |
||||
} |
||||
|
||||
@override |
||||
FutureOr<void> run() async { |
||||
final inputFile = argResults['input'] as String; |
||||
if (inputFile == null) { |
||||
usageException('Required argument: --input'); |
||||
} |
||||
final bytes = await File(inputFile).readAsBytes(); |
||||
final password = prompts.get('Password for $inputFile', conceal: true, validate: (str) => str.isNotEmpty); |
||||
final file = await KdbxFormat.read(bytes, Credentials(ProtectedValue.fromString(password))); |
||||
return runWithFile(file); |
||||
} |
||||
|
||||
Future<void> runWithFile(KdbxFile file); |
||||
} |
||||
|
||||
class CatCommand extends KdbxFileCommand { |
||||
@override |
||||
String get description => 'outputs all entries from file.'; |
||||
|
||||
@override |
||||
String get name => 'cat'; |
||||
|
||||
@override |
||||
Future<void> runWithFile(KdbxFile file) async { |
||||
_logger.severe('running'); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
|
||||
import 'dart:convert'; |
||||
import 'dart:typed_data'; |
||||
|
||||
import 'package:crypto/crypto.dart'; |
||||
import 'package:pointycastle/export.dart'; |
||||
|
||||
class ProtectedSaltGenerator { |
||||
factory ProtectedSaltGenerator(Uint8List key) { |
||||
final hash = sha256.convert(key).bytes as Uint8List; |
||||
final cipher = Salsa20Engine()..init(false, ParametersWithIV(KeyParameter(hash), SalsaNonce)); |
||||
return ProtectedSaltGenerator._(cipher); |
||||
} |
||||
|
||||
ProtectedSaltGenerator._(this.cipher); |
||||
|
||||
static final SalsaNonce = Uint8List.fromList([0xE8, 0x30, 0x09, 0x4B, 0x97, 0x20, 0x5D, 0x2A]); |
||||
final StreamCipher cipher; |
||||
|
||||
String decryptBase64(String protectedValue) { |
||||
final bytes = base64.decode(protectedValue); |
||||
final result = cipher.process(bytes); |
||||
final decrypted = utf8.decode(result); |
||||
return decrypted; |
||||
} |
||||
} |
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?> |
||||
<KeePassFile> |
||||
<Meta> |
||||
<Generator>KdbxWeb</Generator> |
||||
<HeaderHash>r9uD96EiudcSeXq62ma/OqtBBPf+EYX7iMrBaNJBRwo=</HeaderHash> |
||||
<DatabaseName>FooBar</DatabaseName> |
||||
<DatabaseNameChanged>2019-08-20T13:16:06Z</DatabaseNameChanged> |
||||
<DatabaseDescription /> |
||||
<DatabaseDescriptionChanged>2019-08-20T13:15:47Z</DatabaseDescriptionChanged> |
||||
<DefaultUserName /> |
||||
<DefaultUserNameChanged>2019-08-20T13:15:47Z</DefaultUserNameChanged> |
||||
<MaintenanceHistoryDays>365</MaintenanceHistoryDays> |
||||
<Color /> |
||||
<MasterKeyChanged>2019-08-20T13:16:03Z</MasterKeyChanged> |
||||
<MasterKeyChangeRec>-1</MasterKeyChangeRec> |
||||
<MasterKeyChangeForce>-1</MasterKeyChangeForce> |
||||
<RecycleBinEnabled>True</RecycleBinEnabled> |
||||
<RecycleBinUUID>dVSBC/BAx70qcsy6XkrGJA==</RecycleBinUUID> |
||||
<RecycleBinChanged>2019-08-20T13:15:47Z</RecycleBinChanged> |
||||
<EntryTemplatesGroup>AAAAAAAAAAAAAAAAAAAAAA==</EntryTemplatesGroup> |
||||
<EntryTemplatesGroupChanged>2019-08-20T13:15:47Z</EntryTemplatesGroupChanged> |
||||
<HistoryMaxItems>10</HistoryMaxItems> |
||||
<HistoryMaxSize>6291456</HistoryMaxSize> |
||||
<LastSelectedGroup /> |
||||
<LastTopVisibleGroup /> |
||||
<MemoryProtection> |
||||
<ProtectTitle>False</ProtectTitle> |
||||
<ProtectUserName>False</ProtectUserName> |
||||
<ProtectPassword>True</ProtectPassword> |
||||
<ProtectURL>False</ProtectURL> |
||||
<ProtectNotes>False</ProtectNotes> |
||||
</MemoryProtection> |
||||
<CustomIcons /> |
||||
<Binaries /> |
||||
<CustomData /> |
||||
</Meta> |
||||
<Root> |
||||
<Group> |
||||
<UUID>LAQMkihXTkxhA2D2tE40Fg==</UUID> |
||||
<Name>FooBar</Name> |
||||
<Notes /> |
||||
<IconID>49</IconID> |
||||
<Times> |
||||
<CreationTime>2019-08-20T13:15:47Z</CreationTime> |
||||
<LastModificationTime>2019-08-20T13:16:06Z</LastModificationTime> |
||||
<LastAccessTime>2019-08-20T13:16:06Z</LastAccessTime> |
||||
<ExpiryTime>2019-08-20T13:15:47Z</ExpiryTime> |
||||
<Expires>False</Expires> |
||||
<UsageCount>0</UsageCount> |
||||
<LocationChanged>2019-08-20T13:15:47Z</LocationChanged> |
||||
</Times> |
||||
<IsExpanded>True</IsExpanded> |
||||
<DefaultAutoTypeSequence /> |
||||
<EnableAutoType>null</EnableAutoType> |
||||
<EnableSearching>null</EnableSearching> |
||||
<LastTopVisibleEntry>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleEntry> |
||||
<Group> |
||||
<UUID>dVSBC/BAx70qcsy6XkrGJA==</UUID> |
||||
<Name>Recycle Bin</Name> |
||||
<Notes /> |
||||
<IconID>43</IconID> |
||||
<Times> |
||||
<CreationTime>2019-08-20T13:15:47Z</CreationTime> |
||||
<LastModificationTime>2019-08-20T13:15:47Z</LastModificationTime> |
||||
<LastAccessTime>2019-08-20T13:15:47Z</LastAccessTime> |
||||
<ExpiryTime>2019-08-20T13:15:47Z</ExpiryTime> |
||||
<Expires>False</Expires> |
||||
<UsageCount>0</UsageCount> |
||||
<LocationChanged>2019-08-20T13:15:47Z</LocationChanged> |
||||
</Times> |
||||
<IsExpanded>True</IsExpanded> |
||||
<DefaultAutoTypeSequence /> |
||||
<EnableAutoType>False</EnableAutoType> |
||||
<EnableSearching>False</EnableSearching> |
||||
<LastTopVisibleEntry>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleEntry> |
||||
</Group> |
||||
<Entry> |
||||
<UUID>RMUeiV24MDcrIY8qQYRAlg==</UUID> |
||||
<IconID>0</IconID> |
||||
<ForegroundColor /> |
||||
<BackgroundColor /> |
||||
<OverrideURL /> |
||||
<Tags /> |
||||
<Times> |
||||
<CreationTime>2019-08-21T00:17:25Z</CreationTime> |
||||
<LastModificationTime>2019-08-21T00:17:36Z</LastModificationTime> |
||||
<LastAccessTime>2019-08-21T00:17:36Z</LastAccessTime> |
||||
<ExpiryTime>2019-08-21T00:17:25Z</ExpiryTime> |
||||
<Expires>False</Expires> |
||||
<UsageCount>0</UsageCount> |
||||
<LocationChanged>2019-08-21T00:17:25Z</LocationChanged> |
||||
</Times> |
||||
<String> |
||||
<Key>Title</Key> |
||||
<Value>loremipsum.com</Value> |
||||
</String> |
||||
<String> |
||||
<Key>UserName</Key> |
||||
<Value>foo</Value> |
||||
</String> |
||||
<String> |
||||
<Key>Password</Key> |
||||
<Value Protected="True">QcvZ</Value> |
||||
</String> |
||||
<String> |
||||
<Key>URL</Key> |
||||
<Value /> |
||||
</String> |
||||
<String> |
||||
<Key>Notes</Key> |
||||
<Value /> |
||||
</String> |
||||
<AutoType> |
||||
<Enabled>True</Enabled> |
||||
<DataTransferObfuscation>0</DataTransferObfuscation> |
||||
</AutoType> |
||||
<History /> |
||||
</Entry> |
||||
</Group> |
||||
<DeletedObjects /> |
||||
</Root> |
||||
</KeePassFile> |
Loading…
Reference in new issue