Exemple #1
0
        protected virtual byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey,
                                                             ECPrivateKeyParameters privateKey)
        {
            ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();

            basicAgreement.Init(privateKey);
            BigInteger agreement = basicAgreement.CalculateAgreement(publicKey);

            return(BigIntegers.AsUnsignedByteArray(agreement));
        }
        /// <summary>
        /// Creates symmetric key from sender's public key and own key pair
        /// </summary>
        /// <param name="publicKeyBytes"></param>
        /// <returns></returns>
        protected byte[] GetSymmetricKey(byte[] publicKeyBytes)
        {
            ECPublicKeyParameters publicKey = new ECPublicKeyParameters(X9.Curve.DecodePoint(publicKeyBytes), EcSpec);

            var agree = new ECDHBasicAgreement();

            agree.Init(KeyPair.Private);
            BigInteger z = agree.CalculateAgreement((AsymmetricKeyParameter)publicKey);

            return(BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z));
        }
Exemple #3
0
        public static byte[] Agree(PrivateKey privateKey, PublicKey publicKey)
        {
            ECPrivateKeyParameters privateKeyParameters = WrapPrivateKey(privateKey);
            ECPublicKeyParameters  publicKeyParameters  = WrapPublicKey(publicKey);

            ECDHBasicAgreement agreement = new ECDHBasicAgreement();

            agreement.Init(privateKeyParameters);

            byte[] agreementBytes = agreement.CalculateAgreement(publicKeyParameters).ToByteArray();
            return(agreementBytes.Length > 32 ? agreementBytes.Slice(agreementBytes.Length - 32, 32) : agreementBytes.PadLeft(32));
        }
        public static byte[] GetSharedSecret(AsymmetricCipherKeyPair localKeyWithPrivate, byte[] remotePublicKeyDerEncoded)
        {
            var remotePublicKey = PublicKeyFactory.CreateKey(remotePublicKeyDerEncoded);
            var agreement       = new ECDHBasicAgreement();

            agreement.Init(localKeyWithPrivate.Private);
            using (var sha = SHA256.Create()) {
                // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened.
                // So hash it.
                return(sha.ComputeHash(agreement.CalculateAgreement(remotePublicKey).ToByteArray()));
            }
        }
        /// <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)
        {
            ECPrivateKeyParameters privKey = null;

            try
            {
                privKey = (ECPrivateKeyParameters)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 EC 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 ECDHBasicAgreement();

            a1.Init(privKey);

            ECPublicKeyParameters pubKey = null;

            try
            {
                pubKey = (ECPublicKeyParameters)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 EC key parameter\n" +
                                 "Verify that the key is not corrupted.\n" +
                                 "- or - Verify that the correct key is selected.";
                throw new CryptoException(message, exception);
            }

            BigInteger k = null;

            try
            {
                k = a1.CalculateAgreement(pubKey);
            }
            catch (InvalidOperationException exception)
            {
                string message = "Key Deriviation Failed!\n" +
                                 $"{exception.Message}.\n" +
                                 "Different EC curves were used to create the public keys.";
                throw new CryptoException(message, exception);
            }

            return(k.ToByteArrayUnsigned());
        }
        public string GenerateSharedSecretHex(string pubKeyHex)
        {
            var pubKeyBytes     = pubKeyHex.HexToByteArray();
            var q               = _curve.Curve.DecodePoint(pubKeyBytes);
            var remotePublicKey = new ECPublicKeyParameters("ECDH", q, _domain);
            var agreement       = new ECDHBasicAgreement();

            agreement.Init(_key.Private);

            var basicAgreementResult = agreement.CalculateAgreement(remotePublicKey);

            return(BigIntegers.AsUnsignedByteArray(agreement.GetFieldSize(), basicAgreementResult).ToHex(true));
        }
Exemple #7
0
        public byte[] Old()
        {
            ECPrivateKeyParameters privateKeyParameters = BouncyCrypto.WrapPrivateKey(privateKey);
            ECPublicKeyParameters  publicKeyParameters  = BouncyCrypto.WrapPublicKey(ephemeral);
            IBasicAgreement        agreement            = new ECDHBasicAgreement();

            agreement.Init(privateKeyParameters);

            BigInteger zAsInteger = agreement.CalculateAgreement(publicKeyParameters);

            byte[] bytes = BigIntegers.AsUnsignedByteArray(32, zAsInteger);
            return(bytes);
        }
        BigInteger ECDHAgree(byte[] publicKey, byte[] privateKey)
        {
            var domain = SecNamedCurves.GetByName("secp160r1");
            ECDHBasicAgreement     agreement  = new ECDHBasicAgreement();
            BigInteger             privKeyInt = new BigInteger(privateKey);
            ECDomainParameters     parm       = new ECDomainParameters(domain.Curve, domain.G, domain.N);
            ECPrivateKeyParameters privKey    = new ECPrivateKeyParameters(privKeyInt, parm);

            agreement.Init(privKey);
            var pt = Key.Curve.Curve.DecodePoint(publicKey);
            ECPublicKeyParameters pubParams = new ECPublicKeyParameters(pt, parm);

            return(agreement.CalculateAgreement(pubParams));
        }
Exemple #9
0
        public static byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
        {
            ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();

            basicAgreement.Init(privateKey);
            BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey);

            /*
             * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by
             * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for
             * any given field; leading zeros found in this octet string MUST NOT be truncated.
             */
            return(BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue));
        }
