private void DoTestAgreement() { IAsymmetricCipherKeyPairGenerator kpGen = new X25519KeyPairGenerator(); kpGen.Init(new X25519KeyGenerationParameters(Random)); AsymmetricCipherKeyPair kpA = kpGen.GenerateKeyPair(); AsymmetricCipherKeyPair kpB = kpGen.GenerateKeyPair(); X25519Agreement agreeA = new X25519Agreement(); agreeA.Init(kpA.Private); byte[] secretA = new byte[agreeA.AgreementSize]; agreeA.CalculateAgreement(kpB.Public, secretA, 0); X25519Agreement agreeB = new X25519Agreement(); agreeB.Init(kpB.Private); byte[] secretB = new byte[agreeB.AgreementSize]; agreeB.CalculateAgreement(kpA.Public, secretB, 0); if (!AreEqual(secretA, secretB)) { Fail("X25519 agreement failed"); } }
/// <summary> /// Derives a shared secret key from a private key and another persons public key /// </summary> /// <param name="myPrivateKey">the private key which is used</param> /// <param name="otherPartyPublicKey">the public key of the other person</param> /// <returns></returns> public byte[] DeriveKey(byte[] myPrivateKey, byte[] otherPartyPublicKey) { X25519PrivateKeyParameters privateKey; try { privateKey = (X25519PrivateKeyParameters)CreateAsymmetricKeyParameterFromPrivateKeyInfo(myPrivateKey); } catch (InvalidCastException exception) { string message = "Private Key Import Failed!\n" + $"{exception.Message}.\n" + "The contents of the source do not represent a valid X25519 key parameter\n" + "Verify that the key is not corrupted.\n" + "- or - Verify that the correct key is selected."; throw new CryptoException(message, exception); } var a1 = new X25519Agreement(); a1.Init(privateKey); byte[] k1 = new byte[a1.AgreementSize]; X25519PublicKeyParameters publicKey = null; try { publicKey = (X25519PublicKeyParameters)CreateAsymmetricKeyParameterFromPublicKeyInfo(otherPartyPublicKey); } catch (InvalidCastException exception) { string message = "Public Key Import Failed!\n" + $"{exception.Message}.\n" + "The contents of the source do not represent a valid X25519 public key parameter\n" + "Verify that the public key is not corrupted.\n" + "- or - Verify that the correct key is selected."; throw new CryptoException(message, exception); } a1.CalculateAgreement(publicKey, k1, 0); return(k1); }
private byte[] ECDH_GenerateSecret(JWK key, EncryptMessage msg) { JWK epk; if ((key.AsString("kty") != "EC") && (key.AsString("kty") != "OKP")) { throw new JoseException("Not an EC or OKP Key"); } if (_mSenderKey != null) { epk = _mSenderKey; } else { CBORObject epkT = FindAttr("epk", msg); if (epkT == null) { throw new JoseException("No Ephemeral key"); } epk = new JWK(epkT); } if (epk.AsString("crv") != key.AsString("crv")) { throw new JoseException("not a match of curves"); } if (key.AsString("kty") == "EC") { // Get the curve X9ECParameters p = NistNamedCurves.GetByName(key.AsString("crv")); ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H); Org.BouncyCastle.Math.EC.ECPoint pubPoint = p.Curve.CreatePoint(epk.AsBigInteger("x"), epk.AsBigInteger("y")); ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters); ECPrivateKeyParameters priv = new ECPrivateKeyParameters(key.AsBigInteger("d"), parameters); IBasicAgreement e1 = new ECDHBasicAgreement(); e1.Init(priv); BigInteger k1 = e1.CalculateAgreement(pub); return(k1.ToByteArrayUnsigned()); } else { switch (epk.AsString("crv")) { case "X25519": { X25519PublicKeyParameters pub = new X25519PublicKeyParameters(epk.AsBytes("x"), 0); X25519PrivateKeyParameters priv = new X25519PrivateKeyParameters(key.AsBytes("d"), 0); X25519Agreement agree = new X25519Agreement(); agree.Init(priv); byte[] secret = new byte[32]; agree.CalculateAgreement(pub, secret, 0); return(secret); } default: throw new JoseException("Unsupported curve"); } } }