/// <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"); } }
// 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)); } }
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(); }