Exemple #10
0
        internal static byte[] ComputeSharedSecret(ECPrivateKeyParameters privateKey, ECPublicKeyParameters publicKey)
        {
            if (!KeyParser.ValidateCurve(privateKey))
            {
                throw new ArgumentException("Private key not on NIST P-256 curve", "privateKey");
            }
            if (!KeyParser.ValidateCurve(publicKey))
            {
                throw new ArgumentException("Public key not on NIST P-256 curve", "publicKey");
            }

            var ecdhAgreement = new ECDHBasicAgreement();

            ecdhAgreement.Init(privateKey);
            BigInteger secret = ecdhAgreement.CalculateAgreement(publicKey);

            return(BigIntegers.AsUnsignedByteArray(SharedSecretSize, secret));
        }
Exemple #11
0
        public static byte[] GenerateSharedSecret(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
        {
            var agreement = new ECDHBasicAgreement();

            agreement.Init(privateKey);
            var z            = agreement.CalculateAgreement(publicKey);
            var sharedSecret = new byte[32];
            var zArr         = z.ToByteArrayUnsigned();

            // zero the output array
            for (var i = 0; i < sharedSecret.Length; i++)
            {
                sharedSecret[i] = 0;
            }

            Array.Copy(zArr, 0, sharedSecret, 32 - zArr.Length, zArr.Length);

            return(sharedSecret);
        }
Exemple #12
0
        /// <summary>
        /// Called by client to get his ephemaral ECC keys
        /// TODO: get information about which ECC curve should be used
        /// </summary>
        /// <param name="version"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data, X509Certificate serverCertificate)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (data.Length < 4)
            {
                throw new ArgumentException(nameof(data));
            }

            //if (data[0] != 3 || data[1] != 0 || data[2] != 23)
            if (data[0] != 3 || data[1] != 0)
            {
                throw new ArgumentException(nameof(data));
            }

            //if (data[3] != 65 || data[4] > data.Length - 4)
            if (data[4] > data.Length - 4)
            {
                throw new ArgumentException(nameof(data));
            }


            // Extract the public key from the data
            byte[] ecPointData = new byte[data[3]];
            Buffer.BlockCopy(data, 4, ecPointData, 0, ecPointData.Length);

            ushort curveNameId    = (ushort)(data[1] << 8 | data[2]);
            var    ecPoint        = this.ObtainCurveNameAndPoint(curveNameId, ecPointData);
            var    theirPublicKey = new ECPublicKeyParameters(ecPoint, this.domainParameters);

            // Calculate the actual agreement
            var agreement = new ECDHBasicAgreement();

            agreement.Init(this.privateKey);
            this.preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), ecPoint.Curve.FieldSize / 8);

            var signature = new byte[data.Length - 4 - data[3]];

            Buffer.BlockCopy(data, 4 + data[3], signature, 0, signature.Length);
            return(signature);
        }
Exemple #13
0
        static byte[] GenerateAESKey(ECPublicKeyParameters bobPublicKey,
                                     AsymmetricKeyParameter alicePrivateKey)
        {
            ECDHBasicAgreement aKeyAgree = new ECDHBasicAgreement();

            aKeyAgree.Init(alicePrivateKey);
            byte[] sharedSecret = aKeyAgree.CalculateAgreement(bobPublicKey).ToByteArray();

            // make sure each part has the correct and same size
            ResizeRight(ref sharedSecret, 66); // 66 is the desired key size

            Sha256Digest digest = new Sha256Digest();

            byte[] symmetricKey = new byte[digest.GetDigestSize()];
            digest.BlockUpdate(sharedSecret, 0, sharedSecret.Length);
            digest.DoFinal(symmetricKey, 0);

            return(symmetricKey);
        }
Exemple #14
0
        public static byte[] AsymmetricDecrypt(byte[] data, ref AsymmetricCipherKeyPair keypair)
        {
            //create the key agreement
            ECDHBasicAgreement ag = new ECDHBasicAgreement();

            ag.Init(keypair.Private);

            //calculate the shared secret key
            BigInteger a = ag.CalculateAgreement(keypair.Public);

            byte[] secret = a.ToByteArray();

            //derive the symmetric encryption key
            ECDHKekGenerator topkek = new ECDHKekGenerator(DigestUtilities.GetDigest("SHA256"));

            topkek.Init(new DHKdfParameters(NistObjectIdentifiers.Aes, secret.Length, secret));
            byte[] symKey = new byte[DigestUtilities.GetDigest("SHA256").GetDigestSize()];
            topkek.GenerateBytes(symKey, 0, symKey.Length);

            //decrypt the data
            KeyParameter    parm   = ParameterUtilities.CreateKeyParameter("DES", symKey);
            IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/ISO7816_4PADDING");

            cipher.Init(false, parm);
            byte[] ret = null;
            try
            {
                ret = cipher.DoFinal(data);
            }
            catch (Exception e)
            {
                if (e != null)
                {
                    return(null);
                }
            }

            //erase the keys
            Eraser.SecureErase(secret);
            Eraser.SecureErase(symKey);

            return(ret);
        }
