Skip to content

Commit 3a9be6e

Browse files
committed
feat: Add CryptoNet.Examples project with various encryption examples
- Introduced `Program.cs` to demonstrate DSA and AES examples. - Added test files for AES and RSA examples including `.docx`, `.pdf`, `.png`, and `.xlsx`. - Updated `CryptoNet.ExtPack` project to improve MD5 calculation and string comparison. - Modified solution file to include the new `CryptoNet.Examples` project. - Removed outdated contributing guidelines from `README.md`. - Deleted `RELEASE-NOTES` file as it was no longer needed. - Created various PowerShell scripts for build, code coverage, Docker setup, documentation generation, and NuGet validation. - Added migration guide for transitioning from CryptoNet v2.4.0 to v3.4.3, detailing breaking changes and updates. - Updated table of contents in documentation to include migration and examples sections.
1 parent ca90f3c commit 3a9be6e

26 files changed

+1316
-18
lines changed

.github/copilot-instructions.md

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# CryptoNet - AI Coding Agent Instructions
2+
3+
## Project Overview
4+
CryptoNet is a cross-platform .NET cryptography library providing RSA, AES, and DSA implementations. The core library targets .NET Standard 2.0 for maximum compatibility, while tests and examples use .NET 8.0.
5+
6+
## Architecture
7+
8+
### Project Structure
9+
- **CryptoNet** (netstandard2.0): Core library with `CryptoNetRsa`, `CryptoNetAes`, `CryptoNetDsa` classes
10+
- **CryptoNet.Models** (netstandard2.0): Shared models (`CryptoNetInfo`, `RsaDetail`, `AesDetail`, `DsaDetail`, `KeyType`, `EncryptionType`)
11+
- **CryptoNet.ExtShared** (netstandard2.0): Internal utilities for certificate handling and byte operations
12+
- **CryptoNet.ExtPack** (net8.0): Extension methods for MD5 hashing, PEM export, and content validation
13+
- **CryptoNet.UnitTests** (net8.0): NUnit tests with NUnit, Moq, Shouldly assertions
14+
15+
### Key Dependencies
16+
All projects use **Central Package Management** via `Directory.Packages.props`. Never add package versions directly to `.csproj` files—only add `<PackageReference Include="PackageName" />` without versions.
17+
18+
### NuGet Packaging Pattern
19+
The main `CryptoNet.csproj` uses `PrivateAssets="all"` for project references to `ExtShared` and `Models`, then explicitly includes their DLLs in the package via `IncludeReferencedDllsInPackage` target. This creates a self-contained NuGet package.
20+
21+
## Development Workflows
22+
23+
### Building & Testing
24+
```powershell
25+
# Standard build and test
26+
dotnet build
27+
dotnet test --configuration Release --no-build
28+
29+
# Code coverage with HTML report
30+
.\Scripts\run_codecoverage.ps1 # Runs tests, generates coverage, opens in Edge
31+
32+
# Docker build
33+
.\Scripts\run_docker_build.ps1
34+
# or: docker build . --file .\Dockerfile --tag cryptonet-service:latest
35+
```
36+
37+
### Documentation Generation
38+
Documentation uses **DocFX** to generate API docs from XML comments:
39+
```powershell
40+
.\Scripts\run_docs.ps1 # Cleans, builds, serves on localhost:8080
41+
42+
# Setup (one-time): dotnet tool install -g docfx
43+
```
44+
45+
The `index.md` is kept in sync with `README.md`:
46+
```powershell
47+
.\Scripts\run_update_index.ps1 # Adds YAML header and appends README content
48+
```
49+
50+
### Release Process
51+
Releases are tag-based with version format `vX.Y.Z` or `vX.Y.Z-previewYYYYMMDDHmm`:
52+
```powershell
53+
# Preview release
54+
.\Scripts\run_release.ps1 -VersionNumber 3.0.0 -IsPreview $true
55+
56+
# Production release
57+
.\Scripts\run_release.ps1 -VersionNumber 3.0.0 -IsPreview $false
58+
```
59+
60+
Pushing tags triggers GitHub Actions workflows (`cd-release.yml`, `cd-release-preview.yml`) that build, test, pack, and publish to NuGet.
61+
62+
## Coding Conventions
63+
64+
### Code Quality Standards
65+
- **Nullable reference types enabled**: Use `?` for nullable types, handle nulls explicitly
66+
- **TreatWarningsAsErrors**: All warnings are errors—code must be warning-free
67+
- **XML documentation required**: Public APIs must have `<summary>` tags (enforced by `GenerateDocumentationFile`)
68+
- **Deterministic builds**: `<Deterministic>true</Deterministic>` in `Directory.Build.Props`
69+
70+
### Interface Pattern
71+
All main crypto classes implement interfaces (`ICryptoNetRsa`, `ICryptoNetAes`, `ICryptoNetDsa`) which inherit from `ICryptoNet`. This base interface defines:
72+
```csharp
73+
CryptoNetInfo Info { get; }
74+
byte[] EncryptFromString(string content);
75+
string DecryptToString(byte[] bytes);
76+
byte[] EncryptFromBytes(byte[] bytes);
77+
byte[] DecryptToBytes(byte[] bytes);
78+
```
79+
80+
### Constructor Overloading Pattern
81+
Crypto classes follow a consistent constructor pattern:
82+
```csharp
83+
// Self-generated keys
84+
public CryptoNetRsa(int keySize = 2048)
85+
86+
// String key (XML or PEM)
87+
public CryptoNetRsa(string key, int keySize = 2048)
88+
89+
// File-based key
90+
public CryptoNetRsa(FileInfo fileInfo, int keySize = 2048)
91+
92+
// X509 certificate
93+
public CryptoNetRsa(X509Certificate2? certificate, KeyType keyType, int keySize = 2048)
94+
```
95+
96+
### Testing Patterns
97+
Tests use **NUnit** with **Shouldly** for assertions:
98+
```csharp
99+
result.ShouldBe(expected); // NOT Assert.AreEqual
100+
ExtensionPack.CheckContent(original, decrypted).ShouldBeTrue(); // MD5-based content comparison
101+
```
102+
103+
Test resource files are in `Resources/` with `<CopyToOutputDirectory>Always</CopyToOutputDirectory>`.
104+
105+
## Common Pitfalls
106+
107+
### Version Management
108+
- **Never** hardcode versions in individual `.csproj` files
109+
- Update versions in `Directory.Build.Props` (global) and `Directory.Packages.props` (package versions)
110+
- Release versions must match the format `^\d+\.\d+\.\d+$` in `run_release.ps1`
111+
112+
### Cross-Platform Compatibility
113+
- Core library must remain .NET Standard 2.0 compatible
114+
- Avoid .NET 8+ specific APIs in `CryptoNet`, `CryptoNet.Models`, `CryptoNet.ExtShared`
115+
- Use `System.Security.Cryptography` types from .NET Standard 2.0
116+
117+
### GitHub Actions Workflows
118+
- **Never add `runs-on` to caller jobs** when using reusable workflows (see `CONTRIBUTING.md`)
119+
- Reusable workflows declare `on: workflow_call` and define their own `runs-on`
120+
- Example: `cd-build-test-pack.yml` is a reusable workflow called by release workflows
121+
122+
### File Header Conventions
123+
All C# files include copyright headers:
124+
```csharp
125+
// <copyright file="FileName.cs" company="itbackyard" year="2021">
126+
// Copyright (c) 2021 All Rights Reserved
127+
// </copyright>
128+
// <author>Maytham Fahmi</author>
129+
// <date>DD-MM-YYYY HH:MM:SS</date>
130+
// <summary>part of CryptoNet project</summary>
131+
```
132+
133+
## Key Files
134+
- `Directory.Build.Props`: Global MSBuild properties (version, warnings, symbols)
135+
- `Directory.Packages.props`: Central package version management
136+
- `docfx.json`: DocFX configuration for API documentation
137+
- `RELEASE-NOTES`: Changelog file read during NuGet packing (see `PrepareReleaseNotes` target)
138+
- `coverlet.runsettings`: Code coverage configuration
139+
140+
## Development Tips
141+
- Use `ExtShared.LoadFileToString()` for reading key files consistently
142+
- Use `ExtensionPack.CheckContent()` for MD5-based content validation in tests
143+
- Key files are stored/loaded using `SaveKey(FileInfo, bool isPrivate)` and constructor overloads
144+
- The `Info` property exposes algorithm details, key types, and loaded keys for inspection
145+
146+
## Migration Guide: Old API → Latest CryptoNet v3+
147+
148+
### API Changes Summary
149+
- **Removed**: `ExportKey()`, `ExportKeyAndSave()` methods
150+
- **Replaced with**: `GetKey()` and `SaveKey()` methods
151+
- **Namespace change**: `CryptoNetUtils``ExtShared.ExtShared`
152+
- All crypto classes now expose `Info` property with algorithm details
153+
154+
### AES Examples
155+
156+
#### Old: Encrypt/Decrypt with Symmetric Key
157+
```csharp
158+
// OLD API (v2.x)
159+
ICryptoNet cryptoNet = new CryptoNetAes();
160+
var key = cryptoNet.ExportKey();
161+
ICryptoNet encryptClient = new CryptoNetAes(key);
162+
var encrypt = encryptClient.EncryptFromString(data);
163+
ICryptoNet decryptClient = new CryptoNetAes(key);
164+
var decrypt = decryptClient.DecryptToString(encrypt);
165+
```
166+
167+
#### New: Encrypt/Decrypt with Symmetric Key
168+
```csharp
169+
// NEW API (v3.x)
170+
ICryptoNetAes cryptoNet = new CryptoNetAes();
171+
var key = cryptoNet.GetKey(); // Changed from ExportKey()
172+
173+
ICryptoNetAes encryptClient = new CryptoNetAes(key);
174+
var encrypt = encryptClient.EncryptFromString(data);
175+
176+
ICryptoNetAes decryptClient = new CryptoNetAes(key);
177+
var decrypt = decryptClient.DecryptToString(encrypt);
178+
```
179+
180+
#### Old: Export and Import Symmetric Key from File
181+
```csharp
182+
// OLD API (v2.x)
183+
ICryptoNet cryptoNet = new CryptoNetAes();
184+
var file = new FileInfo("symmetric.key");
185+
cryptoNet.ExportKeyAndSave(file);
186+
var encrypt = cryptoNet.EncryptFromString(data);
187+
ICryptoNet cryptoNetImport = new CryptoNetAes(file);
188+
var decrypt = cryptoNetImport.DecryptToString(encrypt);
189+
```
190+
191+
#### New: Save and Load Symmetric Key from File
192+
```csharp
193+
// NEW API (v3.x)
194+
ICryptoNetAes cryptoNet = new CryptoNetAes();
195+
var file = new FileInfo("symmetric.key");
196+
cryptoNet.SaveKey(file); // Changed from ExportKeyAndSave()
197+
198+
var encrypt = cryptoNet.EncryptFromString(data);
199+
200+
ICryptoNetAes cryptoNetImport = new CryptoNetAes(file);
201+
var decrypt = cryptoNetImport.DecryptToString(encrypt);
202+
```
203+
204+
### RSA Examples
205+
206+
#### Old: Generate RSA Key Pair and Save
207+
```csharp
208+
// OLD API (v2.x)
209+
ICryptoNet cryptoNet = new CryptoNetRsa();
210+
cryptoNet.ExportKeyAndSave(new FileInfo("private.key"), true);
211+
cryptoNet.ExportKeyAndSave(new FileInfo("public.key"), false);
212+
ICryptoNet pubKeyCrypto = new CryptoNetRsa(new FileInfo("public.key"));
213+
var encrypt = pubKeyCrypto.EncryptFromString(data);
214+
ICryptoNet priKeyCrypto = new CryptoNetRsa(new FileInfo("private.key"));
215+
var decrypt = priKeyCrypto.DecryptToString(encrypt);
216+
```
217+
218+
#### New: Generate RSA Key Pair and Save
219+
```csharp
220+
// NEW API (v3.x)
221+
ICryptoNetRsa cryptoNet = new CryptoNetRsa();
222+
cryptoNet.SaveKey(new FileInfo("private.key"), true); // Changed from ExportKeyAndSave()
223+
cryptoNet.SaveKey(new FileInfo("public.key"), false); // Changed from ExportKeyAndSave()
224+
225+
ICryptoNetRsa pubKeyCrypto = new CryptoNetRsa(new FileInfo("public.key"));
226+
var encrypt = pubKeyCrypto.EncryptFromString(data);
227+
228+
ICryptoNetRsa priKeyCrypto = new CryptoNetRsa(new FileInfo("private.key"));
229+
var decrypt = priKeyCrypto.DecryptToString(encrypt);
230+
```
231+
232+
### X509 Certificate Examples
233+
234+
#### Old: Use X509 Certificate for Encryption
235+
```csharp
236+
// OLD API (v2.x)
237+
X509Certificate2? cert = CryptoNetUtils.GetCertificateFromStore("CN=Maytham");
238+
ICryptoNet publicKeyCrypto = new CryptoNetRsa(cert, KeyType.PublicKey);
239+
var encrypt = publicKeyCrypto.EncryptFromString(data);
240+
ICryptoNet privateKeyCrypto = new CryptoNetRsa(cert, KeyType.PrivateKey);
241+
var decrypt = privateKeyCrypto.DecryptToString(encrypt);
242+
```
243+
244+
#### New: Use X509 Certificate for Encryption
245+
```csharp
246+
// NEW API (v3.x)
247+
using CryptoNet.ExtShared; // Namespace change: CryptoNetUtils → ExtShared
248+
249+
X509Certificate2? cert = ExtShared.GetCertificateFromStore("CN=Maytham"); // Changed from CryptoNetUtils
250+
251+
ICryptoNetRsa publicKeyCrypto = new CryptoNetRsa(cert, KeyType.PublicKey);
252+
var encrypt = publicKeyCrypto.EncryptFromString(data);
253+
254+
ICryptoNetRsa privateKeyCrypto = new CryptoNetRsa(cert, KeyType.PrivateKey);
255+
var decrypt = privateKeyCrypto.DecryptToString(encrypt);
256+
```
257+
258+
### Key Migration Points
259+
1. **Method renames**: `ExportKey()``GetKey()`, `ExportKeyAndSave()``SaveKey()`
260+
2. **Namespace**: `CryptoNetUtils``CryptoNet.ExtShared.ExtShared`
261+
3. **Interface specificity**: Prefer `ICryptoNetRsa`, `ICryptoNetAes`, `ICryptoNetDsa` over generic `ICryptoNet`
262+
4. **Info property**: Access algorithm details via `cryptoNet.Info` (includes key types, sizes, loaded keys)
263+
5. **File operations**: Both `FileInfo` and `string` filename overloads available for `SaveKey()`

