I was following this article (in it there is a link to a .cs file at the bottom of the page) to generate a self-signed X509Certificate2. The code in the article works but now I want to extend it. I am trying to pass the optional argument, _In_opt_ PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm
, into CertCreateSelfSignCertificate.
I have created this structure for it:
struct CryptoApiBlob
{
public Int32 cbData;
public IntPtr pbData;
}
struct CryptAlgorithmIdentifier {
public String pszObjId;
public CryptoApiBlob Parameters;
}
The code I am trying to use to create it is:
CryptAlgorithmIdentifier algorithm = new CryptAlgorithmIdentifier { pszObjId = "szOID_NIST_AES256_CBC", Parameters = new CryptoApiBlob { cbData = 0 } };
algorithmPointer = Marshal.AllocHGlobal(Marshal.SizeOf(algorithm));
Marshal.StructureToPtr(algorithm, algorithmPointer, false);
I then pass the algorithmPointer
into the method.
I get this error when I try to pass it into CertCreateSelfSignCertificate:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
Additional information: ASN1 bad arguments to function call. (Exception from HRESULT: 0x80093109)
Does anyone happen to know why this happens, or can see any problems with the way I've defined my structure or allocated it in memory?
As @Luaan noted, strings can be tricky to marshal correctly in p/invoke, it's often easiest to avoid p/invoke interop when you can. However I was still curious what was going wrong here.
From the MSDN docs on
PCRYPT_ALGORITHM_IDENTIFIER
it looks as though you should pass in the actual OID of the algorithm"2.16.840.1.101.3.4.1.42"
in this case. TheszOID_NIST_AES256_CBC
that is in the list there is only the C/C++ identifier (or macro) that expands to said OID string.