Exemple #15
0
        public static EncryptionResult EncryptMessage(byte[] userKey, byte[] userSecret, byte[] data, ushort padding = 0, bool randomisePadding = false)
        {
            var Random = new SecureRandom();
            var Salt   = new byte[16];

            Random.NextBytes(Salt);

            var Curve     = ECNamedCurveTable.GetByName("prime256v1");
            var Spec      = new ECDomainParameters(Curve.Curve, Curve.G, Curve.N, Curve.H, Curve.GetSeed());
            var Generator = new ECKeyPairGenerator();

            Generator.Init(new ECKeyGenerationParameters(Spec, new SecureRandom()));

            var KeyPair            = Generator.GenerateKeyPair();
            var AgreementGenerator = new ECDHBasicAgreement();

            AgreementGenerator.Init(KeyPair.Private);

            var IKM       = AgreementGenerator.CalculateAgreement(new ECPublicKeyParameters(Spec.Curve.DecodePoint(userKey), Spec));
            var PRK       = GenerateHKDF(userSecret, IKM.ToByteArrayUnsigned(), Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32);
            var PublicKey = ((ECPublicKeyParameters)KeyPair.Public).Q.GetEncoded(false);
            var CEK       = GenerateHKDF(Salt, PRK, CreateInfoChunk("aesgcm", userKey, PublicKey), 16);
            var Nonce     = GenerateHKDF(Salt, PRK, CreateInfoChunk("nonce", userKey, PublicKey), 12);

            if (randomisePadding && padding > 0)
            {
                padding = Convert.ToUInt16(Math.Abs(Random.NextInt()) % (padding + 1));
            }
            var Input = new byte[padding + 2 + data.Length];

            Buffer.BlockCopy(ConvertInt(padding), 0, Input, 0, 2);
            Buffer.BlockCopy(data, 0, Input, padding + 2, data.Length);
            var Cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");

            Cipher.Init(true, new AeadParameters(new KeyParameter(CEK), 128, Nonce));
            var Message = new byte[Cipher.GetOutputSize(Input.Length)];

            Cipher.DoFinal(Input, 0, Input.Length, Message, 0);
            return(new EncryptionResult {
                Salt = Salt, Payload = Message, PublicKey = PublicKey
            });
        }
Exemple #16
0
 public virtual Task <byte[]> SharedSecret(ECDSAPublicKey Pbk)
 {
     return(Task.Run(() =>
     {
         lock (Cache)
         {
             var clipped = Pbk.FingerprintEncodedClipped;
             if (Cache.ContainsKey(clipped))
             {
                 return Cache[clipped];
             }
         }
         var agree = new ECDHBasicAgreement();
         agree.Init(PrivateKey);
         var result = agree.CalculateAgreement(Pbk.PublicKey).ToByteArrayUnsigned();
         result = CryptoHelper.Sha256(result);
         lock (Cache)
             Cache[Pbk.FingerprintEncodedClipped] = result;
         return result;
     }));
 }
Exemple #17
0
        public static byte[] GetSharedSecret(byte[] localPrivateKeyBytes, byte[] remotePublicKeyBytes)
        {
            var             curve = NistNamedCurves.GetByName("P-256");
            var             dom   = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H);
            ECKeyParameters privateKeyParameters = new ECPrivateKeyParameters(new BigInteger(1, localPrivateKeyBytes), dom);

            var q = curve.Curve.DecodePoint(new byte[] { 0x04 }.Concat(remotePublicKeyBytes).ToArray());

            ECKeyParameters publicKeyParameters = new ECPublicKeyParameters(q, dom);

            var agreement = new ECDHBasicAgreement();

            agreement.Init(privateKeyParameters);

            using (var sha = SHA256.Create())
            {
                // CalculateAgreement returns a BigInteger, whose length is variable, and bits are not whitened, so hash it.
                var temp = agreement.CalculateAgreement(publicKeyParameters).ToByteArray();
                return(sha.ComputeHash(temp));
            }
        }
Exemple #18
0
        public override void ProcessClientKeys(ProtocolVersion version, ProtocolVersion clientVersion, CertificatePrivateKey privateKey, byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length < 1)
            {
                throw new ArgumentException("data");
            }

            byte[] ecPointData = new byte[data[0]];
            Buffer.BlockCopy(data, 1, ecPointData, 0, ecPointData.Length);
            ECPoint ecPoint = _domainParameters.Curve.DecodePoint(ecPointData);
            ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, _domainParameters);

            // Calculate the actual agreement
            ECDHBasicAgreement agreement = new ECDHBasicAgreement();

            agreement.Init(_privateKey);
            _preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32);
        }
