Below, we will introduce how to encrypt your own program using LiteDB, and first provide an overview of LiteDB.
LiteDB
LiteDB is a lightweight embedded database written in C# for the .NET platform. Its design goal is to provide a simple and easy-to-use database solution that can be used in various applications.
LiteDB uses a single file for database storage, which can be stored on disk or in memory. It supports a document storage model, similar to NoSQL databases, where each document is a JSON-formatted object. This means you can store and retrieve any type of data without needing a predefined schema.
LiteDB provides a simple set of APIs to perform various database operations, including insert, update, delete, and query. It also supports transactions, ensuring data consistency and integrity.
LiteDB also offers advanced features such as indexing, full-text search, and file storage. Indexing can speed up queries, full-text search allows keyword searching in text data, and file storage enables storing files directly in the database.
The advantages of LiteDB include ease of use, lightweight nature, speed, and embeddability. Its codebase is very small and can be easily integrated into your application. Additionally, it is cross-platform, running on Windows, Linux, and Mac operating systems.
In summary, LiteDB is a simple and easy-to-use embedded database suitable for various applications. It offers a simple set of APIs for database operations and supports some advanced features. If you need a lightweight database solution, consider using LiteDB.
Encryption Encapsulation
Create a LiteDB.Service WebApi project.
Right-click to publish:

Create a console LiteDB.Launch project.
EntryPointDiscoverer.cs is used to find the entry method.
internal class EntryPointDiscoverer
{
public static MethodInfo FindStaticEntryMethod(Assembly assembly, string? entryPointFullTypeName = null)
{
var candidates = new List<MethodInfo>();
if (!string.IsNullOrWhiteSpace(entryPointFullTypeName))
{
var typeInfo = assembly.GetType(entryPointFullTypeName, false, false)?.GetTypeInfo();
if (typeInfo == null)
{
throw new InvalidProgramException($"Could not find '{entryPointFullTypeName}' specified for Main method. See <StartupObject> project property.");
}
FindMainMethodCandidates(typeInfo, candidates);
}
else
{
foreach (var type in assembly
.DefinedTypes
.Where(t => t.IsClass)
.Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() is null))
{
FindMainMethodCandidates(type, candidates);
}
}
string MainMethodFullName()
{
return string.IsNullOrWhiteSpace(entryPointFullTypeName) ? "Main" : $"{entryPointFullTypeName}.Main";
}
if (candidates.Count > 1)
{
throw new AmbiguousMatchException(
$"Ambiguous entry point. Found multiple static functions named '{MainMethodFullName()}'. Could not identify which method is the main entry point for this function.");
}
if (candidates.Count == 0)
{
throw new InvalidProgramException(
$"Could not find a static entry point '{MainMethodFullName()}'.");
}
return candidates[0];
}
private static void FindMainMethodCandidates(TypeInfo type, List<MethodInfo> candidates)
{
foreach (var method in type
.GetMethods(BindingFlags.Static |
BindingFlags.Public |
BindingFlags.NonPublic)
.Where(m =>
string.Equals("Main", m.Name, StringComparison.OrdinalIgnoreCase)))
{
if (method.ReturnType == typeof(void)
|| method.ReturnType == typeof(int)
|| method.ReturnType == typeof(Task)
|| method.ReturnType == typeof(Task<int>))
{
candidates.Add(method);
}
}
}
}
Then open the Program.cs file. Please note to modify the parameter of SaveDb to the path of your own packaged project.
// Used to package the specified program.
SaveDb(@"E:\Project\LiteDB-Application\LiteDB.Service\bin\Release\net7.0\publish");
// Open db
var db = new LiteDatabase("Launch.db");
// Open collection
var files = db.GetCollection<FileAssembly>("files");
// Handle assembly not found event
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
{
try
{
var name = eventArgs.Name.Split(",")[0];
if (!name.EndsWith(".dll"))
{
name += ".dll";
}
var file = files.FindOne(x => x.Name == name);
return file != null ? Assembly.Load(file.Bytes) : default;
}
catch (Exception)
{
return default;
}
};
// Start the program
StartServer("LiteDB.Service", new string[] { });
Console.ReadKey();
void StartServer(string assemblyName, string[] args)
{
var value = files!.FindOne(x => x.Name == assemblyName + ".dll");
var assembly = Assembly.Load(value!.Bytes);
var entryPoint = EntryPointDiscoverer.FindStaticEntryMethod(assembly);
try
{
var parameters = entryPoint.GetParameters();
if (parameters.Length != 0)
{
var parameterValues = parameters.Select(p =>
p.ParameterType.IsValueType ? Activator.CreateInstance(p.ParameterType) : null)
.ToArray();
entryPoint.Invoke(null, parameterValues);
}
else
{
entryPoint.Invoke(null, null);
}
}
catch (Exception e)
{
}
}
// Scan specified directory for all files and subdirectories, save to LiteDB database.
void SaveDb(string path)
{
var files = ScanDirectory(path);
using var db = new LiteDatabase("Launch.db");
var col = db.GetCollection<FileAssembly>("files");
col.InsertBulk(files);
}
// Implement a method to scan all files and subdirectories in the specified path and return a collection.
List<FileAssembly> ScanDirectory(string path)
{
var files = new List<FileAssembly>();
var dir = new DirectoryInfo(path);
var fileInfos = dir.GetFiles("*", SearchOption.AllDirectories);
foreach (var fileInfo in fileInfos)
{
var file = new FileAssembly
{
Name = fileInfo.Name,
Bytes = File.ReadAllBytes(fileInfo.FullName)
};
files.Add(file);
}
return files;
}
class FileAssembly
{
/// <summary>
/// File name
/// </summary>
public string Name { get; set; }
/// <summary>
/// File content
/// </summary>
public byte[] Bytes { get; set; }
}
Click on the LiteDB.Launch project file, add the LiteDB dependency, and change the SDK to Microsoft.NET.Sdk.Web.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LiteDB" Version="5.0.17" />
</ItemGroup>
</Project>
Before starting the project, first publish LiteDB.Service. Then modify the SaveDb parameter to the published directory (it will automatically scan all files and package them into the LiteDB file).
Then start the project.

When we start LiteDB.Launch, the StartServer method will open the created LiteDB file and search for the specified startup assembly.
Then, in AppDomain.CurrentDomain.AssemblyResolve, the missing assemblies of the startup assembly will be loaded into the domain.
AppDomain.CurrentDomain.AssemblyResolve is an event that is triggered when a dependency is not found.
When storing to LiteDB, the stored content can be encrypted, and then when the AppDomain.CurrentDomain.AssemblyResolve event is triggered, the content read from the LiteDB file can be decrypted.
Conclusion
Shared by token
QQ Tech Community: 737776595