Skip to content

Commit 4c0ec6a

Browse files
author
John
committed
Initial commit
1 parent 4b1d6dc commit 4c0ec6a

23 files changed

+1475
-1
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -337,4 +337,5 @@ ASALocalRun/
337337
.localhistory/
338338

339339
# BeatPulse healthcheck temp database
340-
healthchecksdb
340+
healthchecksdb
341+
/lib

App.config

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
5+
</startup>
6+
</configuration>

Crypto.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Text;
3+
4+
using System.Security.Cryptography;
5+
6+
using Org.BouncyCastle.Crypto.Engines;
7+
using Org.BouncyCastle.Crypto.Modes;
8+
using Org.BouncyCastle.Crypto.Parameters;
9+
10+
namespace DOOMSaveManager
11+
{
12+
public static class Crypto
13+
{
14+
public static byte[] EncryptAndDigest(string aad, byte[] data) {
15+
byte[] nonce = Utilities.RandomBytes(12);
16+
byte[] aadBytes = Encoding.UTF8.GetBytes(aad);
17+
byte[] aadHash = new SHA256Managed().ComputeHash(aadBytes);
18+
var cipher = new GcmBlockCipher(new AesEngine());
19+
var cParams = new AeadParameters(new KeyParameter(aadHash, 0, 16), 128, nonce, aadBytes);
20+
cipher.Init(true, cParams);
21+
byte[] ciphertext = new byte[cipher.GetOutputSize(data.Length)];
22+
int retLen = cipher.ProcessBytes(data, 0, data.Length, ciphertext, 0);
23+
cipher.DoFinal(ciphertext, retLen);
24+
25+
byte[] output = new byte[nonce.Length + ciphertext.Length];
26+
Buffer.BlockCopy(nonce, 0, output, 0, nonce.Length);
27+
Buffer.BlockCopy(ciphertext, 0, output, nonce.Length, ciphertext.Length);
28+
return output;
29+
}
30+
31+
public static byte[] DecryptAndVerify(string aad, byte[] data) {
32+
byte[] nonce = new byte[12];
33+
byte[] ciphertext = new byte[data.Length - 12];
34+
Buffer.BlockCopy(data, 0, nonce, 0, nonce.Length);
35+
Buffer.BlockCopy(data, nonce.Length, ciphertext, 0, ciphertext.Length);
36+
37+
byte[] aadBytes = Encoding.UTF8.GetBytes(aad);
38+
byte[] aadHash = new SHA256Managed().ComputeHash(aadBytes);
39+
var cipher = new GcmBlockCipher(new AesEngine());
40+
var cParams = new AeadParameters(new KeyParameter(aadHash, 0, 16), 128, nonce, aadBytes);
41+
cipher.Init(false, cParams);
42+
byte[] plaintext = new byte[cipher.GetOutputSize(ciphertext.Length)];
43+
int retLen = cipher.ProcessBytes(ciphertext, 0, ciphertext.Length, plaintext, 0);
44+
cipher.DoFinal(plaintext, retLen);
45+
46+
return plaintext;
47+
}
48+
}
49+
}