Exemple #19
0
        private static EncryptionResult EncryptMessage(byte[] userKey, byte[] userSecret, byte[] data,
                                                       ushort padding = 0, bool randomisePadding = false)
        {
            SecureRandom random = new SecureRandom();

            byte[] salt = new byte[16];
            random.NextBytes(salt);
            X9ECParameters     curve     = ECNamedCurveTable.GetByName("prime256v1");
            ECDomainParameters spec      = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed());
            ECKeyPairGenerator generator = new ECKeyPairGenerator();

            generator.Init(new ECKeyGenerationParameters(spec, new SecureRandom()));
            AsymmetricCipherKeyPair keyPair            = generator.GenerateKeyPair();
            ECDHBasicAgreement      agreementGenerator = new ECDHBasicAgreement();

            agreementGenerator.Init(keyPair.Private);
            BigInteger ikm = agreementGenerator.CalculateAgreement(new ECPublicKeyParameters(spec.Curve.DecodePoint(userKey), spec));

            byte[] prk       = GenerateHkdf(userSecret, ikm.ToByteArrayUnsigned(), Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32);
            byte[] publicKey = ((ECPublicKeyParameters)keyPair.Public).Q.GetEncoded(false);
            byte[] cek       = GenerateHkdf(salt, prk, CreateInfoChunk("aesgcm", userKey, publicKey), 16);
            byte[] nonce     = GenerateHkdf(salt, prk, CreateInfoChunk("nonce", userKey, publicKey), 12);
            if (randomisePadding && padding > 0)
            {
                padding = Convert.ToUInt16(Math.Abs(random.NextInt()) % (padding + 1));
            }
            byte[] input = new byte[padding + 2 + data.Length];
            Buffer.BlockCopy(ConvertInt(padding), 0, input, 0, 2);
            Buffer.BlockCopy(data, 0, input, padding + 2, data.Length);
            IBufferedCipher cipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");

            cipher.Init(true, new AeadParameters(new KeyParameter(cek), 128, nonce));
            byte[] message = new byte[cipher.GetOutputSize(input.Length)];
            cipher.DoFinal(input, 0, input.Length, message, 0);
            return(new EncryptionResult()
            {
                Salt = salt, Payload = message, PublicKey = publicKey
            });
        }
        private (byte[], byte[]) ExtractSecretAndContext(ECPublicKeyParameters senderPublicKey, ECPublicKeyParameters receiverPublicKey, ECPrivateKeyParameters receiverPrivateKey)
        {
            IBasicAgreement aKeyAgree = new ECDHBasicAgreement();

            aKeyAgree.Init(receiverPrivateKey);
            byte[] sharedSecret = aKeyAgree.CalculateAgreement(senderPublicKey).ToByteArrayUnsigned();

            byte[] receiverKeyBytes     = AddLengthPrefix(receiverPublicKey.Q.GetEncoded());
            byte[] senderPublicKeyBytes = AddLengthPrefix(senderPublicKey.Q.GetEncoded());

            byte[] context = new byte[keyLabel.Length + 1 + receiverKeyBytes.Length + senderPublicKeyBytes.Length];

            int destinationOffset = 0;

            Array.Copy(keyLabel, 0, context, destinationOffset, keyLabel.Length);
            destinationOffset += keyLabel.Length + 1;
            Array.Copy(receiverKeyBytes, 0, context, destinationOffset, receiverKeyBytes.Length);
            destinationOffset += receiverKeyBytes.Length;
            Array.Copy(senderPublicKeyBytes, 0, context, destinationOffset, senderPublicKeyBytes.Length);

            return(sharedSecret, context);
        }
Exemple #21
0
        public new void InitiateEncryption(byte[] serverKey, byte[] randomKeyToken)
        {
            try
            {
                ECPublicKeyParameters remotePublicKey = (ECPublicKeyParameters)
                                                        PublicKeyFactory.CreateKey(serverKey);

                ECDHBasicAgreement agreement = new ECDHBasicAgreement();
                agreement.Init(Session.CryptoContext.ClientKey.Private);
                byte[] secret;
                using (var sha = SHA256.Create())
                {
                    secret = sha.ComputeHash(randomKeyToken.Concat(agreement.CalculateAgreement(remotePublicKey).ToByteArrayUnsigned()).ToArray());
                }

                // Create a decrytor to perform the stream transform.
                IBufferedCipher decryptor = CipherUtilities.GetCipher("AES/CFB8/NoPadding");
                decryptor.Init(false, new ParametersWithIV(new KeyParameter(secret), secret.Take(16).ToArray()));

                IBufferedCipher encryptor = CipherUtilities.GetCipher("AES/CFB8/NoPadding");
                encryptor.Init(true, new ParametersWithIV(new KeyParameter(secret), secret.Take(16).ToArray()));

                Session.CryptoContext = new CryptoContext
                {
                    Decryptor     = decryptor,
                    Encryptor     = encryptor,
                    UseEncryption = true,
                    Key           = secret
                };

                Thread.Sleep(1250);
                McpeClientToServerHandshake magic = new McpeClientToServerHandshake();
                SendPacket(magic);
            }
            catch (Exception e)
            {
                Log.Error("Initiate encryption", e);
            }
        }
