P /调用CertCreateSelfSignCertificate时的问题

时间:2015-06-10 12:49:15

标签: c# .net pinvoke marshalling x509certificate2

我正在关注this article (in it there is a link to a .cs file at the bottom of the page)以生成自签名的X509Certificate2。文章中的代码有效但现在我想扩展它。我试图将可选参数_In_opt_ PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm传递给CertCreateSelfSignCertificate

我为它创建了这个结构:

struct CryptoApiBlob
{
    public Int32 cbData;
    public IntPtr pbData;
}

struct CryptAlgorithmIdentifier {
    public String pszObjId;
    public CryptoApiBlob Parameters;
}

我尝试用来创建它的代码是:

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

然后我将algorithmPointer传递给方法。

当我尝试将其传递到CertCreateSelfSignCertificate时,我收到此错误:

  

未处理的类型异常   ' System.Runtime.InteropServices.COMException'发生在mscorlib.dll

     

附加信息:ASN1函数调用的错误参数。   (HRESULT异常:0x80093109)

有没有人碰巧知道为什么会发生这种情况,或者可以看到我定义我的结构或在内存中分配它的方式有任何问题?

2 个答案:

答案 0 :(得分:1)

正如@Luaan所指出的那样,在p / invoke中正确编组字符串可能很棘手,在可能的情况下,通常最容易避免p / invoke互操作。但是我仍然很好奇这里出了什么问题。

PCRYPT_ALGORITHM_IDENTIFIER上的MSDN文档中,在这种情况下,您似乎应该传递算法"2.16.840.1.101.3.4.1.42"的实际OID。列表中的szOID_NIST_AES256_CBC只有扩展为所述OID字符串的C / C ++标识符(或宏)。

答案 1 :(得分:0)

这个问题很老,但我想我会分享我的见解。 MSDN将CRYPT_ALGORITHM_IDENTIFIER列为:

typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
    LPSTR            pszObjId;
    CRYPT_OBJID_BLOB Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;

重要的是要注意它是LPSTR不是 a LPWSTR。所以字符串需要编组为ANSI。除非明确指定,否则.NET会将字符串封送为unicode。所以我们相应的结构需要额外的装饰:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct AlgorithmIdentifier
{
    public string ObjectId;
    public CryptoBlob Parameters;
}

CharSet添加到StructLayout属性中将使.NET以所需的编码封装字符串。然后它可以直接使用:

var algId = new AlgorithmIdentifier
{
    ObjectId = "1.2.840.113549.1.1.5" // szOID_RSA_SHA1RSA
};