P/Invoking CertCreateSelfSignCertificate 时出现问题
Problems when P/Invoking CertCreateSelfSignCertificate
我正在关注 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。
我为它创建了这个结构:
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:
时出现此错误
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)
有没有人碰巧知道为什么会这样,或者能看出我定义结构或在内存中分配结构的方式有任何问题吗?
正如@Luaan 指出的那样,在 p/invoke 中正确编组字符串可能很棘手,如果可以的话,通常最容易避免 p/invoke 互操作。不过我还是很好奇这里出了什么问题。
从 PCRYPT_ALGORITHM_IDENTIFIER
上的 MSDN 文档看来,在这种情况下您应该传入算法 "2.16.840.1.101.3.4.1.42"
的实际 OID。列表中的 szOID_NIST_AES256_CBC
只有 C/C++ 标识符(或宏)扩展为所述 OID 字符串。
这个问题很老了,但我想我会分享我的见解。 MSDN 将 CRYPT_ALGORITHM_IDENTIFIER
列为:
typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
LPSTR pszObjId;
CRYPT_OBJID_BLOB Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;
需要注意的重要一点是它是 LPSTR
,不是 LPWSTR
。所以字符串需要编组为 ANSI。除非明确指定,否则 .NET 会将字符串编组为 unicode。所以我们对应的struct需要额外的修饰:
[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
};
我正在关注 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。
我为它创建了这个结构:
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:
时出现此错误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)
有没有人碰巧知道为什么会这样,或者能看出我定义结构或在内存中分配结构的方式有任何问题吗?
正如@Luaan 指出的那样,在 p/invoke 中正确编组字符串可能很棘手,如果可以的话,通常最容易避免 p/invoke 互操作。不过我还是很好奇这里出了什么问题。
从 PCRYPT_ALGORITHM_IDENTIFIER
上的 MSDN 文档看来,在这种情况下您应该传入算法 "2.16.840.1.101.3.4.1.42"
的实际 OID。列表中的 szOID_NIST_AES256_CBC
只有 C/C++ 标识符(或宏)扩展为所述 OID 字符串。
这个问题很老了,但我想我会分享我的见解。 MSDN 将 CRYPT_ALGORITHM_IDENTIFIER
列为:
typedef struct _CRYPT_ALGORITHM_IDENTIFIER {
LPSTR pszObjId;
CRYPT_OBJID_BLOB Parameters;
} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER;
需要注意的重要一点是它是 LPSTR
,不是 LPWSTR
。所以字符串需要编组为 ANSI。除非明确指定,否则 .NET 会将字符串编组为 unicode。所以我们对应的struct需要额外的修饰:
[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
};