使用 python 创建密钥并在 .net 中使用它
Create keys with python and use it in .net
我尝试使用 python 包 ecdsa 创建密钥,将其导出到 der 并在 .Net 下与 BouncyCastle 一起使用它们(反之亦然)。
这是我在 Python 中的代码:
import base64
from ecdsa.keys import SigningKey
from ecdsa.curves import NIST521p, NIST384p, NIST256p
@classmethod
def CreateKey(self) -> SigningKey:
privateKey = SigningKey.generate(NIST256p)
return privateKey
@classmethod
def GetPublicKey(self, privateKey: SigningKey) -> str:
publicKey = privateKey.get_verifying_key()
der = publicKey.to_der()
return base64.b64encode(der)
我得到两个要导入 .Net 的字符串:
Const plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Const plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Dim keyPriv = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Priv))
Dim keyPub = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Pub))
但我得到一个例外:
Test method LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest threw exception:
System.ArgumentException: Wrong number of elements in sequence
Parametername: seq
Result StackTrace:
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo..ctor(Asn1Sequence seq) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 18.
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo.GetInstance(Object obj) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 42.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Asn1Object asn1Object) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 196.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Byte[] encryptedPrivateKeyInfoData) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 182.
bei LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest() in ...
知道我做错了什么吗?
我不熟悉 python 库,但我猜到了格式,下面的代码将解析示例数据:
using System;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
namespace BCTests
{
class MainClass
{
public static void Main(string[] args)
{
var plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var pubKeyBytes = Base64.Decode(plainDerBase64Pub);
var privKeyBytes = Base64.Decode(plainDerBase64Priv);
var pubKey = PublicKeyFactory.CreateKey(pubKeyBytes);
var privKeyStruct = ECPrivateKeyStructure.GetInstance(privKeyBytes);
var x9 = ECNamedCurveTable.GetByName("P-256");
var ec = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
var privKey = new ECPrivateKeyParameters(privKeyStruct.GetKey(), ec);
}
}
}
pubKey 和 privKey 然后是 ECPublicKeyParameters 和 ECPrivateKeyParameters,您可以将它们用于各种算法。
请注意,DER 是一种编码,而不是一种格式。对于 public 键,python 代码生成 SubjectPublicKeyInfo,这是 public 键的标准 X.509 格式。
应该有生成 PrivateKeyInfo 的私钥选项(或使用密码的 EncryptedPrivateKeyInfo),这两种格式都是 PKCS#8 标准。如果 python 代码可以输出其中之一,那么解码私钥会更容易,只需 PrivateKeyFactory.CreateKey(bytes) 或 .DecryptKey(password, bytes).
我尝试使用 python 包 ecdsa 创建密钥,将其导出到 der 并在 .Net 下与 BouncyCastle 一起使用它们(反之亦然)。
这是我在 Python 中的代码:
import base64
from ecdsa.keys import SigningKey
from ecdsa.curves import NIST521p, NIST384p, NIST256p
@classmethod
def CreateKey(self) -> SigningKey:
privateKey = SigningKey.generate(NIST256p)
return privateKey
@classmethod
def GetPublicKey(self, privateKey: SigningKey) -> str:
publicKey = privateKey.get_verifying_key()
der = publicKey.to_der()
return base64.b64encode(der)
我得到两个要导入 .Net 的字符串:
Const plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Const plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g=="
Dim keyPriv = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Priv))
Dim keyPub = PrivateKeyFactory.DecryptKey({}, Base64.Decode(plainDerBase64Pub))
但我得到一个例外:
Test method LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest threw exception:
System.ArgumentException: Wrong number of elements in sequence
Parametername: seq
Result StackTrace:
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo..ctor(Asn1Sequence seq) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 18.
bei Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo.GetInstance(Object obj) in C:\BouncyCastle\crypto\src\asn1\pkcs\EncryptedPrivateKeyInfo.cs:Zeile 42.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Asn1Object asn1Object) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 196.
bei Org.BouncyCastle.Security.PrivateKeyFactory.DecryptKey(Char[] passPhrase, Byte[] encryptedPrivateKeyInfoData) in C:\BouncyCastle\crypto\src\security\PrivateKeyFactory.cs:Zeile 182.
bei LicenseProtectorTest.KeyManagementTest.ImportKeyFromPythonTest() in ...
知道我做错了什么吗?
我不熟悉 python 库,但我猜到了格式,下面的代码将解析示例数据:
using System;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
namespace BCTests
{
class MainClass
{
public static void Main(string[] args)
{
var plainDerBase64Pub = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var plainDerBase64Priv = "MHcCAQEEIKjIPCG9CGMunu34jXnDZg1LmNYrcJo8EqzKbRu2E24MoAoGCCqGSM49AwEHoUQDQgAEyJW32bO4wswhE9ZC5klCjRNDJQSB0lIBphe9wIa/W2n3fBJ0cDpSpy9qlq2L6sa4W5lgRHYD9IyfETom6YOH/g==";
var pubKeyBytes = Base64.Decode(plainDerBase64Pub);
var privKeyBytes = Base64.Decode(plainDerBase64Priv);
var pubKey = PublicKeyFactory.CreateKey(pubKeyBytes);
var privKeyStruct = ECPrivateKeyStructure.GetInstance(privKeyBytes);
var x9 = ECNamedCurveTable.GetByName("P-256");
var ec = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
var privKey = new ECPrivateKeyParameters(privKeyStruct.GetKey(), ec);
}
}
}
pubKey 和 privKey 然后是 ECPublicKeyParameters 和 ECPrivateKeyParameters,您可以将它们用于各种算法。
请注意,DER 是一种编码,而不是一种格式。对于 public 键,python 代码生成 SubjectPublicKeyInfo,这是 public 键的标准 X.509 格式。
应该有生成 PrivateKeyInfo 的私钥选项(或使用密码的 EncryptedPrivateKeyInfo),这两种格式都是 PKCS#8 标准。如果 python 代码可以输出其中之一,那么解码私钥会更容易,只需 PrivateKeyFactory.CreateKey(bytes) 或 .DecryptKey(password, bytes).