// Command action public int OnExecute(CommandLineApplication app) { // Prepare output data structure this.outputFile = new EncryptedFile(); // Get encryption key if (!string.IsNullOrEmpty(this.KeyFile)) { // Get key from file (or create new random) if (!this.GetKeyFromFile()) { return(1); } } else if (!string.IsNullOrEmpty(this.Password)) { // Derive key from password specified as option this.GetKeyFromPassword(); } else { // Derive key from password entered interactively var pwd1 = Prompt.GetPassword("Enter encryption password: "******"Password cannot be empty."); return(1); } var pwd2 = Prompt.GetPassword("Confirm encryption password: "******"Confirmation does not match the password."); return(1); } this.Password = pwd1; Console.WriteLine(); this.GetKeyFromPassword(); } // Read data for encryption Console.Write($"Reading plaintext file {this.InputFileName}..."); var plainBytes = File.ReadAllBytes(this.InputFileName); Console.WriteLine($"OK, {plainBytes.Length} bytes read"); // Prepare authenticated data var adBytes = string.IsNullOrEmpty(this.AuthenticatedData) ? null : System.Text.Encoding.UTF8.GetBytes(this.AuthenticatedData); // Create 96-bit nonce Console.Write("Preparing 96-bit nonce..."); var nonce = new byte[12]; RandomNumberGenerator.Fill(nonce); Console.WriteLine("OK"); // Prepare arrays in target var tag = new byte[16]; var data = new byte[plainBytes.Length]; // Encrypt Console.Write("Encrypting with AES-GCM..."); using var aes = new AesGcm(this.key); aes.Encrypt(nonce, plainBytes, data, tag, adBytes); Console.WriteLine("OK"); // Serialize to JSON this.outputFile.AuthenticatedData = this.AuthenticatedData; this.outputFile.Nonce = Convert.ToBase64String(nonce); this.outputFile.Tag = Convert.ToBase64String(tag); this.outputFile.Data = Convert.ToBase64String(data); var json = JsonSerializer.ToString(this.outputFile, new JsonSerializerOptions { IgnoreNullValues = true, WriteIndented = true }); // Save to output file if (string.IsNullOrEmpty(this.OutputFileName)) { this.OutputFileName = this.InputFileName + ".fjd"; } Console.Write($"Saving to {this.OutputFileName}..."); File.WriteAllText(this.OutputFileName, json); Console.WriteLine("OK"); return(0); }
// Command action public int OnExecute(CommandLineApplication app) { // Read data file Console.Write($"Reading encrypted file {this.InputFileName}..."); var json = File.ReadAllText(this.InputFileName); this.inputFile = JsonSerializer.Parse <EncryptedFile>(json); Console.WriteLine("OK"); // Get key if (this.inputFile.PasswordOptions is null) { // Keyfile requested if (string.IsNullOrEmpty(this.KeyFile)) { Console.WriteLine("This file was encrypted using key file. Please specify it using -k option."); return(0); } // Read key from file Console.Write($"Reading key from {this.KeyFile}..."); this.key = File.ReadAllBytes(this.KeyFile); var keyLength = this.key.Length * 8; if (keyLength != 128 && keyLength != 256) { Console.WriteLine("Failed!"); Console.WriteLine($"File has {keyLength} bits, expected 128 or 256."); return(1); } Console.WriteLine($"OK, {keyLength} bits"); } else { // If password not specified, get key from user if (string.IsNullOrEmpty(this.Password)) { this.Password = Prompt.GetPassword("Enter decryption password: "******"Generating {this.inputFile.PasswordOptions.Length} bit key from password using PBKDF2 with {this.inputFile.PasswordOptions.Iterations} iterations..."); var pbkdf = new Rfc2898DeriveBytes(this.Password, Convert.FromBase64String(this.inputFile.PasswordOptions.Salt), this.inputFile.PasswordOptions.Iterations); this.key = pbkdf.GetBytes(this.inputFile.PasswordOptions.Length / 8); Console.WriteLine("OK"); } // Get authenticated data var adData = string.IsNullOrEmpty(this.inputFile.AuthenticatedData) ? null : Encoding.UTF8.GetBytes(this.inputFile.AuthenticatedData); // Get nonce and tag var nonce = Convert.FromBase64String(this.inputFile.Nonce); var tag = Convert.FromBase64String(this.inputFile.Tag); var cipherData = Convert.FromBase64String(this.inputFile.Data); var plainData = new byte[cipherData.Length]; // Decrypt try { Console.Write("Decrypting using AES-GCM..."); using var aes = new AesGcm(this.key); aes.Decrypt(nonce, cipherData, tag, plainData, adData); Console.WriteLine("OK"); } catch (CryptographicException cex) { Console.WriteLine("Failed!"); Console.WriteLine(cex.Message); return(2); } // Display AD if (!string.IsNullOrEmpty(this.inputFile.AuthenticatedData)) { Console.WriteLine("Additional authenticated data:"); Console.WriteLine(this.inputFile.AuthenticatedData); } // Save to file if (string.IsNullOrEmpty(this.OutputFileName)) { this.OutputFileName = Path.Combine(Path.GetDirectoryName(this.InputFileName), Path.GetFileNameWithoutExtension(this.InputFileName)); } Console.Write($"Saving decrypted file to {this.OutputFileName}..."); File.WriteAllBytes(this.OutputFileName, plainData); Console.WriteLine("OK"); return(0); }