.NET Core 3无法加载ECC私钥

Ras*_*usW 6 c# cryptography elliptic-curve .net-core-3.0

通过在.NET中加载ECC私钥,我能够将ECC私钥加载到.NET Core 3中,并执行签名任务。

但是,我遇到了一个不能由加载的密钥ECDSA.ImportPrivateKey。奇怪的是,通过将其openssl更改为.NET Core 3 可以理解的键字节来进行查看

导入失败的私钥的代码(这是失败的实际密钥):

ecdsa = ECDsa.Create();
var pem = "MHYCAQEEH5t2Xlmsw5uqw3W9+/3nosFi6i3V901uW6ZzUpvVM0qgCgYIKoZIzj0DAQehRANCAASck2UuMxfyDYBdJC0mHNeToqMBhJuMZYSgkUNbK/xzD7e3cwr5okPx0pZdSMfDmyi1dBujtIIxFK9va1bdVAR9";
var derArray = Convert.FromBase64String(pem);
ecdsa.ImportECPrivateKey(derArray, out _);
Run Code Online (Sandbox Code Playgroud)

ImportECPrivateKey呼叫失败,System.Security.Cryptography.CryptographicException : ASN1 corrupted data内部System.Security.Cryptography.EccKeyFormatHelper.FromECPrivateKey(ReadOnlyMemory`1 keyData, AlgorithmIdentifierAsn& algId, ECParameters& ret)

原始PEM文件如下所示:

$ cat private_key_cert_265.pem
-----BEGIN EC PRIVATE KEY-----
MHYCAQEEH5t2Xlmsw5uqw3W9+/3nosFi6i3V901uW6ZzUpvVM0qgCgYIKoZIzj0D
AQehRANCAASck2UuMxfyDYBdJC0mHNeToqMBhJuMZYSgkUNbK/xzD7e3cwr5okPx
0pZdSMfDmyi1dBujtIIxFK9va1bdVAR9
-----END EC PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

openssl将私钥转换为其他内容:

$ openssl ec -in private_key_cert_265.pem
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIACbdl5ZrMObqsN1vfv956LBYuot1fdNblumc1Kb1TNKoAoGCCqGSM49
AwEHoUQDQgAEnJNlLjMX8g2AXSQtJhzXk6KjAYSbjGWEoJFDWyv8cw+3t3MK+aJD
8dKWXUjHw5sotXQbo7SCMRSvb2tW3VQEfQ==
-----END EC PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

使用这种形式的PEM文件,.NET Core 3 可以导入私钥。

我的问题是:怎么回事?为什么openssl将私钥更改为另一种格式(如何分辨是哪种格式?),为什么.NET Core 3可以理解一种格式而不能理解另一种格式?

Maa*_*wes 3

初始密钥的格式不正确。私有值 S 未正确左填充。值 S 作为 ASN.1 八位字节字符串中的无符号大端整数进行传输。根据定义,该八位字节字符串(字节数组)的大小必须与密钥大小(以字节为单位)相同。这意味着您使用的 256 位曲线必须是 32 字节(secp256r1,有不同的名称)。

\n\n

所以你的代码和.NET代码是正确的。OpenSSL 似乎更自由地接受它,但它写出了应有的值 S。

\n\n
\n\n

以下是初始私钥值,取自此处

\n\n
SEQUENCE (4 elem)\n  INTEGER 1\n  OCTET STRING (31 byte) 9B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A\n  [0] (1 elem)\n    OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)\n  [1] (1 elem)\n    BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011\xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是经过 OpenSSL 修正的:

\n\n
SEQUENCE (4 elem)\n  INTEGER 1\n  OCTET STRING (32 byte) 009B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A\n  [0] (1 elem)\n    OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)\n  [1] (1 elem)\n    BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011\xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n\n

并记下八位字节字符串值的大小和前面的零。

\n\n
\n\n

当然,这个私钥现在已经被泄露了。00请注意,丢失两个字节或三个字节(等等)的可能性较小。

\n