Skip to content

Commit be41d41

Browse files
committed
#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 f3b8fb3 commit be41d41

File tree

12 files changed

+585
-475
lines changed

12 files changed

+585
-475
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 6 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:
@@ -48,7 +48,7 @@ jobs:
4848
- name: Checkout
4949
uses: actions/checkout@v4
5050
#
51-
```
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

CryptoNet.Examples/ExampleAes.cs

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,119 +12,146 @@
1212

1313
namespace CryptoNet.Examples;
1414

15+
/// <summary>
16+
/// Example usage scenarios for AES symmetric encryption using the CryptoNet library.
17+
/// Demonstrates generating, saving/loading symmetric keys and encrypting/decrypting
18+
/// both content and files.
19+
/// </summary>
1520
public static class ExampleAes
1621
{
1722
private const string ConfidentialDummyData = @"Some Secret Data";
1823

19-
private static readonly string BaseFolder = AppDomain.CurrentDomain.BaseDirectory;
20-
private readonly static string SymmetricKeyFile = Path.Combine(BaseFolder, $"{KeyType.SymmetricKey}.xml");
24+
private static readonly string BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
25+
private static readonly string SymmetricKeyFilePath = Path.Combine(BaseDirectory, $"{KeyType.SymmetricKey}.xml");
2126

22-
public static void Example_1_Encrypt_Decrypt_Content_With_SelfGenerated_SymmetricKey()
27+
/// <summary>
28+
/// Generate a symmetric key, encrypt and decrypt a string using self-generated key.
29+
/// </summary>
30+
public static void EncryptDecryptWithSelfGeneratedSymmetricKey()
2331
{
2432
ICryptoNetAes cryptoNet = new CryptoNetAes();
25-
var key = cryptoNet.GetKey();
33+
string key = cryptoNet.GetKey();
2634

2735
ICryptoNet encryptClient = new CryptoNetAes(key);
28-
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);
36+
byte[] encrypted = encryptClient.EncryptFromString(ConfidentialDummyData);
2937

3038
ICryptoNet decryptClient = new CryptoNetAes(key);
31-
var decrypt = decryptClient.DecryptToString(encrypt);
39+
string decrypted = decryptClient.DecryptToString(encrypted);
3240

33-
Debug.Assert(ConfidentialDummyData == decrypt);
41+
Debug.Assert(ConfidentialDummyData == decrypted);
3442
}
3543

36-
public static void Example_2_SelfGenerated_And_Save_SymmetricKey()
44+
/// <summary>
45+
/// Generate a symmetric key and save it to disk, then load it to decrypt previously encrypted content.
46+
/// </summary>
47+
public static void GenerateAndSaveSymmetricKey()
3748
{
3849
ICryptoNetAes cryptoNet = new CryptoNetAes();
39-
var file = new FileInfo(SymmetricKeyFile);
40-
cryptoNet.SaveKey(file);
50+
FileInfo keyFile = new FileInfo(SymmetricKeyFilePath);
51+
cryptoNet.SaveKey(keyFile);
4152

42-
Debug.Assert(File.Exists(file.FullName));
53+
Debug.Assert(File.Exists(keyFile.FullName));
4354

44-
var encrypt = cryptoNet.EncryptFromString(ConfidentialDummyData);
55+
byte[] encrypted = cryptoNet.EncryptFromString(ConfidentialDummyData);
4556

46-
ICryptoNet cryptoNetKeyImport = new CryptoNetAes(file);
47-
var decrypt = cryptoNetKeyImport.DecryptToString(encrypt);
57+
ICryptoNet cryptoNetImported = new CryptoNetAes(keyFile);
58+
string decrypted = cryptoNetImported.DecryptToString(encrypted);
4859

49-
Debug.Assert(ConfidentialDummyData == decrypt);
60+
Debug.Assert(ConfidentialDummyData == decrypted);
5061
}
5162

52-
public static void Example_3_Encrypt_Decrypt_Content_With_Own_SymmetricKey()
63+
/// <summary>
64+
/// Encrypt and decrypt using a provided raw symmetric key and IV.
65+
/// </summary>
66+
public static void EncryptDecryptWithProvidedSymmetricKey()
5367
{
54-
var symmetricKey = "12345678901234567890123456789012";
68+
string symmetricKey = "12345678901234567890123456789012";
5569
if (symmetricKey.Length != 32)
5670
{
57-
Console.WriteLine("key should be 32 character long");
71+
Console.WriteLine("Key should be 32 characters long");
5872
Environment.Exit(0);
5973
}
6074

61-
var secret = "1234567890123456";
75+
string secret = "1234567890123456";
6276
if (secret.Length != 16)
6377
{
64-
Console.WriteLine("key should be 16 character long");
78+
Console.WriteLine("IV should be 16 characters long");
6579
Environment.Exit(1);
6680
}
6781

68-
var key = Encoding.UTF8.GetBytes(symmetricKey);
69-
var iv = Encoding.UTF8.GetBytes(secret);
82+
byte[] key = Encoding.UTF8.GetBytes(symmetricKey);
83+
byte[] iv = Encoding.UTF8.GetBytes(secret);
7084

7185
ICryptoNet encryptClient = new CryptoNetAes(key, iv);
72-
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);
86+
byte[] encrypted = encryptClient.EncryptFromString(ConfidentialDummyData);
7387

7488
ICryptoNet decryptClient = new CryptoNetAes(key, iv);
75-
var decrypt = decryptClient.DecryptToString(encrypt);
89+
string decrypted = decryptClient.DecryptToString(encrypted);
7690

77-
Debug.Assert(ConfidentialDummyData == decrypt);
91+
Debug.Assert(ConfidentialDummyData == decrypted);
7892
}
7993

80-
public static void Example_4_Encrypt_Decrypt_Content_With_Human_Readable_Key_Secret_SymmetricKey()
94+
/// <summary>
95+
/// Generate a human-readable key/secret pair and use them for encryption/decryption.
96+
/// </summary>
97+
public static void EncryptDecryptWithHumanReadableKeySecret()
8198
{
82-
var symmetricKey = UniqueKeyGenerator("symmetricKey");
83-
var secret = new string(UniqueKeyGenerator("password").Take(16).ToArray());
99+
string symmetricKey = GenerateUniqueKey("symmetricKey");
100+
string secret = new string(GenerateUniqueKey("password").Take(16).ToArray());
84101

85-
var key = Encoding.UTF8.GetBytes(symmetricKey);
86-
var iv = Encoding.UTF8.GetBytes(secret);
102+
byte[] key = Encoding.UTF8.GetBytes(symmetricKey);
103+
byte[] iv = Encoding.UTF8.GetBytes(secret);
87104

88105
ICryptoNet encryptClient = new CryptoNetAes(key, iv);
89-
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);
106+
byte[] encrypted = encryptClient.EncryptFromString(ConfidentialDummyData);
90107

91108
ICryptoNet decryptClient = new CryptoNetAes(key, iv);
92-
var decrypt = decryptClient.DecryptToString(encrypt);
109+
string decrypted = decryptClient.DecryptToString(encrypted);
93110

94-
Debug.Assert(ConfidentialDummyData == decrypt);
111+
Debug.Assert(ConfidentialDummyData == decrypted);
95112
}
96113

97-
public static void Example_5_Encrypt_And_Decrypt_File_With_SymmetricKey_Test(string filename)
114+
/// <summary>
115+
/// Encrypt and decrypt a file using a self-generated symmetric key and verify content equality.
116+
/// </summary>
117+
/// <param name="filename">Relative path under TestFiles directory to the file to encrypt.</param>
118+
public static void EncryptAndDecryptFileWithSymmetricKeyTest(string filename)
98119
{
99120
ICryptoNetAes cryptoNet = new CryptoNetAes();
100-
var key = cryptoNet.GetKey();
121+
string key = cryptoNet.GetKey();
101122

102-
FileInfo fi = new FileInfo(filename);
123+
FileInfo fileInfo = new FileInfo(filename);
103124

104125
ICryptoNet encryptClient = new CryptoNetAes(key);
105-
string pdfFilePath = Path.Combine(BaseFolder, filename);
106-
byte[] pdfFileBytes = File.ReadAllBytes(pdfFilePath);
107-
var encrypt = encryptClient.EncryptFromBytes(pdfFileBytes);
126+
string sourceFilePath = Path.Combine(BaseDirectory, filename);
127+
byte[] fileBytes = File.ReadAllBytes(sourceFilePath);
128+
byte[] encrypted = encryptClient.EncryptFromBytes(fileBytes);
108129

109130
ICryptoNet decryptClient = new CryptoNetAes(key);
110-
var decrypt = decryptClient.DecryptToBytes(encrypt);
111-
string pdfDecryptedFilePath = $"TestFiles\\{Path.GetFileNameWithoutExtension(fi.Name)}-decrypted.{fi.Extension}";
112-
File.WriteAllBytes(pdfDecryptedFilePath, decrypt);
131+
byte[] decrypted = decryptClient.DecryptToBytes(encrypted);
132+
string decryptedFilePath = $"TestFiles\\{Path.GetFileNameWithoutExtension(fileInfo.Name)}-decrypted{fileInfo.Extension}";
133+
File.WriteAllBytes(decryptedFilePath, decrypted);
113134

114-
var isIdenticalFile = ExtShared.ExtShared.ByteArrayCompare(pdfFileBytes, decrypt);
135+
bool isIdenticalFile = ExtShared.ExtShared.ByteArrayCompare(fileBytes, decrypted);
115136
Debug.Assert(isIdenticalFile);
116137
}
117138

118-
public static string UniqueKeyGenerator(string input)
139+
/// <summary>
140+
/// Create a deterministic unique key string from input using MD5 (example helper).
141+
/// </summary>
142+
/// <param name="input">Input string to derive the key from.</param>
143+
/// <returns>Hexadecimal string representation of MD5 hash.</returns>
144+
public static string GenerateUniqueKey(string input)
119145
{
120146
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
121147
byte[] hash = MD5.HashData(inputBytes);
122148

123149
StringBuilder sb = new StringBuilder();
124-
foreach (var t in hash)
150+
foreach (byte b in hash)
125151
{
126-
sb.Append(t.ToString("X2"));
152+
sb.Append(b.ToString("X2"));
127153
}
154+
128155
return sb.ToString();
129156
}
130157
}

CryptoNet.Examples/ExampleDsa.cs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,57 @@
1313

1414
namespace CryptoNet.Examples;
1515

16+
/// <summary>
17+
/// Example usage scenarios for DSA operations using the CryptoNet library.
18+
/// Demonstrates signing, verification and saving/loading DSA keys.
19+
/// </summary>
1620
public static class ExampleDsa
1721
{
1822
private const string ConfidentialDummyData = @"Some Secret Data";
19-
private static readonly string BaseFolder = AppDomain.CurrentDomain.BaseDirectory;
23+
private static readonly string BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
2024

21-
internal static readonly string PrivateKeyFile = Path.Combine(BaseFolder, "privateKey");
22-
internal static readonly string PublicKeyFile = Path.Combine(BaseFolder, "publicKey.pub");
25+
internal static readonly string PrivateKeyFilePath = Path.Combine(BaseDirectory, "privateKey");
26+
internal static readonly string PublicKeyFilePath = Path.Combine(BaseDirectory, "publicKey.pub");
2327

24-
public static void Example_1_Sign_Validate_Content_With_SelfGenerated_AsymmetricKey()
28+
/// <summary>
29+
/// Demonstrates signing content with a self-generated DSA key and validating the signature.
30+
/// </summary>
31+
public static void SignAndValidateWithSelfGeneratedKey()
2532
{
2633
ICryptoNetDsa client = new CryptoNetDsa();
27-
var privateKey = client.GetKey(true);
34+
string privateKeyXml = client.GetKey(true);
2835

29-
ICryptoNetDsa signatureClient = new CryptoNetDsa(privateKey);
30-
var signature = signatureClient.CreateSignature(ConfidentialDummyData);
36+
ICryptoNetDsa signatureClient = new CryptoNetDsa(privateKeyXml);
37+
byte[] signature = signatureClient.CreateSignature(ConfidentialDummyData);
3138

32-
ICryptoNetDsa verifyClient = new CryptoNetDsa(privateKey);
33-
var confidentialAsBytes = ExtShared.ExtShared.StringToBytes(ConfidentialDummyData);
39+
ICryptoNetDsa verifyClient = new CryptoNetDsa(privateKeyXml);
40+
byte[] contentBytes = ExtShared.ExtShared.StringToBytes(ConfidentialDummyData);
3441

35-
bool isVerified = verifyClient.IsContentVerified(confidentialAsBytes, signature);
42+
bool isVerified = verifyClient.IsContentVerified(contentBytes, signature);
3643

3744
Debug.Assert(isVerified == true);
3845
}
3946

40-
public static void Example_2_SelfGenerated_And_Save_AsymmetricKey()
47+
/// <summary>
48+
/// Demonstrates generating DSA key pair, saving them to files, and verifying signatures using loaded keys.
49+
/// </summary>
50+
public static void GenerateAndSaveDsaKeyPair()
4151
{
4252
ICryptoNetDsa cryptoNet = new CryptoNetDsa();
4353

44-
cryptoNet.SaveKey(new FileInfo(PrivateKeyFile), true);
45-
cryptoNet.SaveKey(new FileInfo(PublicKeyFile), false);
54+
cryptoNet.SaveKey(new FileInfo(PrivateKeyFilePath), true);
55+
cryptoNet.SaveKey(new FileInfo(PublicKeyFilePath), false);
4656

47-
Debug.Assert(File.Exists(new FileInfo(PrivateKeyFile).FullName));
48-
Debug.Assert(File.Exists(new FileInfo(PublicKeyFile).FullName));
57+
Debug.Assert(File.Exists(new FileInfo(PrivateKeyFilePath).FullName));
58+
Debug.Assert(File.Exists(new FileInfo(PublicKeyFilePath).FullName));
4959

50-
ICryptoNetDsa dsaWithPrivateKey = new CryptoNetDsa(new FileInfo(PrivateKeyFile));
51-
var signature = dsaWithPrivateKey.CreateSignature(ConfidentialDummyData);
60+
ICryptoNetDsa dsaWithPrivateKey = new CryptoNetDsa(new FileInfo(PrivateKeyFilePath));
61+
byte[] signature = dsaWithPrivateKey.CreateSignature(ConfidentialDummyData);
5262

53-
ICryptoNetDsa dsaWithPublicKey = new CryptoNetDsa(new FileInfo(PublicKeyFile));
54-
var confidentialAsBytes = ExtShared.ExtShared.StringToBytes(ConfidentialDummyData);
55-
var isVerified = dsaWithPublicKey.IsContentVerified(confidentialAsBytes, signature);
63+
ICryptoNetDsa dsaWithPublicKey = new CryptoNetDsa(new FileInfo(PublicKeyFilePath));
64+
byte[] confidentialBytes = ExtShared.ExtShared.StringToBytes(ConfidentialDummyData);
65+
bool isVerified = dsaWithPublicKey.IsContentVerified(confidentialBytes, signature);
5666

5767
Debug.Assert(isVerified == true);
5868
}
59-
6069
}

0 commit comments

Comments
 (0)