DOOMSaveManager.csproj

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4+
<PropertyGroup>
5+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7+
<ProjectGuid>{6057DF34-7DE4-44DB-9976-F78F4C2D402E}</ProjectGuid>
8+
<OutputType>WinExe</OutputType>
9+
<RootNamespace>DOOMSaveManager</RootNamespace>
10+
<AssemblyName>DOOM Save Manager</AssemblyName>
11+
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
12+
<FileAlignment>512</FileAlignment>
13+
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
14+
<Deterministic>true</Deterministic>
15+
<PublishUrl>publish\</PublishUrl>
16+
<Install>true</Install>
17+
<InstallFrom>Disk</InstallFrom>
18+
<UpdateEnabled>false</UpdateEnabled>
19+
<UpdateMode>Foreground</UpdateMode>
20+
<UpdateInterval>7</UpdateInterval>
21+
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
22+
<UpdatePeriodically>false</UpdatePeriodically>
23+
<UpdateRequired>false</UpdateRequired>
24+
<MapFileExtensions>true</MapFileExtensions>
25+
<ApplicationRevision>0</ApplicationRevision>
26+
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
27+
<IsWebBootstrapper>false</IsWebBootstrapper>
28+
<UseApplicationTrust>false</UseApplicationTrust>
29+
<BootstrapperEnabled>true</BootstrapperEnabled>
30+
</PropertyGroup>
31+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
32+
<PlatformTarget>AnyCPU</PlatformTarget>
33+
<DebugSymbols>true</DebugSymbols>
34+
<DebugType>full</DebugType>
35+
<Optimize>false</Optimize>
36+
<OutputPath>bin\Debug\</OutputPath>
37+
<DefineConstants>DEBUG;TRACE</DefineConstants>
38+
<ErrorReport>prompt</ErrorReport>
39+
<WarningLevel>4</WarningLevel>
40+
</PropertyGroup>
41+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
42+
<PlatformTarget>AnyCPU</PlatformTarget>
43+
<DebugType>pdbonly</DebugType>
44+
<Optimize>true</Optimize>
45+
<OutputPath>bin\Release\</OutputPath>
46+
<DefineConstants>TRACE</DefineConstants>
47+
<ErrorReport>prompt</ErrorReport>
48+
<WarningLevel>4</WarningLevel>
49+
</PropertyGroup>
50+
<ItemGroup>
51+
<Reference Include="BouncyCastle.Crypto">
52+
<HintPath>lib\BouncyCastle.Crypto.dll</HintPath>
53+
</Reference>
54+
<Reference Include="ICSharpCode.SharpZipLib, Version=1.2.0.246, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
55+
<HintPath>packages\SharpZipLib.1.2.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
56+
</Reference>
57+
<Reference Include="System" />
58+
<Reference Include="System.Core" />
59+
<Reference Include="System.Xml.Linq" />
60+
<Reference Include="System.Data.DataSetExtensions" />
61+
<Reference Include="Microsoft.CSharp" />
62+
<Reference Include="System.Data" />
63+
<Reference Include="System.Deployment" />
64+
<Reference Include="System.Drawing" />
65+
<Reference Include="System.Net.Http" />
66+
<Reference Include="System.Windows.Forms" />
67+
<Reference Include="System.Xml" />
68+
</ItemGroup>
69+
<ItemGroup>
70+
<Compile Include="Crypto.cs" />
71+
<Compile Include="DoomEternal.cs" />
72+
<Compile Include="Form1.cs">
73+
<SubType>Form</SubType>
74+
</Compile>
75+
<Compile Include="Form1.Designer.cs">
76+
<DependentUpon>Form1.cs</DependentUpon>
77+
</Compile>
78+
<Compile Include="Program.cs" />
79+
<Compile Include="Properties\AssemblyInfo.cs" />
80+
<Compile Include="TransferForm.cs">
81+
<SubType>Form</SubType>
82+
</Compile>
83+
<Compile Include="TransferForm.Designer.cs">
84+
<DependentUpon>TransferForm.cs</DependentUpon>
85+
</Compile>
86+
<Compile Include="Utilities.cs" />
87+
<Compile Include="SelectUUIDForm.cs">
88+
<SubType>Form</SubType>
89+
</Compile>
90+
<Compile Include="SelectUUIDForm.Designer.cs">
91+
<DependentUpon>SelectUUIDForm.cs</DependentUpon>
92+
</Compile>
93+
<EmbeddedResource Include="Form1.resx">
94+
<DependentUpon>Form1.cs</DependentUpon>
95+
</EmbeddedResource>
96+
<EmbeddedResource Include="Properties\Resources.resx">
97+
<Generator>ResXFileCodeGenerator</Generator>
98+
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
99+
<SubType>Designer</SubType>
100+
</EmbeddedResource>
101+
<Compile Include="Properties\Resources.Designer.cs">
102+
<AutoGen>True</AutoGen>
103+
<DependentUpon>Resources.resx</DependentUpon>
104+
<DesignTime>True</DesignTime>
105+
</Compile>
106+
<EmbeddedResource Include="TransferForm.resx">
107+
<DependentUpon>TransferForm.cs</DependentUpon>
108+
</EmbeddedResource>
109+
<EmbeddedResource Include="SelectUUIDForm.resx">
110+
<DependentUpon>SelectUUIDForm.cs</DependentUpon>
111+
</EmbeddedResource>
112+
<None Include="packages.config" />
113+
<None Include="Properties\Settings.settings">
114+
<Generator>SettingsSingleFileGenerator</Generator>
115+
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
116+
</None>
117+
<Compile Include="Properties\Settings.Designer.cs">
118+
<AutoGen>True</AutoGen>
119+
<DependentUpon>Settings.settings</DependentUpon>
120+
<DesignTimeSharedInput>True</DesignTimeSharedInput>
121+
</Compile>
122+
</ItemGroup>
123+
<ItemGroup>
124+
<None Include="App.config" />
125+
</ItemGroup>
126+
<ItemGroup>
127+
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
128+
<Visible>False</Visible>
129+
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
130+
<Install>true</Install>
131+
</BootstrapperPackage>
132+
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
133+
<Visible>False</Visible>
134+
<ProductName>.NET Framework 3.5 SP1</ProductName>
135+
<Install>false</Install>
136+
</BootstrapperPackage>
137+
</ItemGroup>
138+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
139+
</Project>

