Skip to content

Instantly share code, notes, and snippets.

@ddjerqq
Created September 29, 2023 17:03
Show Gist options
  • Save ddjerqq/435981a8b15557560ffcad100c34adae to your computer and use it in GitHub Desktop.
Save ddjerqq/435981a8b15557560ffcad100c34adae to your computer and use it in GitHub Desktop.
C# implementation and easy abstraction for RSA cryptographic encryption algorithm
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!,
};
}
}
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!,
};
}
}
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