Exemple #22
0
        public override string ComputeSharedSecret(string otherKey, bool isBase64 = true)
        {
            byte[] blob = (isBase64 ? Convert.FromBase64String(otherKey) : Encoding.UTF8.GetBytes(otherKey));

            // the shared secret is the x-coordinate of a point on the EC. the point
            // is calculated by multiplying the remote entity's public key (which itself is
            // a point on the curve) by our private key (an integer value).
            // the following calculation follows the code example here:
            // https://stackoverflow.com/questions/15430784/
            PrivateKeyInfo         info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(_keyPair.Private);
            ECPrivateKeyParameters priv = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(info);
            ECPoint point             = priv.Parameters.Curve.DecodePoint(blob);
            ECPublicKeyParameters pub = new ECPublicKeyParameters(point, priv.Parameters);

            IBasicAgreement agree = new ECDHBasicAgreement();

            agree.Init(priv);
            BigInteger value = agree.CalculateAgreement(pub);

            SharedSecret = Convert.ToBase64String(value.ToByteArrayUnsigned());
            return(SharedSecret);
        }
Exemple #23
0
        public override byte[] ProcessServerKeys(ProtocolVersion version, byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length < 4)
            {
                throw new ArgumentException("data");
            }

            if (data[0] != 3 || data[1] != 0 || data[2] != 23)
            {
                throw new ArgumentException("data");
            }
            if (data[3] != 65 || data[4] > data.Length - 4)
            {
                throw new ArgumentException("data");
            }

            // Generate our private key
            GenerateKeys("secp256r1");

            // Extract the public key from the data
            byte[] ecPointData = new byte[data[3]];
            Buffer.BlockCopy(data, 4, ecPointData, 0, ecPointData.Length);
            ECPoint ecPoint = _domainParameters.Curve.DecodePoint(ecPointData);
            ECPublicKeyParameters theirPublicKey = new ECPublicKeyParameters(ecPoint, _domainParameters);

            // Calculate the actual agreement
            ECDHBasicAgreement agreement = new ECDHBasicAgreement();

            agreement.Init(_privateKey);
            _preMasterSecret = BigIntegerToByteArray(agreement.CalculateAgreement(theirPublicKey), 32);

            byte[] signature = new byte[data.Length - 4 - data[3]];
            Buffer.BlockCopy(data, 4 + data[3], signature, 0, signature.Length);
            return(signature);
        }
        public byte[] DeriveKey(ArraySegment <byte> otherPublicKey)
        {
            if (_pk == null)
            {
                throw new ObjectDisposedException(nameof(KeyAgreement));
            }

            if (otherPublicKey == null)
            {
                throw new ArgumentNullException(nameof(otherPublicKey));
            }
            if (otherPublicKey.Count != 32)
            {
                throw new ArgumentException("The other public key needs to be compressed with the first byte omitted. Only even public keys are accepted");
            }

            var pubk = DecodePublicKey(otherPublicKey);

            var ecdh = new ECDHBasicAgreement();

            ecdh.Init(_pk);
            var key      = ecdh.CalculateAgreement(pubk);
            var keyBytes = key.ToByteArray();

            if (keyBytes.Length != 32)
            {
                byte[] output = new byte[32];
                int    l      = keyBytes.Length;
                int    o      = Math.Max(0, l - 32);
                int    t      = Math.Min(32, l);
                int    w      = 32 - t;
                Array.Copy(keyBytes, o, output, w, t);
                keyBytes = output;
            }

            return(keyBytes);
        }
Exemple #25
0
        public static EphemeralKeyPair Generate(string curveName)
        {
            var ecp = CustomNamedCurves.GetByName(curveName);
            var ecs = new ECDomainParameters(ecp.Curve, ecp.G, ecp.N, ecp.H, ecp.GetSeed());
            var g   = new ECKeyPairGenerator();

            g.Init(new ECKeyGenerationParameters(ecs, new SecureRandom()));

            var pair  = g.GenerateKeyPair();
            var agree = new ECDHBasicAgreement();

            agree.Init(pair.Private);

            var pubkey = MarshalCurvePoint(((ECPublicKeyParameters)pair.Public).Q);
            var done   = new GenerateSharedKeyDelegate(theirPub =>
            {
                var point = UnmarshalCurvePoint(ecp.Curve, theirPub);
                var key   = new ECPublicKeyParameters(point, ecs);

                return(agree.CalculateAgreement(key).ToByteArray());
            });

            return(new EphemeralKeyPair(pubkey, done));
        }
