ARTICLE AD BOX
My problem: I need to digitally sign RDP files before distribution since Microsoft change in April 2026.
I have an RSA code signing certificate stored in HSM (Azure Key Vault) and hence can't use rdpsign.exe.
I found a python implementation nfedera/rdpsign, which uses openssl to create and append the digital signature. Using this along with AzureKeyVaultManagedHSMEngine I'm able to sign .rdp files.
The OpenSSL command is structured openssl smime -sign -binary -outform DER -noattr -nosmimecap -signer 'mycert.crt' -inkey 'managedhsm:<keyvault>:<keyname>'.
I'd like to remove the dependency on Python and OpenSSL in my signing flow and am looking to implement the whole solution in a single C# .NET application. Based on my reading, it seemed as though BouncyCastle was the library to use for this. But I've hit a dead end, which I'm sure is to do with my (lack of) understanding of PKCS / CMS.
Given:
RSA signed SHA 256 digest signedDigest:byte[] Public certificate `mycert.crt'How can I produce a signature result:byte[] which matches the output of the above OpenSSL command?
Use of BouncyCastle is optional.
The following is a code excerpt which I've tried to use to generate the signature.
using Org.BouncyCastle.Asn1.Pkcs; // Picked this as it matched openssl smime option var digestOid = "2.16.840.1.101.3.4.2.1"; //SHA256 var digestAlg = new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance); var digestAlgs = new DerSet(digestAlg); var path = "./path/to/mycert.crt"; var cert = new X509CertificateParser().ReadCertificate(File.ReadAllBytes(path)); var signedDigest = new DerOctetString(signedDigest); var certVec = new Asn1EncodableVector(); certVec.Add(Asn1Object.FromByteArray(cert.GetEncoded())); var certs = new BerSet(certVec); var signerInfo = new SignerInfo( DerInteger.One, new IssuerAndSerialNumber(cert.IssuerDN, cert.SerialNumber), digestAlg, null, new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance), digestSig, null ); var contentInfo = new ContentInfo(PkcsObjectIdentifiers.Data, null); var signedData = new SignedData(DerInteger.One, digestAlgs, contentInfo, certs, null, new DerSet(signerInfo)); var finalContentInfo = new ContentInfo(PkcsObjectIdentifiers.SignedData, signedData); var result = finalContentInfo.GetEncoded();Thanks in advance!
