1+ using KeeperData . Core . Crypto ;
2+ using KeeperData . Infrastructure . Crypto ;
3+ using Microsoft . Extensions . Configuration ;
4+ using Microsoft . Extensions . DependencyInjection ;
5+ using Microsoft . Extensions . Hosting ;
6+ using Microsoft . Extensions . Logging ;
7+ using System . CommandLine ;
8+
9+ var builder = Host . CreateApplicationBuilder ( args ) ;
10+ builder . Configuration . AddEnvironmentVariables ( ) ;
11+ builder . Configuration . AddInMemoryCollection ( [ new KeyValuePair < string , string ? > ( "AesSalt" , "fakesalt" ) ] ) ;
12+ builder . Services . AddLogging ( config => config . AddConsole ( ) ) ;
13+ builder . Services . AddCrypto ( builder . Configuration ) ;
14+
15+ var host = builder . Build ( ) ;
16+
17+ var rootCommand = new RootCommand ( "KeeperData Crypto Tool - File encryption/decryption utility" ) ;
18+
19+ var encryptCommand = new Command ( "encrypt" , "Encrypt a file" )
20+ {
21+ new Option < string > ( "--input" ) { Description = "Input file path" , Required = true } ,
22+ new Option < string > ( "--output" ) { Description = "Output file path" , Required = true } ,
23+ new Option < string > ( "--password" ) { Description = "Encryption password" , Required = true } ,
24+ new Option < string > ( "--salt" ) { Description = "Encryption salt" , Required = true }
25+ } ;
26+
27+ encryptCommand . SetAction ( async ( parseResult ) =>
28+ {
29+ var inputFile = parseResult . GetValue < string > ( "--input" ) ! ;
30+ var outputFile = parseResult . GetValue < string > ( "--output" ) ! ;
31+ var password = parseResult . GetValue < string > ( "--password" ) ! ;
32+ var salt = parseResult . GetValue < string > ( "--salt" ) ! ;
33+
34+ var cryptoTransform = host . Services . GetRequiredService < IAesCryptoTransform > ( ) ;
35+
36+ Console . WriteLine ( $ "Encrypting '{ inputFile } ' to '{ outputFile } '...") ;
37+
38+ try
39+ {
40+ await cryptoTransform . EncryptFileAsync (
41+ inputFile ,
42+ outputFile ,
43+ password ,
44+ salt ,
45+ ( progress , status ) =>
46+ {
47+ Console . Write ( $ "\r Progress: { progress } % - { status } ") ;
48+ } ) ;
49+
50+ Console . WriteLine ( "\n Encryption completed successfully!" ) ;
51+ }
52+ catch ( Exception ex )
53+ {
54+ Console . WriteLine ( $ "\n Encryption failed: { ex . Message } ") ;
55+ Environment . Exit ( 1 ) ;
56+ }
57+ } ) ;
58+
59+ var decryptCommand = new Command ( "decrypt" , "Decrypt a file" )
60+ {
61+ new Option < string > ( "--input" ) { Description = "Input file path" , Required = true } ,
62+ new Option < string > ( "--output" ) { Description = "Output file path" , Required = true } ,
63+ new Option < string > ( "--password" ) { Description = "Decryption password" , Required = true } ,
64+ new Option < string > ( "--salt" ) { Description = "Decryption salt" , Required = true }
65+ } ;
66+
67+ decryptCommand . SetAction ( async ( parseResult ) =>
68+ {
69+ var inputFile = parseResult . GetValue < string > ( "--input" ) ! ;
70+ var outputFile = parseResult . GetValue < string > ( "--output" ) ! ;
71+ var password = parseResult . GetValue < string > ( "--password" ) ! ;
72+ var salt = parseResult . GetValue < string > ( "--salt" ) ! ;
73+
74+ var cryptoTransform = host . Services . GetRequiredService < IAesCryptoTransform > ( ) ;
75+
76+ Console . WriteLine ( $ "Decrypting '{ inputFile } ' to '{ outputFile } '...") ;
77+
78+ try
79+ {
80+ await cryptoTransform . DecryptFileAsync (
81+ inputFile ,
82+ outputFile ,
83+ password ,
84+ salt ,
85+ ( progress , status ) =>
86+ {
87+ Console . Write ( $ "\r Progress: { progress } % - { status } ") ;
88+ } ) ;
89+
90+ Console . WriteLine ( "\n Decryption completed successfully!" ) ;
91+ }
92+ catch ( Exception ex )
93+ {
94+ Console . WriteLine ( $ "\n Decryption failed: { ex . Message } ") ;
95+ Environment . Exit ( 1 ) ;
96+ }
97+ } ) ;
98+
99+ var getPasswordCommand = new Command ( "get-password" , "Get password for a filename" )
100+ {
101+ new Option < string > ( "--filename" ) { Description = "Filename to get password for" , Required = true }
102+ } ;
103+
104+ getPasswordCommand . SetAction ( ( parseResult ) =>
105+ {
106+ var filename = parseResult . GetValue < string > ( "--filename" ) ! ;
107+ var passwordSaltService = host . Services . GetRequiredService < IPasswordSaltService > ( ) ;
108+
109+ try
110+ {
111+ var passwordSalt = passwordSaltService . Get ( filename ) ;
112+ Console . WriteLine ( $ "Password: { passwordSalt . Password } ") ;
113+ // Console.WriteLine($"Salt: {passwordSalt.Salt}"); // ignore salt, we only use fake values in this tool.
114+ }
115+ catch ( Exception ex )
116+ {
117+ Console . WriteLine ( $ "Error getting password for filename '{ filename } ': { ex . Message } ") ;
118+ Environment . Exit ( 1 ) ;
119+ }
120+ } ) ;
121+
122+ var generateFilenameCommand = new Command ( "generate-filename" , "Generate a compliant filename" ) ;
123+
124+ generateFilenameCommand . SetAction ( ( parseResult ) =>
125+ {
126+ var passwordSaltService = host . Services . GetRequiredService < IPasswordSaltService > ( ) ;
127+
128+ try
129+ {
130+ var filename = passwordSaltService . GenerateFileName ( ) ;
131+ Console . WriteLine ( $ "Generated filename: { filename } ") ;
132+ }
133+ catch ( Exception ex )
134+ {
135+ Console . WriteLine ( $ "Error generating filename: { ex . Message } ") ;
136+ Environment . Exit ( 1 ) ;
137+ }
138+ } ) ;
139+
140+ rootCommand . Add ( encryptCommand ) ;
141+ rootCommand . Add ( decryptCommand ) ;
142+ rootCommand . Add ( getPasswordCommand ) ;
143+ rootCommand . Add ( generateFilenameCommand ) ;
144+
145+ var parseResult = rootCommand . Parse ( args ) ;
146+ return await parseResult . InvokeAsync ( ) ;
0 commit comments