.NET Core 3 无法加载 ECC 私钥
.NET Core 3 unable to load ECC private key
感谢 ,我能够将 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 _);
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-----
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-----
使用这种形式的 PEM 文件,.NET Core 3 可以 导入私钥。
我的问题是:这是怎么回事;为什么 openssl 将私钥更改为另一种格式(我怎么知道是哪种格式?),为什么 .NET Core 3 可以理解一种格式而不是另一种格式?
初始密钥格式不正确。私有值 S 尚未 left-padded 正确。值 S 作为 ASN.1 八位字节串中的无符号大端整数传输。根据定义,此八位字节串(字节数组)的大小必须与以字节为单位的密钥大小相同。这意味着您使用的 256 位曲线必须是 32 字节(secp256r1,以不同的名称已知)。
所以您的代码和 .NET 代码是正确的。 OpenSSL 似乎更自由地接受它所接受的内容,但它会写出应有的值 S。
下面是初始私钥值,取自here:
SEQUENCE (4 elem)
INTEGER 1
OCTET STRING (31 byte) 9B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A
[0] (1 elem)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
[1] (1 elem)
BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011…
这是 OpenSSL-corrected 一个:
SEQUENCE (4 elem)
INTEGER 1
OCTET STRING (32 byte) 009B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A
[0] (1 elem)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
[1] (1 elem)
BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011…
并记下 OCTET STRING 值的大小和前面的零。
当然,这个私钥现在已经被泄露了。请注意,丢失两个 00
字节或三个(等等)字节的可能性较小。
感谢
但是,我有 运行 进入 一个 无法被 ECDSA.ImportPrivateKey
加载的密钥。奇怪的是,用 openssl
查看它会将关键字节更改为 .NET Core 3 可以 理解的内容。
导入失败私钥的代码(这是失败的实际密钥):
ecdsa = ECDsa.Create();
var pem = "MHYCAQEEH5t2Xlmsw5uqw3W9+/3nosFi6i3V901uW6ZzUpvVM0qgCgYIKoZIzj0DAQehRANCAASck2UuMxfyDYBdJC0mHNeToqMBhJuMZYSgkUNbK/xzD7e3cwr5okPx0pZdSMfDmyi1dBujtIIxFK9va1bdVAR9";
var derArray = Convert.FromBase64String(pem);
ecdsa.ImportECPrivateKey(derArray, out _);
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-----
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-----
使用这种形式的 PEM 文件,.NET Core 3 可以 导入私钥。
我的问题是:这是怎么回事;为什么 openssl 将私钥更改为另一种格式(我怎么知道是哪种格式?),为什么 .NET Core 3 可以理解一种格式而不是另一种格式?
初始密钥格式不正确。私有值 S 尚未 left-padded 正确。值 S 作为 ASN.1 八位字节串中的无符号大端整数传输。根据定义,此八位字节串(字节数组)的大小必须与以字节为单位的密钥大小相同。这意味着您使用的 256 位曲线必须是 32 字节(secp256r1,以不同的名称已知)。
所以您的代码和 .NET 代码是正确的。 OpenSSL 似乎更自由地接受它所接受的内容,但它会写出应有的值 S。
下面是初始私钥值,取自here:
SEQUENCE (4 elem)
INTEGER 1
OCTET STRING (31 byte) 9B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A
[0] (1 elem)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
[1] (1 elem)
BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011…
这是 OpenSSL-corrected 一个:
SEQUENCE (4 elem)
INTEGER 1
OCTET STRING (32 byte) 009B765E59ACC39BAAC375BDFBFDE7A2C162EA2DD5F74D6E5BA673529BD5334A
[0] (1 elem)
OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named elliptic curve)
[1] (1 elem)
BIT STRING (520 bit) 0000010010011100100100110110010100101110001100110001011111110010000011…
并记下 OCTET STRING 值的大小和前面的零。
当然,这个私钥现在已经被泄露了。请注意,丢失两个 00
字节或三个(等等)字节的可能性较小。