DOOMSaveManager.sln

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29911.98
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DOOMSaveManager", "DOOMSaveManager.csproj", "{6057DF34-7DE4-44DB-9976-F78F4C2D402E}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{6057DF34-7DE4-44DB-9976-F78F4C2D402E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{6057DF34-7DE4-44DB-9976-F78F4C2D402E}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{6057DF34-7DE4-44DB-9976-F78F4C2D402E}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{6057DF34-7DE4-44DB-9976-F78F4C2D402E}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {31718A44-E113-4D3D-A806-94773BAE5E67}
24+
EndGlobalSection
25+
EndGlobal

DoomEternal.cs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System;
2+
using System.Linq;
3+
4+
using System.IO;
5+
6+
namespace DOOMSaveManager
7+
{
8+
public class DoomEternal
9+
{
10+
public const string GameName = "Doom Eternal";
11+
12+
public static string SavePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Saved Games", "id Software", "DOOMEternal", "base", "savegame");
13+
14+
public const string BackupPassword = "doometernalbackup";
15+
16+
public static string[] GetUserIDs() {
17+
return Directory.GetDirectories(SavePath, "*.*", SearchOption.TopDirectoryOnly).Select(single => Path.GetFileNameWithoutExtension(single)).Where(single => Utilities.CheckUUID(single)).ToArray();
18+
}
19+
20+
public static void FileEncrypt(string fromFile, string toFile, string toUUID) {
21+
if (fromFile.EndsWith("-BACKUP"))
22+
return;
23+
byte[] fromFileData = File.ReadAllBytes(fromFile);
24+
Directory.CreateDirectory(Path.GetDirectoryName(toFile));
25+
File.WriteAllBytes(toFile, Crypto.EncryptAndDigest($"{toUUID}PAINELEMENTAL{Path.GetFileName(toFile)}", fromFileData));
26+
}
27+
28+
public static void FileDecrypt(string fromFile, string fromUUID, string toFile) {
29+
if (fromFile.EndsWith("-BACKUP"))
30+
return;
31+
byte[] fromFileData = Crypto.DecryptAndVerify($"{fromUUID}PAINELEMENTAL{Path.GetFileName(fromFile)}", File.ReadAllBytes(fromFile));
32+
Directory.CreateDirectory(Path.GetDirectoryName(toFile));
33+
File.WriteAllBytes(toFile, fromFileData);
34+
}
35+
36+
public static void FileTransfer(string fromFile, string fromUUID, string toFile, string toUUID) {
37+
if (fromFile.EndsWith("-BACKUP"))
38+
return;
39+
byte[] fromFileData = Crypto.DecryptAndVerify($"{fromUUID}PAINELEMENTAL{Path.GetFileName(fromFile)}", File.ReadAllBytes(fromFile));
40+
Directory.CreateDirectory(Path.GetDirectoryName(toFile));
41+
File.WriteAllBytes(toFile, Crypto.EncryptAndDigest($"{toUUID}PAINELEMENTAL{Path.GetFileName(toFile)}", fromFileData));
42+
}
43+
44+
public static void BulkTransfer(string fromUUID, string toUUID) {
45+
string fromDir = Path.Combine(SavePath, fromUUID);
46+
foreach(var single in Directory.GetFiles(fromDir, "*.*", SearchOption.AllDirectories)) {
47+
FileTransfer(single, fromUUID, single.Replace(fromUUID, toUUID), toUUID);
48+
}
49+
}
50+
51+
public static void BulkEncrypt(string fromDir, string toUUID) {
52+
string toDir = Path.Combine(SavePath, toUUID);
53+
foreach (var single in Directory.GetFiles(fromDir, "*.*", SearchOption.AllDirectories)) {
54+
Console.WriteLine(Path.Combine(toDir, single.Replace(fromDir, "").Substring(1)));
55+
FileEncrypt(single, Path.Combine(toDir, single.Replace(fromDir, "").Substring(1)), toUUID);
56+
}
57+
}
58+
59+
public static void BulkDecrypt(string fromUUID, string toDir) {
60+
string fromDir = Path.Combine(SavePath, fromUUID);
61+
foreach (var single in Directory.GetFiles(fromDir, "*.*", SearchOption.AllDirectories)) {
62+
FileDecrypt(single, fromUUID, Path.Combine(toDir, single.Replace(Path.Combine(SavePath, fromUUID), "").Substring(1)));
63+
}
64+
}
65+
}
66+
}

Form1.Designer.cs

+89
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)