gpt4 book ai didi

openssl - 微软压缩天然气 |如何将 PEM 编码的 ECDSA 私钥导入 MS Key Storage Provider

转载 作者:行者123 更新时间:2023-12-04 11:47:37 27 4
gpt4 key购买 nike

我知道 MS CNG 私有(private)有这种格式 -
BCRYPT_ECCKEY_BLOB
BYTE X[cbKey] // Big-endian.
BYTE Y[cbKey] // Big-endian.
BYTE d[cbKey] // Big-endian.

因此试图导入以下关键字节 -

byte[] ec256PrivKB =
{
//Magic + CBLength
0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00,
//X
0xA7, 0xFB, 0xCD, 0x4D, 0x7E, 0x43, 0x6F, 0x22, 0xBD, 0x74, 0xFA, 0x1F, 0xD7, 0x10, 0xDB, 0x8C, 0xF8, 0x29, 0xC1, 0xEC, 0x5E, 0x15, 0x1E, 0xE2, 0x84, 0x56, 0x3E, 0x54, 0x6E, 0x1D, 0x5C, 0xF6,
//Y
0x6B, 0x42, 0x21, 0xD1, 0x92, 0xEB, 0x69, 0x66, 0x56, 0xD6, 0xEC, 0x4D, 0x21, 0xB7, 0xDB, 0x3C, 0x94, 0x56, 0x8D, 0x87, 0xEB, 0x1C, 0x11, 0x0F, 0x03, 0x80, 0xF6, 0x10, 0x70, 0x73, 0x7D, 0x1D,
//D
0x5E, 0xF0, 0x2A, 0x1B, 0x34, 0xE9, 0x2B, 0x96, 0xA4, 0xAE, 0x05, 0x1D, 0x33, 0x53, 0x36, 0x39, 0x7B, 0x1F, 0xF5, 0x24, 0xA4, 0xD6, 0xBD, 0x12, 0x07, 0x3F, 0x43, 0x30, 0x70, 0x32, 0x4E, 0x5D
};

现在打电话
ECDsaCng eCDsa = new ECDsaCng( CngKey.Import(ec256PrivKB, CngKeyBlobFormat.EccPrivateBlob,
CngProvider.MicrosoftSoftwareKeyStorageProvider));

它给 System.Security.Cryptography.CryptographicException: 'The requested operation is not supported.我不明白为什么它会给出这个异常(exception)?

还有如何将 base64 编码的 ecdsa 私钥导入 MS key 存储提供程序,即假设我有以下 ec 私钥 -
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICWeuFHssg5i2vJlyMHPUb+DJnylxfbkR8KJPXfYw5ikoAoGCCqGSM49
AwEHoUQDQgAE7A4wVMLQ+orOZYcFv6mLNBbAWfffPwTTw4iroyQDcytYWT+frzl3
RiFXqC1niHgduYtGBZIbwq/48ooyL9HbkA==
-----END EC PRIVATE KEY-----

现在我如何将其导入 CNG 供应商?

编辑 - 还有什么方法可以返回这个过程,即
我知道如何从 OpenSSL(PEM FORMAT) 转换至 MS Format(RAW format)但如何做相反的意思
如何转换 MS将 ECDSA key 格式化为 OpenSSL PEM 中的 EC key 。

最佳答案

您的 key blob 以 BCRYPT_ECDSA_ 开头 公众号 _P256_MAGIC,但你想要 BCRYPT_ECDSA_ 私有(private) _P256_MAGIC(将 0x31 更改为 0x32)。

由此我们可以假设您知道如何进行转换,但由于标题更一般地询问如何进行转换,我将继续。 C# Get CngKey object from public key in text file对公钥有一个简单的(如果是hacky)答案。私钥不同,但大多很简单。

如果我们从问题中获取 PEM key ,我们可以移除“PEM 盔甲”以获得 base-64 blob。将 base-64 blob 转换为十六进制我们得到

30 77 02 01 01 04 20 25 9E B8 51 EC B2 0E 62 DA 
F2 65 C8 C1 CF 51 BF 83 26 7C A5 C5 F6 E4 47 C2
89 3D 77 D8 C3 98 A4 A0 0A 06 08 2A 86 48 CE 3D
03 01 07 A1 44 03 42 00 04 EC 0E 30 54 C2 D0 FA
8A CE 65 87 05 BF A9 8B 34 16 C0 59 F7 DF 3F 04
D3 C3 88 AB A3 24 03 73 2B 58 59 3F 9F AF 39 77
46 21 57 A8 2D 67 88 78 1D B9 8B 46 05 92 1B C2
AF F8 F2 8A 32 2F D1 DB 90

