当前位置: 首页 > 知识库问答 >
问题:

在C#中使用ECDSA生成证书

刘升
2023-03-14
openssl ecparam -genkey -name secp256r1 -out mykey.key
openssl req -new -key mykey.key -out myreq.csr
openssl req -x509 -days 7 -key mykey.key -in myreq.csr -out mycert.crt
openssl pkcs12 -export -out mycert.pfx -inkey mykey.key -in mycert.crt

我已经使用BouncyCastle来帮助创建基于RSA的证书,因此接下来的步骤或多或少遵循了创建RSA证书的方法。

(注意,bc前缀用于来自BouncyCastle的类,ms用于.NET类)

1生成密钥对:私钥和公钥

BC.IAsymmetricCipherKeyPairGenerator bcKpGen = BC.GeneratorUtilities.GetKeyPairGenerator("ECDSA");
bcKpGen.Init(new BC.ECKeyGenerationParameters(BC.SecObjectIdentifiers.SecP256r1, new BC.SecureRandom()));
BC.AsymmetricCipherKeyPair bcSubjKeys = bcKpGen.GenerateKeyPair();
BC.X509V3CertificateGenerator bcXgen = new BC.X509V3CertificateGenerator();
// .. set subject, validity period etc
bcXgen.SetPublicKey(bcSubjKeys.Public);
BC.ISignatureFactory bcSigFac = new BC.Asn1SignatureFactory("SHA256WITHECDSA", bcSubjKeys.Private);
BC.X509Certificate bcCert = bcXgen.Generate(bcSigFac);

如果我可以使用没有私钥的证书,则可以执行以下操作:

MS.X509Certificate mcCert = new MS.X509Certificate2(bcCert.GetEncoded(), null);

我就完蛋了。

当试图设置私钥时会出现问题:

msCert.PrivateKey = ConvertBouncyToNetSomehow(bcSubjKeys.Private)
BC.PrivateKeyInfo bcPKInfo = BC.PrivateKeyInfoFactory.CreatePrivateKeyInfo(bcSubjKeys.Private);
byte[] pkArr = bcPKInfo.GetDerEncoded();
MS.CngKey msPKCng = MS.CngKey.Import(pkArr, MS.CngKeyBlobFormat.Pkcs8PrivateBlob);

共有1个答案

吕晟睿
2023-03-14

不幸的是,现在不可能直接跳出框框。您可以使用P/Invokes和.NET4.6.2(当前处于预览阶段)来完成其余的工作。或者,通过绕道.NET Core,您可以构建一个在.NET4.6.1中工作的PFX。

Windows CNG库将ECC拆分为ECDSA和ECDH。ECDSA密钥对象只能用于ECDSA;但每当Windows无法确定PFX导入(或PKCS#8导入)期间的使用情况时,它就会调用私钥ECDH。为什么?由于Windows允许ECDH密钥对象同时进行密钥协商(ECDH)和数字签名(ECDSA),因此ECDH更加灵活。

但.NET4.6.1并不知道这一点。

[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
private static extern unsafe bool CertSetCertificateContextProperty(IntPtr pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, SafeNCryptKeyHandle pvData);

internal enum CertContextPropId : int
{
    CERT_NCRYPT_KEY_HANDLE_PROP_ID = 78,
}

[Flags]
internal enum CertSetPropertyFlags : int
{
    None = 0,
}

private static X509Certificate2 MateECDsaPrivateKey(
    X509Certificate2 cert,
    CngKey privateKey)
{
    // Make a new certificate instance which isn't tied to the current one
    using (var tmpCert = new X509Certificate2(cert.RawData))
    {
        SafeNCryptKeyHandle keyHandle = privateKey.Handle;

        // Set the ephemeral key handle property
        if (!CertSetCertificateContextProperty(
            tmpCert.Handle,
            CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
            CertSetPropertyFlags.None,
            keyHandle))
        {
            throw new CryptographicException(Marshal.GetLastWin32Error());
        }

        // You could emit this, if you prefer.
        byte[] pfxBytes = tmpCert.Export(X509ContentType.Pkcs12);

        // Clear the key handle out again to prevent double-free
        keyHandle = new SafeNCryptKeyHandle();

        if (!CertSetCertificateContextProperty(
            tmpCert.Handle,
            CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
            CertSetPropertyFlags.None,
            keyHandle))
        {
            throw new CryptographicException(Marshal.GetLastWin32Error());
        }

        // Now load a new certificate which has a temporary keyfile on disk.
        // Note: If you don't want exportability here, don't request it.
        var matedCert = new X509Certificate2(pfxBytes, (string)null, X509KeyStorageFlags.Exportable);

        using (ECDsa ecdsa = matedCert.GetECDsaPrivateKey())
        {
            if (ecdsa == null)
            {
                throw new InvalidOperationException("It didn't work");
            }
        }

        return matedCert;
    }
}
 类似资料:
  • 我有代码使用为ECDSA签名生成串联(r-s)签名和JWK格式的密钥: 似乎有效。我也有使用来实现相同目标的代码: 这两者都返回128字节的缓冲区;并且它们可以交叉验证(例如,我可以用< code>SubtleCrypto验证< code > JSR sign 签名,反之亦然)。然而,当我在Node.js 模块中使用< code>Sign类时,我似乎得到了完全不同的东西。 在这里,我得到了一个可变

  • 我正在尝试使用C#和内置的加密库来验证使用EC密钥SHA256创建的签名。 我使用openssl创建了一个私钥和相应的证书: 以下是我正在使用的密钥(别担心,它们并不重要): 然后,我有一个包含字符串“Hello”的简单数据文件。然后,我使用openssl对该文件进行签名,如下所示: 然后,我可以通过首先从证书中提取公钥,然后使用公钥来验证签名: 然后,我尝试使用 C#(.NET Core 3.1

  • 是否可以使用KeypairGenerator在java中生成ecdsa 32字节私钥?我的意思是keys.getpublic.getEncoded.length将返回32我尝试生成私钥,但大小是144字节

  • 我想在c中对大随机数进行降级。问题是srand()可以生成的最大数字大约是37000。我想在intervall中创建一个70000到2150000000的数字。有人能帮我吗? 随机数生成器:

  • 我有一个包含EC私钥的文件: 我有一个证书,它的公钥对应于私钥: 在 pem 格式中: 以txt格式: 我正在努力完成两件事: < li >使用ecdsa-with-SHA256签名算法使用私钥对字节数组进行签名 < li >使用证书中的公钥验证签名是否正确 我尝试过使用充气城堡图书馆。这是我到目前为止所拥有的。我的断言是失败的。

  • 在BGI库的“graphics.h”头文件中有一个函数pieslice,它的语法是: [x、y为圆心,短角和端角分别为起始角和结束角] 到目前为止我的代码: 我能够完成使用圆的参数方程的计算部分,但无法使用函数生成图形。一些帮助会很好。提前谢谢你。 在运行这个程序时,我得到了这个错误: