Beispiel #1
0
        /**
         * return the object identifier signified by the passed in name. Null
         * if there is no object identifier associated with name.
         *
         * @return the object identifier associated with name, if present.
         */
        public static DerObjectIdentifier GetOid(string name)
        {
            DerObjectIdentifier oid = X962NamedCurves.GetOid(name);

            if (oid == null)
            {
                oid = SecNamedCurves.GetOid(name);
            }

            if (oid == null)
            {
                oid = NistNamedCurves.GetOid(name);
            }

            if (oid == null)
            {
                oid = TeleTrusTNamedCurves.GetOid(name);
            }

            if (oid == null)
            {
                oid = AnssiNamedCurves.GetOid(name);
            }

            return(oid);
        }
Beispiel #2
0
        /// <summary>
        /// Parameters to generate the key for
        /// </summary>
        /// <returns></returns>
        private string GetEcCurve()
        {
            var ret = "secp384r1"; // Default

            try
            {
                var config = Properties.Settings.Default.ECCurve;
                DerObjectIdentifier curveOid = null;
                try
                {
                    curveOid = SecNamedCurves.GetOid(config);
                }
                catch {}
                if (curveOid != null)
                {
                    ret = config;
                }
                else
                {
                    _log.Warning("Unknown curve {ECCurve}", config);
                }
            }
            catch (Exception ex)
            {
                _log.Warning("Unable to get EC name, error: {@ex}", ex);
            }
            _log.Debug("ECCurve: {ECCurve}", ret);
            return(ret);
        }
        public static ECDH_Key GenerateKey()
        {
            var generator           = GeneratorUtilities.GetKeyPairGenerator("ECDH");
            var derObjectIdentifier = SecNamedCurves.GetOid("secp256k1");

            generator.Init(new ECKeyGenerationParameters(derObjectIdentifier, _secureRandom));
            var generatedKey = generator.GenerateKeyPair();
            var key          = new ECDH_Key(generatedKey);

            return(key);
        }
Beispiel #4
0
        internal override AsymmetricCipherKeyPair GenerateNewKeyPair()
        {
            var generator = new ECKeyPairGenerator();
            var curve     = GetEcCurve();
            var genParam  = new ECKeyGenerationParameters(
                SecNamedCurves.GetOid(curve),
                new SecureRandom());

            generator.Init(genParam);
            return(generator.GenerateKeyPair());
        }
Beispiel #5
0
        /// <summary>
        /// Determine the curve OID from an EC key blob
        /// </summary>
        /// <param name="magic">Magic number</param>
        /// <returns>Curve OID</returns>
        private static DerObjectIdentifier getCurveOid(int magic, CurveNamespace nameSpace)
        {
            switch (magic)
            {
            case (int)KeyBlobMagicNumber.ECDHPublicP256:
            case (int)KeyBlobMagicNumber.ECDsaPublicP256:
                switch (nameSpace)
                {
                case CurveNamespace.X962:
                    return(X962NamedCurves.GetOid("prime256v1"));

                case CurveNamespace.NIST:
                    return(NistNamedCurves.GetOid("P-256"));

                case CurveNamespace.SEC:
                    return(SecNamedCurves.GetOid("SecP256r1"));
                }
                break;

            case (int)KeyBlobMagicNumber.ECDHPublicP384:
            case (int)KeyBlobMagicNumber.ECDsaPublicP384:
                switch (nameSpace)
                {
                case CurveNamespace.X962:                   // These aren't in the BC list
                    return(X962NamedCurves.GetOid("prime384v1"));

                case CurveNamespace.NIST:
                    return(NistNamedCurves.GetOid("P-384"));

                case CurveNamespace.SEC:
                    return(SecNamedCurves.GetOid("SecP384r1"));
                }
                break;

            case (int)KeyBlobMagicNumber.ECDHPublicP521:
            case (int)KeyBlobMagicNumber.ECDsaPublicP521:
                switch (nameSpace)
                {
                case CurveNamespace.X962:               // These aren't in the BC list
                    return(X962NamedCurves.GetOid("prime521v1"));

                case CurveNamespace.NIST:
                    return(NistNamedCurves.GetOid("P-521"));

                case CurveNamespace.SEC:
                    return(SecNamedCurves.GetOid("SecP521r1"));
                }
                break;
            }
            return(null);
        }
Beispiel #6
0
 /// <summary>
 /// Generate or return private key
 /// </summary>
 /// <returns></returns>
 public override AsymmetricKeyParameter GetPrivateKey()
 {
     if (_keyPair == null)
     {
         var generator = new ECKeyPairGenerator();
         var curve     = GetEcCurve();
         var genParam  = new ECKeyGenerationParameters(
             SecNamedCurves.GetOid(curve),
             new SecureRandom());
         generator.Init(genParam);
         _keyPair = generator.GenerateKeyPair();
     }
     return(_keyPair.Private);
 }
Beispiel #7
0
 private static KeyPair GenerateECDSAKey(string encryptionName, string curveName)
 {
     try
     {
         DerObjectIdentifier doi = SecNamedCurves.GetOid(curveName);
         ECKeyPairGenerator  g   = new ECKeyPairGenerator(encryptionName);
         g.Init(new ECKeyGenerationParameters(doi, new SecureRandom()));
         return(Create(g.GenerateKeyPair()));
     }
     catch (Exception exp)
     {
         throw new CryptoException("Unable to generate key pair", exp);
     }
 }
        public void PrepareKey()
        {
            try
            {
                byte key_idx = 0;

                X9ECParameters curve = SecNamedCurves.GetByName("secp256k1");

                AsymmetricKeyParameter pub_key = null;
                pub_key = new ECPublicKeyParameters("ECDSA", curve.Curve.DecodePoint(Hex.Decode(ECPubKeyStr)), SecNamedCurves.GetOid("secp256k1"));

                AsymmetricKeyParameter priv_key = null;

                setParameters(this, pub_key, priv_key, key_idx, "ECDSA");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        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);
            }
        }