使用BouncyCastle在C#中重新创建密钥(ECPublicKeyParameters)

时间:2013-07-03 04:33:57

标签: c# bouncycastle ecdsa

我按如下方式生成AsymmetricCipherKeyPair:

string curveName = "P-521";
X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
ECDomainParameters ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH");
g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();

我的目的是提取公钥和私钥,然后再重建密钥。我首先按如下方式提取密钥:

byte[] privateKey = ((ECPrivateKeyParameters)aKeyPair.Private).D.ToByteArray();
byte[] publicKey = ((ECPublicKeyParameters)aKeyPair.Public).Q.GetEncoded();

如何重新创建公钥和私钥参数以便我可以使用它们?在这个例子中,我确实重新创建了私钥,然后对数据字节数组进行了签名。

public static byte[] SignData(byte[] data, byte[] privateKey)
{
    string curveName = "P-521";
    X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
    ECDomainParameters ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
    ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
    BigInteger biPrivateKey = new BigInteger(privateKey);
    ECPrivateKeyParameters keyParameters = new ECPrivateKeyParameters(biPrivateKey, ecSpec);
    signer.Init(true, keyParameters);
    signer.BlockUpdate(data, 0, data.Length);
    return signer.GenerateSignature();
}

虽然它感觉像是一个真正的黑客,但它的工作正常。如何使用公钥执行此操作?我将变量xxx设置为(ECPublicKeyParameters)aKeyPair.Public,我可以使用下面的代码来验证签名。请注意,我可以直接使用xxx,但重点是将xxx序列化然后再输入,因此,此代码实际上会转换xxx变量并创建一个新的变量,该变量存储在xx中。然后我使用xx进行验证(这表明我可以将密钥往返)。

var xx = PublicKeyFactory.CreateKey(Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(xxx).GetDerEncoded());
ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
signer.Init(false, xx);
signer.BlockUpdate(data, 0, data.Length);
return signer.VerifySignature(signature);

我原本希望能从Q.GetEncoded()创建密钥(xx),就像我为私钥做的那样。

有没有更好的方法来重建私钥?还使用ASN.1编码?如果是这样,也许我应该使用它。

1 个答案:

答案 0 :(得分:3)

我可以这样做:

string curveName = "P-521";
X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
FpCurve c = (FpCurve)ecP.Curve;
ECFieldElement x = new FpFieldElement(c.Q, xxx.Q.X.ToBigInteger());
ECFieldElement y = new FpFieldElement(c.Q, xxx.Q.Y.ToBigInteger());
ECPoint q = new FpPoint(c, x, y);
ECPublicKeyParameters xxpk = new ECPublicKeyParameters("ECDH", q, SecObjectIdentifiers.SecP521r1);

然后,我可以使用xxpk来验证签名。

免责声明:我并不是说这是最好的方法,只是它有效!