Exemple #26
0
        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");
                }
            }
        }
        protected void DecodeCertMono(McpeLogin message)
        {
            byte[] buffer = message.payload;

            if (message.payload.Length != buffer.Length)
            {
                Log.Debug($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
                throw new Exception($"Wrong lenght {message.payload.Length} != {message.payload.Length}");
            }

            if (Log.IsDebugEnabled)
            {
                Log.Debug("Lenght: " + message.payload.Length + ", Message: " + buffer.EncodeBase64());
            }

            string certificateChain;
            string skinData;

            try
            {
                var destination = new MemoryStream(buffer);
                destination.Position = 0;
                NbtBinaryReader reader = new NbtBinaryReader(destination, false);

                var countCertData = reader.ReadInt32();
                certificateChain = Encoding.UTF8.GetString(reader.ReadBytes(countCertData));
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Certificate Chain (Lenght={countCertData})\n{certificateChain}");
                }

                var countSkinData = reader.ReadInt32();
                skinData = Encoding.UTF8.GetString(reader.ReadBytes(countSkinData));
                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Skin data (Lenght={countSkinData})\n{skinData}");
                }
            }
            catch (Exception e)
            {
                Log.Error("Parsing login", e);
                return;
            }

            try
            {
                {
                    IDictionary <string, dynamic> headers = JWT.Headers(skinData);
                    dynamic payload = JObject.Parse(JWT.Payload(skinData));

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Header: {string.Join(";", headers)}");
                    }
                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Skin JWT Payload:\n{payload.ToString()}");
                    }

                    try
                    {
                        _playerInfo.ClientId         = payload.ClientRandomId;
                        _playerInfo.CurrentInputMode = payload.CurrentInputMode;
                        _playerInfo.DefaultInputMode = payload.DefaultInputMode;
                        _playerInfo.DeviceModel      = payload.DeviceModel;
                        _playerInfo.DeviceOS         = payload.DeviceOS;
                        _playerInfo.GameVersion      = payload.GameVersion;
                        _playerInfo.GuiScale         = payload.GuiScale;
                        _playerInfo.LanguageCode     = payload.LanguageCode;
                        _playerInfo.ServerAddress    = payload.ServerAddress;
                        _playerInfo.UIProfile        = payload.UIProfile;

                        _playerInfo.Skin = new Skin()
                        {
                            CapeData         = Convert.FromBase64String((string)payload.CapeData),
                            SkinId           = payload.SkinId,
                            SkinData         = Convert.FromBase64String((string)payload.SkinData),
                            SkinGeometryName = payload.SkinGeometryName,
                            SkinGeometry     = Encoding.UTF8.GetString(Convert.FromBase64String((string)payload.SkinGeometry)),
                        };
                        Log.Warn($"Cape data lenght={_playerInfo.Skin.CapeData.Length}");
                    }
                    catch (Exception e)
                    {
                        Log.Error("Parsing skin data", e);
                    }
                }

                //var chainArray = chain.ToArray();

                string validationKey     = null;
                string identityPublicKey = null;
                //if (!isMono)
                {
                    dynamic json = JObject.Parse(certificateChain);

                    if (Log.IsDebugEnabled)
                    {
                        Log.Debug($"Certificate JSON:\n{json}");
                    }

                    JArray chain = json.chain;

                    foreach (JToken token in chain)
                    {
                        IDictionary <string, dynamic> headers = JWT.Headers(token.ToString());

                        if (Log.IsDebugEnabled)
                        {
                            Log.Debug("Raw chain element:\n" + token.ToString());
                            Log.Debug($"JWT Header: {string.Join(";", headers)}");

                            dynamic jsonPayload = JObject.Parse(JWT.Payload(token.ToString()));
                            Log.Debug($"JWT Payload:\n{jsonPayload}");
                        }

                        // Mojang root x5u cert (string): MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V

                        if (!headers.ContainsKey("x5u"))
                        {
                            continue;
                        }

                        string x5u = headers["x5u"];

                        if (identityPublicKey == null)
                        {
                            if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.Debug("Key is ok, and got Mojang root");
                            }
                            else if (chain.Count > 1)
                            {
                                Log.Debug("Got client cert (client root)");
                                continue;
                            }
                            else if (chain.Count == 1)
                            {
                                Log.Debug("Selfsigned chain");
                            }
                        }
                        else if (identityPublicKey.Equals(x5u))
                        {
                            Log.Debug("Derived Key is ok");
                        }
                        // Validate

                        var key = PublicKeyFactory.CreateKey(x5u.DecodeBase64Url());

                        CertificateData data = CryptoUtils.Decode(token.ToString(), key);
                        if (data != null)
                        {
                            identityPublicKey = data.IdentityPublicKey;

                            if (Log.IsDebugEnabled)
                            {
                                Log.Debug("Decoded token success");
                            }

                            if (CertificateData.MojangRootKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.Debug("Got Mojang key. Is valid = " + data.CertificateAuthority);
                                validationKey = data.IdentityPublicKey;
                            }
                            else if (validationKey != null && validationKey.Equals(x5u, StringComparison.InvariantCultureIgnoreCase))
                            {
                                _playerInfo.CertificateData = data;
                            }
                            else
                            {
                                if (data.ExtraData == null)
                                {
                                    continue;
                                }

                                // Self signed, make sure they don't fake XUID
                                if (data.ExtraData.Xuid != null)
                                {
                                    Log.Warn("Received fake XUID from " + data.ExtraData.DisplayName);
                                    data.ExtraData.Xuid = null;
                                }

                                _playerInfo.CertificateData = data;
                            }
                        }
                        else
                        {
                            Log.Error("Not a valid Identity Public Key for decoding");
                        }
                    }
                }

                //TODO: Implement disconnect here


                _playerInfo.Username = _playerInfo.CertificateData.ExtraData.DisplayName;
                _session.Username    = _playerInfo.Username;
                string identity = _playerInfo.CertificateData.ExtraData.Identity;

                if (Log.IsDebugEnabled)
                {
                    Log.Debug($"Connecting user {_playerInfo.Username} with identity={identity}");
                }
                _playerInfo.ClientUuid = new UUID(identity);

                bool useEncryption = (Config.GetProperty("UseEncryptionForAll", false) ||
                                      (Config.GetProperty("UseEncryption", true) &&
                                       !string.IsNullOrWhiteSpace(_playerInfo.CertificateData.ExtraData.Xuid)));

                if (useEncryption)
                {
                    var publicKey = PublicKeyFactory.CreateKey(_playerInfo.CertificateData.IdentityPublicKey.DecodeBase64Url());

                    string                    namedCurve = "secp384r1";
                    ECKeyPairGenerator        pGen       = new ECKeyPairGenerator();
                    ECKeyGenerationParameters genParam   = new ECKeyGenerationParameters(
                        SecNamedCurves.GetOid(namedCurve),
                        new SecureRandom());
                    pGen.Init(genParam);

                    AsymmetricCipherKeyPair keyPair = pGen.GenerateKeyPair();

                    ECDHBasicAgreement agreement = new ECDHBasicAgreement();
                    agreement.Init(keyPair.Private);

                    byte[] preHash = agreement.CalculateAgreement(publicKey).ToByteArray();

                    byte[] prepend = Encoding.UTF8.GetBytes("RANDOM SECRET");
                    byte[] secret;

                    SHA256Managed sha = new SHA256Managed();
                    using (var memoryStream = new MemoryStream())
                    {
                        memoryStream.Write(prepend, 0, prepend.Length);
                        memoryStream.Write(preHash, 0, preHash.Length);
                        memoryStream.Position = 0;
                        secret = sha.ComputeHash(memoryStream);
                    }
                    sha.Dispose();

                    //if (Log.IsDebugEnabled) Log.Debug($"SECRET KEY (b64, {secret.Length}):\n{secret.EncodeBase64()}");

                    {
                        RijndaelManaged rijAlg = new RijndaelManaged
                        {
                            BlockSize    = 128,
                            Padding      = PaddingMode.None,
                            Mode         = CipherMode.CFB,
                            FeedbackSize = 8,
                            Key          = secret,
                            IV           = secret.Take(16).ToArray(),
                        };

                        // Create a decrytor to perform the stream transform.
                        ICryptoTransform decryptor      = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
                        MemoryStream     inputStream    = new MemoryStream();
                        CryptoStream     cryptoStreamIn = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read);

                        ICryptoTransform encryptor       = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
                        MemoryStream     outputStream    = new MemoryStream();
                        CryptoStream     cryptoStreamOut = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write);

                        _session.CryptoContext = new CryptoContext
                        {
                            UseEncryption   = true,
                            Algorithm       = rijAlg,
                            Decryptor       = decryptor,
                            Encryptor       = encryptor,
                            InputStream     = inputStream,
                            OutputStream    = outputStream,
                            CryptoStreamIn  = cryptoStreamIn,
                            CryptoStreamOut = cryptoStreamOut
                        };


                        var pubKey1 = ((ECPublicKeyParameters)keyPair.Public);

                        byte[] asn = new byte[24]
                        {
                            0x30, 0x76, 0x30, 0x10, 0x6, 0x7, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x2,
                            0x1, 0x6, 0x5, 0x2b, 0x81, 0x4, 0x0, 0x22, 0x3, 0x62, 0x0, 0x4
                        };
                        string b64Key        = asn.Concat(ConvertToNCryptEccPublicBlob(pubKey1.Q).Skip(8)).ToArray().EncodeBase64();
                        var    handshakeJson = new HandshakeData()
                        {
                            salt = prepend.EncodeBase64()
                        };

                        string val = CryptoUtils.Encode(handshakeJson, keyPair.Private, JwsAlgorithm.ES384,
                                                        new Dictionary <string, object> {
                            { "x5u", b64Key }
                        });

                        var response = McpeServerToClientHandshake.CreateObject();
                        response.NoBatch    = true;
                        response.ForceClear = true;
                        response.token      = val;

                        _session.SendPackage(response);

                        if (Log.IsDebugEnabled)
                        {
                            Log.Warn($"Encryption enabled for {_session.Username}");
                        }
                    }
                }
                else
                {
                    _session.CryptoContext = new CryptoContext
                    {
                        UseEncryption = false
                    };

                    _session.MessageHandler.HandleMcpeClientToServerHandshake(null);
                }
            }
            catch (Exception e)
            {
                Log.Error("Decrypt", e);
            }
        }
Exemple #28
0
        protected static byte[] ECDH_GenerateSecret(OneKey[] keys)
        {
            if (keys[0][CoseKeyKeys.KeyType].Type != CBORType.Number)
            {
                throw new CoseException("Not an EC Key");
            }
            if (keys[1][CoseKeyKeys.KeyType].Type != CBORType.Number)
            {
                throw new CoseException("Not an EC Key");
            }

            OneKey epkPub  = keys[1];
            OneKey epkPriv = keys[0];

            byte[] temp;

            switch ((GeneralValuesInt)epkPub[CoseKeyKeys.KeyType].AsInt32())
            {
            case GeneralValuesInt.KeyType_OKP:
                if (epkPub[CoseKeyParameterKeys.OKP_Curve].AsInt32() != epkPriv[CoseKeyParameterKeys.OKP_Curve].AsInt32())
                {
                    throw new CoseException("Not a match of curves");
                }

                switch ((GeneralValuesInt)epkPriv[CoseKeyParameterKeys.OKP_Curve].AsInt32())
                {
                case GeneralValuesInt.X25519:
                    temp = X25519.CalculateAgreement(epkPub.AsBytes(CoseKeyParameterKeys.OKP_X), epkPriv.AsBytes(CoseKeyParameterKeys.OKP_D));
                    break;

                default:
                    throw new CoseException("Not a supported Curve");
                }
                return(temp);

            case GeneralValuesInt.KeyType_EC2:

                if (epkPub[CoseKeyParameterKeys.EC_Curve].AsInt32() != epkPriv[CoseKeyParameterKeys.EC_Curve].AsInt32())
                {
                    throw new CoseException("not a match of curves");
                }

                //  Get the curve

                X9ECParameters p        = epkPub.GetCurve();
                ECPoint        pubPoint = epkPub.GetPoint();

                ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);

                ECPublicKeyParameters pub = new ECPublicKeyParameters(pubPoint, parameters);

                ECPrivateKeyParameters priv = new ECPrivateKeyParameters(epkPriv.AsBigInteger(CoseKeyParameterKeys.EC_D), parameters);

                IBasicAgreement e1 = new ECDHBasicAgreement();
                e1.Init(priv);

                BigInteger k1 = e1.CalculateAgreement(pub);


                return(PadBytes(k1.ToByteArrayUnsigned(), p.Curve.FieldSize));

            default:
                throw new CoseException("Not an EC Key");
            }
        }
        public string GenerateSharedSecretHex(string pubKeyHex)
        {
            var encoded = pubKeyHex.HexToByteArray();

            if (encoded.Length == 64)
            {
                var numArray = new byte[encoded.Length + 1];
                numArray[0] = (byte)4;
                Array.Copy((Array)encoded, 0, (Array)numArray, 1, encoded.Length);
                encoded = numArray;
            }
            var publicKeyParameters = new ECPublicKeyParameters("ECDH", ECDH_Key._curve.Curve.DecodePoint(encoded), ECDH_Key._domain);
            var ecdhBasicAgreement  = new ECDHBasicAgreement();

            ecdhBasicAgreement.Init(_key.Private);
            return(BigIntegers.AsUnsignedByteArray(ecdhBasicAgreement.GetFieldSize(), ecdhBasicAgreement.CalculateAgreement((ICipherParameters)publicKeyParameters)).ToHex(true));
        }
