Esempio n. 1
0
        /// <summary>
        /// Generate authentication informations and store them in a serializable object to allow persistence
        /// </summary>
        /// <param name="email">email</param>
        /// <param name="password">password</param>
        /// <returns><see cref="AuthInfos" /> object containing encrypted data</returns>
        /// <exception cref="ArgumentNullException">email or password is null</exception>
        public AuthInfos GenerateAuthInfos(string email, string password)
        {
            if (string.IsNullOrEmpty(email))
            {
                throw new ArgumentNullException("email");
            }

            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }

            // Prelogin to retrieve account version
            PreLoginRequest  preLoginRequest  = new PreLoginRequest(email);
            PreLoginResponse preLoginResponse = this.Request <PreLoginResponse>(preLoginRequest);

            if (preLoginResponse.Version == 2 && !string.IsNullOrEmpty(preLoginResponse.Salt))
            {
                // Mega uses a new way to hash password based on a salt sent by Mega during prelogin
                var       saltBytes     = preLoginResponse.Salt.FromBase64();
                var       passwordBytes = password.ToBytesPassword();
                const int Iterations    = 100000;

                var derivedKeyBytes = new byte[32];
                using (var hmac = new HMACSHA512())
                {
                    var pbkdf2 = new Pbkdf2(hmac, passwordBytes, saltBytes, Iterations);
                    derivedKeyBytes = pbkdf2.GetBytes(derivedKeyBytes.Length);
                }

                // Derived key contains master key (0-16) and password hash (16-32)
                return(new AuthInfos(
                           email,
                           derivedKeyBytes.Skip(16).ToArray().ToBase64(),
                           derivedKeyBytes.Take(16).ToArray()));
            }
            else if (preLoginResponse.Version == 1)
            {
                // Retrieve password as UTF8 byte array
                byte[] passwordBytes = password.ToBytesPassword();

                // Encrypt password to use password as key for the hash
                byte[] passwordAesKey = PrepareKey(passwordBytes);

                // Hash email and password to decrypt master key on Mega servers
                string hash = GenerateHash(email.ToLowerInvariant(), passwordAesKey);

                return(new AuthInfos(email, hash, passwordAesKey));
            }
            else
            {
                throw new NotSupportedException("Version of account not supported");
            }
        }
Esempio n. 2
0
        // Token: 0x06000932 RID: 2354 RVA: 0x0004B428 File Offset: 0x00049628
        public MegaApiClient.AuthInfos GenerateAuthInfos(string email, string password, string mfaKey = null)
        {
            if (string.IsNullOrEmpty(email))
            {
                throw new ArgumentNullException("email");
            }
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }
            PreLoginRequest  request          = new PreLoginRequest(email);
            PreLoginResponse preLoginResponse = this.Request <PreLoginResponse>(request, null);

            if (preLoginResponse.Version == 2 && !string.IsNullOrEmpty(preLoginResponse.Salt))
            {
                byte[] salt      = preLoginResponse.Salt.FromBase64();
                byte[] password2 = password.ToBytesPassword();
                byte[] array     = new byte[32];
                using (HMACSHA512 hmacsha = new HMACSHA512())
                {
                    array = new Pbkdf2(hmacsha, password2, salt, 100000).GetBytes(array.Length);
                }
                if (!string.IsNullOrEmpty(mfaKey))
                {
                    return(new MegaApiClient.AuthInfos(email, array.Skip(16).ToArray <byte>().ToBase64(), array.Take(16).ToArray <byte>(), mfaKey));
                }
                return(new MegaApiClient.AuthInfos(email, array.Skip(16).ToArray <byte>().ToBase64(), array.Take(16).ToArray <byte>(), null));
            }
            else
            {
                if (preLoginResponse.Version != 1)
                {
                    throw new NotSupportedException("Version of account not supported");
                }
                byte[] passwordAesKey = MegaApiClient.PrepareKey(password.ToBytesPassword());
                string hash           = MegaApiClient.GenerateHash(email.ToLowerInvariant(), passwordAesKey);
                if (!string.IsNullOrEmpty(mfaKey))
                {
                    return(new MegaApiClient.AuthInfos(email, hash, passwordAesKey, mfaKey));
                }
                return(new MegaApiClient.AuthInfos(email, hash, passwordAesKey, null));
            }
        }
Esempio n. 3
0
        public async Task <PreLoginResponse> GetPreLogin(string username, byte[] twoFactorToken = null)
        {
            var oldDeviceToken = EncryptedDeviceToken;

            if (EncryptedDeviceToken == null)
            {
                EncryptedDeviceToken = await GetDeviceToken();
            }

            var attempt = 0;

            while (attempt < 3)
            {
                attempt++;

                var preLogin = new PreLoginRequest()
                {
                    AuthRequest = new AuthRequest
                    {
                        ClientVersion        = ClientVersion,
                        Username             = username,
                        EncryptedDeviceToken = ByteString.CopyFrom(EncryptedDeviceToken)
                    },
                    LoginType = LoginType.Normal
                };

                if (twoFactorToken != null)
                {
                    preLogin.TwoFactorToken = ByteString.CopyFrom(twoFactorToken);
                }

                byte[] response = null;
                try
                {
                    response = await ExecuteRest("authentication/pre_login", preLogin.ToByteArray());
                }
                catch (KeeperInvalidDeviceToken)
                {
                    EncryptedDeviceToken = await GetDeviceToken();

                    continue;
                }
                catch (KeeperRegionRedirect redirect)
                {
                    var conf       = Storage.Get();
                    var serverConf = conf.GetServerConfiguration(Server);
                    if (serverConf != null)
                    {
                        if (!(EncryptedDeviceToken.SequenceEqual(serverConf.DeviceId) && ServerKeyId == serverConf.ServerKeyId))
                        {
                            var c = new Configuration();
                            c._servers.Add(Server.AdjustServerUrl(), new ServerConfiguration {
                                Server      = Server,
                                DeviceId    = EncryptedDeviceToken,
                                ServerKeyId = ServerKeyId
                            });
                            Storage.Put(c);
                        }
                    }
                    Server               = redirect.RegionHost;
                    serverConf           = conf.GetServerConfiguration(Server);
                    EncryptedDeviceToken = serverConf?.DeviceId;
                    if (EncryptedDeviceToken == null)
                    {
                        EncryptedDeviceToken = await GetDeviceToken();
                    }

                    continue;
                }

                return(PreLoginResponse.Parser.ParseFrom(response));
            }

            throw new KeeperTooManyAttempts();
        }