Created
September 29, 2023 17:03
-
-
Save ddjerqq/435981a8b15557560ffcad100c34adae to your computer and use it in GitHub Desktop.
C# implementation and easy abstraction for RSA cryptographic encryption algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Cryptography; | |
using Newtonsoft.Json; | |
namespace Crypto; | |
public struct PrivateKey | |
{ | |
private byte[] D { get; init; } | |
private byte[] P { get; init; } | |
private byte[] Q { get; init; } | |
private byte[] Dp { get; init; } | |
private byte[] Dq { get; init; } | |
private byte[] InverseQ { get; init; } | |
private byte[] Modulus { get; init; } | |
private byte[] Exponent { get; init; } | |
public static implicit operator string(PrivateKey privateKey) | |
=> JsonConvert.SerializeObject(privateKey, Formatting.None); | |
public static implicit operator PrivateKey(string json) | |
=> JsonConvert.DeserializeObject<PrivateKey>(json); | |
public static implicit operator RSAParameters(PrivateKey privateKey) | |
{ | |
return new RSAParameters | |
{ | |
D = privateKey.D, | |
P = privateKey.P, | |
Q = privateKey.Q, | |
DP = privateKey.Dp, | |
DQ = privateKey.Dq, | |
InverseQ = privateKey.InverseQ, | |
Modulus = privateKey.Modulus, | |
Exponent = privateKey.Exponent, | |
}; | |
} | |
public static implicit operator PrivateKey(RSAParameters rsaParameters) | |
{ | |
return new PrivateKey | |
{ | |
D = rsaParameters.D!, | |
P = rsaParameters.P!, | |
Q = rsaParameters.Q!, | |
Dp = rsaParameters.DP!, | |
Dq = rsaParameters.DQ!, | |
InverseQ = rsaParameters.InverseQ!, | |
Modulus = rsaParameters.Modulus!, | |
Exponent = rsaParameters.Exponent!, | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Cryptography; | |
using Newtonsoft.Json; | |
namespace Crypto; | |
public struct PublicKey | |
{ | |
private byte[] Modulus { get; init; } | |
private byte[] Exponent { get; init; } | |
public static implicit operator string(PublicKey privateKey) | |
=> JsonConvert.SerializeObject(privateKey, Formatting.None); | |
public static implicit operator PublicKey(string json) | |
=> JsonConvert.DeserializeObject<PublicKey>(json); | |
public static implicit operator RSAParameters(PublicKey publicKey) | |
{ | |
return new RSAParameters | |
{ | |
Modulus = publicKey.Modulus, | |
Exponent = publicKey.Exponent, | |
}; | |
} | |
public static implicit operator PublicKey(RSAParameters rsaParameters) | |
{ | |
return new PublicKey | |
{ | |
Modulus = rsaParameters.Modulus!, | |
Exponent = rsaParameters.Exponent!, | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Cryptography; | |
using System.Text; | |
using Newtonsoft.Json; | |
using NUnit.Framework; | |
namespace Crypto; | |
public static class Rsa | |
{ | |
public static (PrivateKey, PublicKey) GenerateKeyPair(int keySize) | |
{ | |
using var rsa = RSA.Create(keySize); | |
return (rsa.ExportParameters(true), rsa.ExportParameters(false)); | |
} | |
public static byte[] Encrypt(byte[] data, PublicKey pKey, RSAEncryptionPadding? padding = default) | |
{ | |
padding ??= RSAEncryptionPadding.OaepSHA512; | |
using var rsa = RSA.Create(); | |
rsa.ImportParameters(pKey); | |
return rsa.Encrypt(data, padding); | |
} | |
public static byte[] Decrypt(byte[] data, PrivateKey sKey, RSAEncryptionPadding? padding = default) | |
{ | |
padding ??= RSAEncryptionPadding.OaepSHA512; | |
using var rsa = RSA.Create(); | |
rsa.ImportParameters(sKey); | |
return rsa.Decrypt(data, padding); | |
} | |
public static byte[] SignData( | |
byte[] data, | |
PrivateKey sKey, | |
HashAlgorithmName? hashAlgorithmName = default, | |
RSASignaturePadding? padding = default) | |
{ | |
hashAlgorithmName ??= HashAlgorithmName.SHA512; | |
padding ??= RSASignaturePadding.Pkcs1; | |
using var rsa = RSA.Create(); | |
rsa.ImportParameters(sKey); | |
return rsa.SignData(data, hashAlgorithmName.Value, padding); | |
} | |
public static bool Verify( | |
byte[] data, | |
byte[] signature, | |
PublicKey pKey, | |
HashAlgorithmName? hashAlgorithmName = default, | |
RSASignaturePadding? padding = default) | |
{ | |
hashAlgorithmName ??= HashAlgorithmName.SHA512; | |
padding ??= RSASignaturePadding.Pkcs1; | |
using var rsa = RSA.Create(); | |
rsa.ImportParameters(pKey); | |
return rsa.VerifyData(data, signature, hashAlgorithmName.Value, padding); | |
} | |
} | |
public class RsaTests | |
{ | |
[Test] | |
public void TestGenerateKeys() | |
{ | |
var (sKey, pKey) = Rsa.GenerateKeyPair(2048); | |
Assert.NotNull(sKey); | |
Assert.NotNull(pKey); | |
var sKeyObj = JsonConvert.SerializeObject(sKey, Formatting.Indented); | |
var pKeyObj = JsonConvert.SerializeObject(pKey, Formatting.Indented); | |
Assert.NotNull(sKeyObj); | |
Assert.NotNull(pKeyObj); | |
Console.WriteLine(sKeyObj); | |
Console.WriteLine(pKeyObj); | |
} | |
[Test] | |
public void TestEncryptDecrypt() | |
{ | |
var data = "Hello World!"u8.ToArray(); | |
var (sKey, pKey) = Rsa.GenerateKeyPair(2048); | |
var encrypted = Rsa.Encrypt(data, pKey); | |
var decrypted = Rsa.Decrypt(encrypted, sKey); | |
Console.WriteLine(Convert.ToBase64String(encrypted)); | |
Console.WriteLine(Encoding.UTF8.GetString(decrypted)); | |
Assert.AreEqual(data, decrypted); | |
} | |
[Test] | |
public void TestSignVerify() | |
{ | |
var data = "Hello World!"u8.ToArray(); | |
var (sKey, pKey) = Rsa.GenerateKeyPair(2048); | |
var signature = Rsa.SignData(data, sKey); | |
var verified = Rsa.Verify(data, signature, pKey); | |
Console.WriteLine(Convert.ToBase64String(signature)); | |
Console.WriteLine(verified); | |
Assert.IsTrue(verified); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment