 
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;
	}
}