如何在 C# 中加载私有 ecdsa 密钥 es256?

Posted

技术标签:

【中文标题】如何在 C# 中加载私有 ecdsa 密钥 es256?【英文标题】:How to load private ecdsa key es256 in c#? 【发布时间】:2020-11-20 16:42:43 【问题描述】:

我使用以下命令来生成私有和公共 ES256 密钥:

创建私钥:openssl ecparam -genkey -name prime256v1 -noout -out private.pem

创建公钥:openssl ec -in private.pem -pubout -out public.pem

现在我得到了以下私钥:

-----开始EC私钥----- MHcCAQEEIFkxqdXoVAGSSc55u0muepwVRr3ARWzLMO0ywW7qhEeIoAoGCCqGSM49 AwEHoUQDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto97qELhiRSObbhX3mUSvxpPeK fVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----结束EC私钥-----

以下公钥:

-----开始公钥----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto 97qELhiRSObbhX3mUSvxpPeKfVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----结束公钥-----

我想将这些键加载到 c# 中的 ecdsa 实例中。我用以下代码做到这一点:

public ECDsaSecurityKey LoadPrivateKey()
    
        byte[] privateKey = Convert.FromBase64String(PRIVATE_KEY);
        try
        
            ECDsa? privateKeyEcDsa = ECDsa.Create();

            if (privateKeyEcDsa == null)
            
                throw new CryptographicException(message: "Key not created");
            

            privateKeyEcDsa.ImportPkcs8PrivateKey(source: privateKey, bytesRead: out _);

            return new ECDsaSecurityKey(privateKeyEcDsa);
        
        catch (CryptographicException exception)
            
            throw;
        
    

还有公钥:

     public ECDsaSecurityKey LoadPublicKey()
        
byte[] publicKey = Convert.FromBase64String(PUBLIC_KEY);
            try
            
                ECDsa? publicKeyEcDsa = ECDsa.Create();

                if (publicKeyEcDsa == null)
                
                    throw new CryptographicException(message: "Key not created");
                

                publicKeyEcDsa.ImportSubjectPublicKeyInfo(source: publicKey, bytesRead: out _);

                return new ECDsaSecurityKey(publicKeyEcDsa);
            
            catch (CryptographicException exception)
            
                this._logger.LogError("Something went wrong while loading EcDsa public key: " + exception.Message);

                throw;
            
        

当我运行单元测试时,事情不起作用,抛出一个错误:

我不确定为什么这不起作用? openssl 命令生成的密钥对类型是否正确?

编辑: 在这个网站上,当我选择 ES256 私钥是不同的: https://kjur.github.io/jsjws/tool_jwt.html

例子:

-----开始私钥----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgEbVzfPnZPxfAyxqE ZV05laAoJAl+/6Xt2O4mOB611sOhRANCAASgFTKjwJAAU95g++/vzKWHkzAVmNMI tB5vTjZOOIwnEb70MsWZFIyUFD1P9Gwstz4+akHX7vI8BH6hHmBmfeQl -----结束私钥-----

我用 OpenSSL 生成的私钥最后加上两个等号:

-----开始EC私钥----- MHcCAQEEIFkxqdXoVAGSSc55u0muepwVRr3ARWzLMO0ywW7qhEeIoAoGCCqGSM49 AwEHoUQDQgAEFXuuZeDJN9dvjCwKy40/coi3NVto97qELhiRSObbhX3mUSvxpPeK fVv3/fVCjt9CeGuwYvkQPHmRfx0EFjAI8A== -----结束EC私钥-----

所以我想我在打开 ssl 时做错了。

【问题讨论】:

【参考方案1】:

私钥具有 SEC1 格式而不是 PKCS#8 格式,即必须通过 ImportECPrivateKey() 完成导入。

公钥是 X.509/SPKI 密钥,所以ImportSubjectPublicKeyInfo() 是正确的。

这两种方法都需要一个 DER 编码的密钥,即没有页眉和页脚以及 Base64 解码的正文。

如果考虑到这一点,代码可以工作(至少在我的机器上)。

这些方法在 .NET Core 3.x 和 .NET 5.0 中可用。

【讨论】:

谢谢,如果有人需要 pkcs#8 格式的 jwt 签名和验证,请使用 openssl pkcs8 -topk8 -nocrypt -in ec1.pem -out ec2.pem

以上是关于如何在 C# 中加载私有 ecdsa 密钥 es256?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 OpenSSL ECDSA 密钥加载到 C# 中?

C# ecdsa 签名 - 我可以选择哪个密钥规范?

如何在 TPM 中加载和使用持久对称密钥?

在 Java 中加载 RSA 私钥(algid 解析错误,不是序列)

ECDSA密钥

如何在 C# 中从文件中加载 RSA 公钥