我正在关注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)
有没有人碰巧知道为什么会发生这种情况,或者可以看到我定义我的结构或在内存中分配它的方式有任何问题?
答案 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
};