Exemple #30
0
        public static byte[] HandleKey(byte[] key, byte[] secretKey)
        {
            Asn1InputStream inputStream = new Asn1InputStream(key);
            Asn1Object      o1          = inputStream.ReadObject();
            DerSequence     seq         = o1 as DerSequence;

            DerInteger x = seq[2] as DerInteger;
            DerInteger y = seq[3] as DerInteger;

            X9ECParameters     p = CustomNamedCurves.GetByName("secp521r1");
            ECDomainParameters domainParameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);

            ECPoint point = p.Curve.CreatePoint(x.Value, y.Value);
            ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(point, domainParameters);

            ECKeyPairGenerator generator = new ECKeyPairGenerator();

            generator.Init(new ECKeyGenerationParameters(publicKeyParameters.Parameters, new SecureRandom()));
            AsymmetricCipherKeyPair keyPair = generator.GenerateKeyPair();

            ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();

            basicAgreement.Init(keyPair.Private);
            BigInteger agreement = basicAgreement.CalculateAgreement(publicKeyParameters);

            byte[] agreementBytes = agreement.ToByteArray();
            if (agreementBytes.Length == 65)
            {
                byte[] newAgreement = new byte[66];
                Array.Copy(agreementBytes, 0, newAgreement, 1, 65);
                agreementBytes = newAgreement;
            }

            Sha512Digest sha512 = new Sha512Digest();

            byte[] hash = new byte[sha512.GetDigestSize()];
            sha512.BlockUpdate(agreementBytes, 0, agreementBytes.Length);
            sha512.DoFinal(hash, 0);

            byte[] secret = new byte[secretKey.Length];
            for (int i = 0; i < secret.Length; i++)
            {
                secret[i]  = secretKey[i];
                secret[i] ^= hash[i];
            }

            ECPublicKeyParameters publicKey = keyPair.Public as ECPublicKeyParameters;

            MemoryStream         keyStream = new MemoryStream();
            DerSequenceGenerator gen2      = new DerSequenceGenerator(keyStream);

            gen2.AddObject(new DerBitString(new byte[] { 0x00 }, 7));
            gen2.AddObject(new DerInteger(new byte[] { 0x41 }));
            gen2.AddObject(new DerInteger(publicKey.Q.XCoord.ToBigInteger()));
            gen2.AddObject(new DerInteger(publicKey.Q.YCoord.ToBigInteger()));
            gen2.Close();

            MemoryStream memoryStream = new MemoryStream();

            DerSequenceGenerator gen1 = new DerSequenceGenerator(memoryStream);

            gen1.AddObject(new DerObjectIdentifier("2.16.840.1.101.3.4.2.3"));
            gen1.AddObject(new DerOctetString(keyStream.ToArray()));
            gen1.AddObject(new DerOctetString(secret));
            gen1.Close();

            byte[] result = memoryStream.ToArray();

            memoryStream.Close();
            keyStream.Close();

            return(result);
        }