如果我们再打开 https://www.secg.org/sec1-v2.pdf C.4节我们看到
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECDomainParameters {{ SECGCurveNames }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}

通过 ASN.1 ( ITU-T X.680 ) 和 BER/DER ( ITU-T X.690 ) 规范,我们可以混合十六进制转储和该结构:
// (constructed) SEQUENCE, 119 content bytes
30 77
// INTEGER, 1 content byte, value 0x01.
02 01 01
// OCTET STRING (byte[]), 32 bytes, value 25 9E ... 98 A4
04 20
25 9E B8 51 EC B2 0E 62 DA F2 65 C8 C1 CF 51 BF
83 26 7C A5 C5 F6 E4 47 C2 89 3D 77 D8 C3 98 A4
// (constructed) CONTEXT-SPECIFIC 0, 10 content bytes
A0 0A
// OBJECT IDENTIFIER, 8 content bytes, 1.2.840.10045.3.1.7
06 08 2A 86 48 CE 3D 03 01 07
// (constructed) CONTEXT-SPECIFIC 1, 68 content bytes
A1 44
// BIT STRING, 66 content bytes, 0 unused bits, value 04 EC .. DB 90
03 42
00
04 EC 0E 30 54 C2 D0 FA 8A CE 65 87 05 BF A9 8B
34 16 C0 59 F7 DF 3F 04 D3 C3 88 AB A3 24 03 73
2B 58 59 3F 9F AF 39 77 46 21 57 A8 2D 67 88 78
1D B9 8B 46 05 92 1B C2 AF F8 F2 8A 32 2F D1 DB
90

做一个 search for 1.2.840.10045.3.1.7表明它(不出所料)是 secp256r1/NIST P-256 椭圆曲线。

BIT STRING 的内容以 04 开头,表示它是一个未压缩的 EC 点,剩下的前半部分是 X 坐标,后半部分是 Y 坐标。很好,这与私钥的 OCTET STRING 的宽度一致,这意味着该结构是有效的。

您会注意到 ASN.1 结构表示曲线标识符和公钥在技术上都是可选的。在实践中,它们被写下来,这很好,因为我们将依靠它。

将 EC 私钥 blob 转换为 CNG blob
// structure opening up to the private key (D) value.
private static readonly byte[] s_secp256R1Prefix =
{ 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20 };

// After D through the 0x04 identifying the public key is uncompressed
private static readonly byte[] s_secp256R1Infix =
{
0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
0x3D, 0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42,
0x00, 0x04
};

private static readonly byte[] s_secp256R1PrivateCngPrefix =
{ 0x45, 0x43, 0x53, 0x32, 0x20, 0x00, 0x00, 0x00 };

private static CngKey DecodeP256ECPrivateKeyBase64(string base64)
{
byte[] derBlob = Convert.FromBase64String(base64);

if (derBlob.Length == 121 &&
derBlob.Take(s_secp256R1Prefix.Length).SequenceEqual(s_secp256R1Prefix) &&
derBlob.Skip(0x20 + s_secp256R1Prefix.Length).Take(s_secp256R1Infix.Length).
SequenceEqual(s_secp256R1Infix))
{
byte[] cngBlob = new byte[2 * sizeof(uint) + 3 * 0x20];
int offset = 0;

// Header (BCRYPT_ECDSA_PRIVATE_P256_MAGIC and 0x00000020)
Buffer.BlockCopy(
s_secp256R1PrivateCngPrefix,
0,
cngBlob,
offset,
s_secp256R1PrivateCngPrefix.Length);

offset += s_secp256R1PrivateCngPrefix.Length;

// X and Y
Buffer.BlockCopy(
derBlob,
s_secp256R1Prefix.Length + 0x20 + s_secp256R1Infix.Length,
cngBlob,
offset,
2 * 0x20);

offset += 2 * 0x20;

Buffer.BlockCopy(
derBlob,
s_secp256R1Prefix.Length,
cngBlob,
offset,
0x20);

offset += 0x20;
Debug.Assert(offset == cngBlob.Length);

return CngKey.Import(cngBlob, CngKeyBlobFormat.EccPrivateBlob);
}

throw new InvalidOperationException();
}

关于openssl - 微软压缩天然气 |如何将 PEM 编码的 ECDSA 私钥导入 MS Key Storage Provider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50080937/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com