Skip to content

Commit

Permalink
Version2 (#18)
Browse files Browse the repository at this point in the history
* !!! Breaking Change Version 2.0 !!!

* #16 give posiblity of customize store location and name.

* #20 RSA refactoring

* #19 Introduce AES encryption

Co-authored-by: Maytham Fahmi <maythamfahmi@nextbix.dk>
  • Loading branch information
Maytham Fahmi and maythamfahmi authored May 21, 2022
1 parent 4e8c727 commit c9b2b38
Show file tree
Hide file tree
Showing 27 changed files with 1,251 additions and 973 deletions.
88 changes: 88 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
[*.cs]

# CA1507: Use nameof to express symbol names
dotnet_diagnostic.CA1507.severity = none
csharp_indent_labels = one_less_than_current
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_space_around_binary_operators = before_and_after

# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
dotnet_diagnostic.CS8618.severity = none

[*.{cs,vb}]
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
[*.{cs,vb}]
#### Naming styles ####

# Naming rules

dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i

dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case

# Symbol specifications

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =

dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =

# Naming styles

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_diagnostic.CA2208.severity = silent

# IDE0017: Simplify object initialization
dotnet_diagnostic.IDE0017.severity = none

# IDE0063: Use simple 'using' statement
dotnet_diagnostic.IDE0063.severity = none

# IDE0090: Use 'new(...)'
dotnet_diagnostic.IDE0090.severity = none
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ADotNet" Version="2.0.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CryptoNetLib\CryptoNetLib.csproj" />
<ProjectReference Include="..\CryptoNet\CryptoNet.csproj" />
</ItemGroup>

</Project>
119 changes: 119 additions & 0 deletions CryptoNet.Cli/ExampleAes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// <copyright file="ExampleAes.cs" company="NextBix" year="2021">
// Copyright (c) 2021 All Rights Reserved
// </copyright>
// <author>Maytham Fahmi</author>
// <date>17-12-2021 12:18:44</date>
// <summary>part of CryptoNet project</summary>

using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using CryptoNet.Models;

namespace CryptoNet.Cli;

public class ExampleAes
{
private const string ConfidentialDummyData = @"Some Secret Data";

private static readonly string BaseFolder = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string SymmetricKeyFile = Path.Combine(BaseFolder, $"{KeyType.SymmetricKey}.xml");

public static void Test()
{
Example_1_Encrypt_Decrypt_Content_With_SelfGenerated_SymmetricKey();
Example_2_SelfGenerated_And_Save_SymmetricKey();
Example_3_Encrypt_Decrypt_Content_With_Own_SymmetricKey();
Example_4_Encrypt_Decrypt_Content_With_Human_Readable_Key_Secret_SymmetricKey();
}

public static void Example_1_Encrypt_Decrypt_Content_With_SelfGenerated_SymmetricKey()
{
ICryptoNet cryptoNet = new CryptoNetAes();
var key = cryptoNet.ExportKey();

ICryptoNet encryptClient = new CryptoNetAes(key);
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);

ICryptoNet decryptClient = new CryptoNetAes(key);
var decrypt = decryptClient.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static void Example_2_SelfGenerated_And_Save_SymmetricKey()
{
ICryptoNet cryptoNet = new CryptoNetAes();
var file = new FileInfo(SymmetricKeyFile);
cryptoNet.ExportKeyAndSave(file);

Debug.Assert(File.Exists(file.FullName));

var encrypt = cryptoNet.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNetKeyImport = new CryptoNetAes(file);
var decrypt = cryptoNetKeyImport.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static void Example_3_Encrypt_Decrypt_Content_With_Own_SymmetricKey()
{
var symmetricKey = "12345678901234567890123456789012";
if (symmetricKey.Length != 32)
{
Console.WriteLine("key should be 32 character long");
Environment.Exit(0);
}

var secret = "1234567890123456";
if (secret.Length != 16)
{
Console.WriteLine("key should be 16 character long");
Environment.Exit(1);
}

var key = Encoding.UTF8.GetBytes(symmetricKey);
var iv = Encoding.UTF8.GetBytes(secret);

ICryptoNet encryptClient = new CryptoNetAes(key, iv);
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);

ICryptoNet decryptClient = new CryptoNetAes(key, iv);
var decrypt = decryptClient.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static void Example_4_Encrypt_Decrypt_Content_With_Human_Readable_Key_Secret_SymmetricKey()
{
var symmetricKey = UniqueKeyGenerator("symmetricKey");
var secret = new string(UniqueKeyGenerator("password").Take(16).ToArray());

var key = Encoding.UTF8.GetBytes(symmetricKey);
var iv = Encoding.UTF8.GetBytes(secret);

ICryptoNet encryptClient = new CryptoNetAes(key, iv);
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);

ICryptoNet decryptClient = new CryptoNetAes(key, iv);
var decrypt = decryptClient.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static string UniqueKeyGenerator(string input)
{
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);

StringBuilder sb = new StringBuilder();
foreach (var t in hash)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}

}
135 changes: 135 additions & 0 deletions CryptoNet.Cli/ExampleRsa.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// <copyright file="ExampleRsa.cs" company="NextBix" year="2021">
// Copyright (c) 2021 All Rights Reserved
// </copyright>
// <author>Maytham Fahmi</author>
// <date>17-12-2021 12:18:44</date>
// <summary>part of CryptoNet project</summary>

using System.Diagnostics;
using System.Security.Cryptography.X509Certificates;
using CryptoNet.Models;
using CryptoNet.Utils;

namespace CryptoNet.Cli;

public class ExampleRsa
{
private const string ConfidentialDummyData = @"Some Secret Data";

private static readonly string BaseFolder = AppDomain.CurrentDomain.BaseDirectory;

internal static string PrivateKeyFile = Path.Combine(BaseFolder, "privateKey");
internal static string PublicKeyFile = Path.Combine(BaseFolder, "publicKey.pub");

public static void Test()
{
Example_1_Encrypt_Decrypt_Content_With_SelfGenerated_AsymmetricKey();
Example_2_SelfGenerated_And_Save_AsymmetricKey();
Example_3_Encrypt_With_PublicKey_Decrypt_With_PrivateKey_Of_Content();
Example_4_Using_X509_Certificate();
Example_5_Export_Public_Key_For_X509_Certificate();
Example_7_Customize();
}

public static void Example_1_Encrypt_Decrypt_Content_With_SelfGenerated_AsymmetricKey()
{
ICryptoNet cryptoNet = new CryptoNetRsa();

var privateKey = cryptoNet.ExportKey(true);
var publicKey = cryptoNet.ExportKey(false);

ICryptoNet encryptClient = new CryptoNetRsa(publicKey);
var encrypt = encryptClient.EncryptFromString(ConfidentialDummyData);

ICryptoNet decryptClient = new CryptoNetRsa(privateKey);
var decrypt = decryptClient.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static void Example_2_SelfGenerated_And_Save_AsymmetricKey()
{
ICryptoNet cryptoNet = new CryptoNetRsa();

cryptoNet.ExportKeyAndSave(new FileInfo(PrivateKeyFile), true);
cryptoNet.ExportKeyAndSave(new FileInfo(PublicKeyFile), false);

Debug.Assert(File.Exists(new FileInfo(PrivateKeyFile).FullName));
Debug.Assert(File.Exists(new FileInfo(PublicKeyFile).FullName));

ICryptoNet cryptoNetPubKey = new CryptoNetRsa(new FileInfo(PublicKeyFile));
var encrypt = cryptoNetPubKey.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNetPriKey = new CryptoNetRsa(new FileInfo(PrivateKeyFile));
var decrypt = cryptoNetPriKey.DecryptToString(encrypt);

Debug.Assert(ConfidentialDummyData == decrypt);
}

public static void Example_3_Encrypt_With_PublicKey_Decrypt_With_PrivateKey_Of_Content()
{
ICryptoNet cryptoNetWithPublicKey = new CryptoNetRsa(new FileInfo(PublicKeyFile));
var encryptWithPublicKey = cryptoNetWithPublicKey.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNetWithPrivateKey = new CryptoNetRsa(new FileInfo(PrivateKeyFile));
var decryptWithPrivateKey = cryptoNetWithPrivateKey.DecryptToString(encryptWithPublicKey);

Debug.Assert(ConfidentialDummyData == decryptWithPrivateKey);
}

public static void Example_4_Using_X509_Certificate()
{
// Find and replace CN=Maytham with your own certificate
X509Certificate2? certificate = CryptoNetUtils.GetCertificateFromStore("CN=Maytham");

ICryptoNet cryptoNetWithPublicKey = new CryptoNetRsa(certificate, KeyType.PublicKey);
var encryptWithPublicKey = cryptoNetWithPublicKey.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNetWithPrivateKey = new CryptoNetRsa(certificate, KeyType.PrivateKey);
var decryptWithPrivateKey = cryptoNetWithPrivateKey.DecryptToString(encryptWithPublicKey);

Debug.Assert(ConfidentialDummyData == decryptWithPrivateKey);
}

public static void Example_5_Export_Public_Key_For_X509_Certificate()
{
// Find and replace CN=Maytham with your own certificate
X509Certificate2? certificate = CryptoNetUtils.GetCertificateFromStore("CN=Maytham");

ICryptoNet cryptoNetWithPublicKey = new CryptoNetRsa(certificate, KeyType.PublicKey);
var publicKey = cryptoNetWithPublicKey.ExportKey(false);

Debug.Assert(!string.IsNullOrEmpty(publicKey));
}

/// <summary>
/// CryptoNet interact with .net 5/6 for customization, like import/export PEM
/// Work in Progress, not finished
/// </summary>
public static void Example_7_Customize()
{
X509Certificate2? cert = CryptoNetUtils.GetCertificateFromStore("CN=Maytham");

var pubKeyPem = CryptoNetUtils.ExportPemKey(cert!, false);
var priKeyPem = CryptoNetUtils.ExportPemKey(cert!);

var password = "password";
var encryptedPriKeyBytes = CryptoNetUtils.ExportPemKeyWithPassword(cert!, password);

ICryptoNet cryptoNet1 = CryptoNetUtils.ImportPemKeyWithPassword(encryptedPriKeyBytes, password);
var encrypt1 = cryptoNet1.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNet2 = CryptoNetUtils.ImportPemKey(pubKeyPem);
var encrypt2 = cryptoNet2.EncryptFromString(ConfidentialDummyData);

ICryptoNet cryptoNet3 = CryptoNetUtils.ImportPemKey(priKeyPem);
var decrypt2 = cryptoNet3.DecryptToString(encrypt2);

Debug.Assert(ConfidentialDummyData == decrypt2);

var decrypt1 = cryptoNet3.DecryptToString(encrypt1);

Debug.Assert(ConfidentialDummyData == decrypt1);
}

}
18 changes: 18 additions & 0 deletions CryptoNet.Cli/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// <copyright file="Program.cs" company="NextBix" year="2021">
// Copyright (c) 2021 All Rights Reserved
// </copyright>
// <author>Maytham Fahmi</author>
// <date>17-12-2021 12:18:44</date>
// <summary>part of CryptoNet project</summary>

namespace CryptoNet.Cli
{
internal class Program
{
public static void Main()
{
ExampleAes.Test();
ExampleRsa.Test();
}
}
}
Loading

0 comments on commit c9b2b38

Please sign in to comment.