CONTRIBUTING.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
steps:
4848
- name: Checkout
4949
uses: actions/checkout@v4
50-
#
50+
#
5151
```
5252

5353
## Versioning and Git Tag Guidelines
@@ -98,3 +98,15 @@ Use via: `${{ steps.sanitize.outputs.sanitized_version }}`
9898
## Maintenance
9999

100100
- Keep conventions aligned with GitHub Actions and NuGet rules.
101+
102+
## Contributing
103+
104+
You are more than welcome to contribute in one of the following ways:
105+
106+
1. Basic: Give input, and suggestions for improvement by creating an issue and labeling it https://github.com/itbackyard/CryptoNet/issues
107+
2. Advance: if you have good knowledge of C# and Cryptography just grab one of the issues, or features, or create a new one and refactor and add a pull request.
108+
3. Documentation: Add, update, or improve documentation, by making a pull request.
109+
110+
### How to contribute:
111+
112+
[Here](https://www.dataschool.io/how-to-contribute-on-github/) is a link to learn how to contribute if you are not aware of how to do it.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="CryptoNet" Version="3.4.3" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<None Update="TestFiles\test.docx">
16+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
17+
</None>
18+
<None Update="TestFiles\test.pdf">
19+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
20+
</None>
21+
<None Update="TestFiles\test.png">
22+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
23+
</None>
24+
<None Update="TestFiles\test.xlsx">
25+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
26+
</None>
27+
</ItemGroup>
28+
29+
</Project>

0 commit comments

Comments
 (0)