当前位置: 首页 > 知识库问答 >
问题:

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

厍华清
2023-03-14

我生成一个不对称密码密钥对,如下所示:

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个答案

牟黎昕
2023-03-14

我可以这样做,如下所示:

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

免责声明:我并不声称这是最好的方法,只是它的作品!

 类似资料:
  • 我需要在C#中加密数据,以便将其传递给Java。Java代码属于第三方,但我得到了相关的源代码,因此我决定,由于Java使用Bouncy Castle库,所以我将使用C#端口。 解密工作正常。但是,解密仅在使用私钥使用encrypt时有效,而不是使用公钥。使用公钥时,解密失败,出现。 编辑: 我还添加了一个单元测试,它证明公钥等于从私钥中提取的公钥:

  • 刚开始使用PGP,我正在尝试通过C#控制台应用程序加密一个文件。在我的研究中,似乎BouncyCastle是一个更受欢迎的应用。我找到了下面的文章,它看起来很好,除了我只有公钥。http://burnignorance.com/c-coding-tips/pgp-encryption-decryption-in-c/

  • 以前有人这么做过吗?谢谢

  • 我试图签署一个Android应用程序,但显然原始的keystore文件是不可用的。我所得到的只有以下几点: 私钥md5 0123456789abcdef0123456789abcdef<--虚构值,但 证书md5 fedcba9876543210fedcba9876543210<-原始为32个十六进制数字 已签署的生产Android应用程序 是否有任何方法可以从这些资产中重新创建一个keystor

  • 根据给定的私钥生成密钥对,并在保存后返回其ID。 调用: web3.shh.addPrivateKey(privateKey, [callback]) 参数: privateKey:String - 要导入的私钥,16进制字符串 callback:Function - 可选的回调函数,其第一个参数为错误对象,第二个对象为返回结果 返回值: String - 成功时返回ID,失败则返回错误信息 示