X9ECParameters curve = NistNamedCurves.GetByName("P-521");
ECDomainParameters ecparam = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed());
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.Init(new ECKeyGenerationParameters(ecparam, new SecureRandom()));
AsymmetricCipherKeyPair ackp1 = generator.GenerateKeyPair();
AsymmetricCipherKeyPair ackp2 = generator.GenerateKeyPair();
然后,
ECDHWithKdfBasicAgreement agreement = new ECDHWithKdfBasicAgreement("2.16.840.1.101.3.4.42", new ECDHKekGenerator(DigestUtilities.GetDigest("SHA256")));
agreement.Init(ackp1.PrivateKey);
BigInteger agInt = agreement.CalculateAgreement(ackp2.PublicKey);
byte[] aeskey = agInt.ToByteArrayUnsigned();
这样做没有产生任何错误,我在交换另一对公钥/私钥时验证了“aeskey”是相同的。
我在谷歌找到了这种用法的零例子。 代码对我来说似乎是正确的,不得不为AES256提供Der OID(而不是字符串“AES256”,它在CalculateAgreement中炸弹)让我怀疑我做错了什么。
答案 0 :(得分:1)
虽然我不确定你的OID是否正确,但你似乎朝着正确的方向前进。它看起来非常可疑,快速的互联网搜索没有显示任何预期的结果。
根据RFC 2631:
算法是CEK包装算法的ASN.1算法OID 将使用此KEK。请注意,这不是一个 AlgorithmIdentifier,但只是OBJECT IDENTIFIER。没有 使用参数。
因此OID的使用是正确的,但OID本身可能不正确。我希望有一个OID表明例如在CBC或GCM模式下的AES。如果你在两边使用无效的OID,它将不会显示,它只用于生成你的密钥,而不是在你真正使用它时。
请注意,Bouncy Castle的代码似乎容易受到Java DH代码中的错误的攻击:BigInteger
始终以最小字节数编码。但是,任何正常密钥协议生成的密钥都是特定数量的字节,包括初始00
值字节。这意味着只调用BigInteger.ToByteArray
将在大约256字节中生成错误的字节数(或非法值),因为在转换期间前导零将丢失。同样,这不会在测试期间对同一系统上的相同代码产生任何差异。但用于对抗其他系统的DH会偶尔失败(我已将此报告给Bouncy for Java并且已经确认,然后在Bouncy 1.50中修复)...
答案 1 :(得分:1)
ECDHWithKdfBasicAgreement有点尴尬,因为它是只存在于Java构建的JCE部分中的东西的端口。正如@owlstead指出你需要处理BigInteger / byte []转换。在这种情况下,使用最新代码,您可以使用:
int keyLen = GeneratorUtilities.GetDefaultKeySize(algorithm) / 8;
byte[] key = BigIntegers.AsUnsignedByteArray(keyLen, agInt);
或者当然,只需将其填充到您所知道的尺寸即可。我认为AES256的东西也在最新代码中修复了。代码现在在github上(https://github.com/bcgit/bc-csharp),但C#的新beta版本(最后)也只有一两天了。