Skip to content

Instantly share code, notes, and snippets.

@itsho
Last active June 4, 2023 17:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save itsho/98bbb6d668b18072b6ffdf089ef28fc2 to your computer and use it in GitHub Desktop.
Save itsho/98bbb6d668b18072b6ffdf089ef28fc2 to your computer and use it in GitHub Desktop.
RSA - create signature and verify
// ----------------------------------------------------
// Notice, this code is using BouncyCastle NuGet:
// https://www.nuget.org/packages/BouncyCastle/1.8.4/
// Created by: Itsho
// Creation Date: 20 December 2018
// ----------------------------------------------------
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using System;
using System.IO;
using System.Text;
namespace Test
{
public class Program
{
[STAThread]
private static void Main(string[] args)
{
// the 'usual' usage of keypair in "textbook" RSA (which is an asymmetric algorithm) is:
// public key = ENCRYPTING / VERIFYING
// private key = DECRYPTING / SIGNING
var rsav = new RsaSignAndVerify();
var keyPair = rsav.GenerateRandomKeyPair();
// print keys to console
rsav.PrintKeys(keyPair);
// content we like to sign
var textToSign = "Data to sign. can be a file or anything :-)";
// display data we are about to sign
Console.WriteLine($"Text to sign: {textToSign}");
// server side - generates the signature by using the PRIVATE key
var signature = rsav.ServerGenerateSignature(textToSign, (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)keyPair.Private);
// client side - validates the signature by using the PUBLIC key
var isSignatureValid = rsav.ClientValidateSignature(textToSign, signature, (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters) keyPair.Public);
Console.WriteLine($"Signature isValid: {isSignatureValid}");
}
}
public class RsaSignAndVerify
{
public AsymmetricCipherKeyPair GenerateRandomKeyPair()
{
var rsaKeyPairGen = new RsaKeyPairGenerator();
rsaKeyPairGen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
return rsaKeyPairGen.GenerateKeyPair(); ;
}
public bool ClientValidateSignature(string sourceData, byte[] signature, RsaKeyParameters publicKey)
{
byte[] tmpSource = Encoding.ASCII.GetBytes(sourceData);
ISigner signClientSide = SignerUtilities.GetSigner(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id);
signClientSide.Init(false, publicKey);
signClientSide.BlockUpdate(tmpSource, 0, tmpSource.Length);
return signClientSide.VerifySignature(signature);
}
public byte[] ServerGenerateSignature(string sourceData, RsaKeyParameters privateKey)
{
byte[] tmpSource = Encoding.ASCII.GetBytes(sourceData);
ISigner sign = SignerUtilities.GetSigner(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id);
sign.Init(true, privateKey);
sign.BlockUpdate(tmpSource, 0, tmpSource.Length);
return sign.GenerateSignature();
}
public void PrintKeys(AsymmetricCipherKeyPair keyPair)
{
using (TextWriter textWriter1 = new StringWriter())
{
var pemWriter1 = new PemWriter(textWriter1);
pemWriter1.WriteObject(keyPair.Private);
pemWriter1.Writer.Flush();
string privateKey = textWriter1.ToString();
Console.WriteLine(privateKey);
}
using (TextWriter textWriter2 = new StringWriter())
{
var pemWriter2 = new PemWriter(textWriter2);
pemWriter2.WriteObject(keyPair.Public);
pemWriter2.Writer.Flush();
string publicKey = textWriter2.ToString();
Console.WriteLine(publicKey);
}
}
private byte[] ConvertHexString(string hexString)
{
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture);
}
return data;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment