Skip to content

Commit 22653d3

Browse files
authored
Feature/#163 documentation enhancement (#165)
* 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. * #163 Support UTF-8 and special character encryption Added `Example_6_Wokring_With_Special_Character_Text` to demonstrate encryption and decryption of text with special characters (e.g., emojis) using UTF-8 encoding. Updated `Program.cs` to include the new example and re-enable previously commented-out AES and RSA examples. Modified `BytesToString` and `StringToBytes` in `ExtShared.cs` to use UTF-8 encoding instead of ASCII for better handling of non-ASCII characters. Updated `migration.md` with a TODO note about encrypting strings with special characters and suggested using byte arrays for clarity. * #163 Refactor examples, docs, and improve developer tooling Refactored example methods to use PascalCase, added XML comments, and improved variable naming for clarity. Standardized key management APIs across AES, DSA, and RSA examples. Enhanced file encryption examples to support arbitrary file types. Updated documentation with detailed examples, migration guides, and a new `tooling.md` for developer workflows. Improved CI/CD documentation and reusable workflow examples in `CONTRIBUTING.md`. Added support for special characters in encryption examples and advanced PEM operations. Updated project structure to include a "Docs" project and additional documentation files. Enhanced code readability, consistency, and developer experience.
1 parent ca90f3c commit 22653d3

30 files changed

Lines changed: 1595 additions & 183 deletions

.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: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ contributors must follow to avoid common build and packaging failures.
1818

1919
### Example: Caller (no `runs-on`)
2020

21-
``` yaml
21+
~~~ yaml
2222
jobs:
2323
call-build:
2424
uses: ./.github/workflows/cd-build-test-pack.yml
2525
with:
2626
version: ${{ github.ref_name }}
2727
configuration: Release
28-
```
28+
~~~
2929

3030
### Example: Reusable Workflow
3131

32-
``` yaml
32+
~~~ yaml
3333
on:
3434
workflow_call:
3535
inputs:
@@ -47,8 +47,8 @@ jobs:
4747
steps:
4848
- name: Checkout
4949
uses: actions/checkout@v4
50-
#
51-
```
50+
#
51+
~~~
5252

5353
## Versioning and Git Tag Guidelines
5454

@@ -78,15 +78,15 @@ jobs:
7878

7979
### Sanitization Example
8080

81-
``` yaml
81+
~~~ yaml
8282
- name: Sanitize version
8383
id: sanitize
8484
run: |
8585
v="${{ inputs.version }}"
8686
v="${v#v}"
8787
v="${v#V}"
8888
echo "sanitized_version=$v" >> "$GITHUB_OUTPUT"
89-
```
89+
~~~
9090

9191
Use via: `${{ steps.sanitize.outputs.sanitized_version }}`
9292

@@ -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)