Sign precomputed hash with bouncycastle (c#)

BouncyCastle

It is an adaption of Java examples of bouncy castle to .NET and a demonstration of using ISignatureFactory instead of the AsymmetricKeyPair. See https://stackoverflow.com/questions/39338094/creating-an-external-2-steps-signature-with-bouncycastle-and-sunmscapi


public class CustomSigner : ISigner
{

	private byte[] result;

	private readonly X509Certificate2 _signCertificate;

	public CustomSigner(X509Certificate2 signCertificate)
	{
		_signCertificate = signCertificate;
	}

	public string AlgorithmName
	{
		get
		{
			return PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id;
		}
	}

	public void BlockUpdate(byte[] input, int inOff, int length)
	{
		using System.Security.Cryptography.RSA rsa = _signCertificate.GetRSAPrivateKey();

		input = input.Take(length).ToArray();

		result = rsa.SignData(input, 
			System.Security.Cryptography.HashAlgorithmName.SHA256, 
			System.Security.Cryptography.RSASignaturePadding.Pkcs1);
	}

	public byte[] GenerateSignature()
	{
		return result;
	}

	public void Init(bool forSigning, ICipherParameters parameters)
	{
		throw new System.NotImplementedException();
	}

	public void Reset()
	{
		throw new System.NotImplementedException();
	}

	public void Update(byte input)
	{
		throw new System.NotImplementedException();
	}

	public bool VerifySignature(byte[] signature)
	{
		throw new System.NotImplementedException();
	}
}

public class CustomSignatureFactory : ISignatureFactory
{
	private readonly AlgorithmIdentifier algID;
	private readonly X509Certificate2 _signingCert;

	public CustomSignatureFactory(X509Certificate2 signingCert)
	{
		algID = new AlgorithmIdentifier(PkcsObjectIdentifiers.Sha256WithRsaEncryption);
		_signingCert = signingCert;

	}

	public object AlgorithmDetails
	{
		get { return algID; }
	}

	public IStreamCalculator CreateCalculator()
	{
		ISigner sig = new CustomSigner(_signingCert);
		return new DefaultSigCalculator(sig);
	}

}

internal class CustomCmsSigner
{
	public static byte[] SignHash(byte[] hash, X509Certificate2 signingCert)
	{

		X509SubjectKeyIdentifierExtension skiExtension = signingCert.Extensions.OfType().FirstOrDefault();

		bouncy.Org.BouncyCastle.X509.X509Certificate bCert = DotNetUtilities.FromX509Certificate(signingCert);

		CmsSignedDataGenerator gen = new ();


		Attribute attrHash = new(CmsAttributes.MessageDigest, new DerSet(new DerOctetString(hash)));
		Attribute attrcontentType = new(CmsAttributes.ContentType, new DerSet(CmsObjectIdentifiers.Data));

		Asn1EncodableVector v = new (attrcontentType, attrHash);

		SignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new SignerInfoGeneratorBuilder()
			.WithSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v)));
		
		SignerInfoGenerator signerInfoGenerator = signerInfoGeneratorBuilder.Build(
			new CustomSignatureFactory(signingCert), bCert);


		gen.AddSignerInfoGenerator(signerInfoGenerator);

		using X509Chain x509Chain = X509Chain.Create();
		x509Chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
		x509Chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreEndRevocationUnknown;
		x509Chain.Build(signingCert);

		var certList = x509Chain.ChainElements.Cast()
			.Select(ce => DotNetUtilities.FromX509Certificate(ce.Certificate)).ToList();
		var storeParams = new X509CollectionStoreParameters(certList);
		var certStore = X509StoreFactory.Create("Certificate/Collection", storeParams);

		gen.AddCertificates(certStore);

		CmsSignedData s = gen.Generate(CmsSignedGenerator.Data, new CmsProcessableByteArray(new byte[0]), true);

		byte[] encoded =  s.GetEncoded();


		/*CmsSignedData signedCmsData = new CmsSignedData(new CmsProcessableByteArray(new byte[] { 1, 2, 3 }), encoded);
		
		SignerInformation signerInformation = signedCmsData.GetSignerInfos().GetSigners().OfType().FirstOrDefault();
		
		bool verified = signerInformation.Verify(bCert);*/


		return encoded;

	}
}

Post a Comment

Previous Post Next Post