6

我生成一个 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 编码?如果是这样,也许我应该改用它。

4

1 回答 1

5

我可以这样做:

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 来验证签名。

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

于 2013-07-03T12:43:48.647 回答