Skip to content

Commit 898e6dc

Browse files
authored
Merge pull request #18 from DEFRA/feature/2832-crypto-tool
2832 crypto tool
2 parents a0436ef + 5bc7fe7 commit 898e6dc

File tree

4 files changed

+192
-0
lines changed

4 files changed

+192
-0
lines changed

KeeperData.Bridge.sln

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-co
3131
EndProject
3232
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeeperData.Core.Tests.Unit", "tests\KeeperData.Core.Tests.Unit\KeeperData.Core.Tests.Unit.csproj", "{389DD08B-1B37-4BF2-9F2B-3F4805B25A46}"
3333
EndProject
34+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "util", "util", "{25784FFF-FBA8-4398-8497-7BE1FF8F92A5}"
35+
EndProject
36+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeeperData.Crypto.Tool", "src\KeeperData.Crypto.Tool\KeeperData.Crypto.Tool.csproj", "{92F51802-9BF8-42A8-98C9-C25B27163DF0}"
37+
EndProject
3438
Global
3539
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3640
Debug|Any CPU = Debug|Any CPU
@@ -77,6 +81,10 @@ Global
7781
{389DD08B-1B37-4BF2-9F2B-3F4805B25A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
7882
{389DD08B-1B37-4BF2-9F2B-3F4805B25A46}.Release|Any CPU.ActiveCfg = Release|Any CPU
7983
{389DD08B-1B37-4BF2-9F2B-3F4805B25A46}.Release|Any CPU.Build.0 = Release|Any CPU
84+
{92F51802-9BF8-42A8-98C9-C25B27163DF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
85+
{92F51802-9BF8-42A8-98C9-C25B27163DF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
86+
{92F51802-9BF8-42A8-98C9-C25B27163DF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
87+
{92F51802-9BF8-42A8-98C9-C25B27163DF0}.Release|Any CPU.Build.0 = Release|Any CPU
8088
EndGlobalSection
8189
GlobalSection(SolutionProperties) = preSolution
8290
HideSolutionNode = FALSE
@@ -86,6 +94,7 @@ Global
8694
{E2B6D37D-2D17-4B43-83DC-36F1C4961526} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
8795
{16AA106D-B4F1-46C9-92F3-548AE89FDA3A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
8896
{389DD08B-1B37-4BF2-9F2B-3F4805B25A46} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
97+
{92F51802-9BF8-42A8-98C9-C25B27163DF0} = {25784FFF-FBA8-4398-8497-7BE1FF8F92A5}
8998
EndGlobalSection
9099
GlobalSection(ExtensibilityGlobals) = postSolution
91100
SolutionGuid = {235917AE-9AF5-49A5-AB06-472A5E5DB30D}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
<AssemblyName>kryp</AssemblyName>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.9" />
13+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.9" />
14+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.9" />
15+
<PackageReference Include="System.CommandLine" Version="2.0.0-rc.1.25451.107" />
16+
<ProjectReference Include="..\KeeperData.Core\KeeperData.Core.csproj" />
17+
<ProjectReference Include="..\KeeperData.Infrastructure\KeeperData.Infrastructure.csproj" />
18+
</ItemGroup>
19+
20+
</Project>
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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($"\rProgress: {progress}% - {status}");
48+
});
49+
50+
Console.WriteLine("\nEncryption completed successfully!");
51+
}
52+
catch (Exception ex)
53+
{
54+
Console.WriteLine($"\nEncryption 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($"\rProgress: {progress}% - {status}");
88+
});
89+
90+
Console.WriteLine("\nDecryption completed successfully!");
91+
}
92+
catch (Exception ex)
93+
{
94+
Console.WriteLine($"\nDecryption 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();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
3+
<Project>
4+
<PropertyGroup>
5+
<Configuration>Release</Configuration>
6+
<Platform>Any CPU</Platform>
7+
<PublishDir>bin\Release\net8.0\publish\win-x64\</PublishDir>
8+
<PublishProtocol>FileSystem</PublishProtocol>
9+
<_TargetId>Folder</_TargetId>
10+
<TargetFramework>net8.0</TargetFramework>
11+
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
12+
<SelfContained>true</SelfContained>
13+
<PublishSingleFile>true</PublishSingleFile>
14+
<PublishReadyToRun>true</PublishReadyToRun>
15+
<PublishTrimmed>true</PublishTrimmed>
16+
</PropertyGroup>
17+
</Project>

0 commit comments

Comments
 (0)