/// <summary> /// Login to Mega.co.nz service using hashed credentials /// </summary> /// <param name="authInfos">Authentication informations generated by <see cref="GenerateAuthInfos"/> method</param> /// <exception cref="ApiException">Service is not available or authInfos is invalid</exception> /// <exception cref="ArgumentNullException">authInfos is null</exception> /// <exception cref="NotSupportedException">Already logged in</exception> public LogonSessionToken Login(AuthInfos authInfos) { if (authInfos == null) { throw new ArgumentNullException("authInfos"); } this.EnsureLoggedOut(); this.authenticatedLogin = true; // Request Mega Api LoginRequest request = new LoginRequest(authInfos.Email, authInfos.Hash); LoginResponse response = this.Request <LoginResponse>(request); // Decrypt master key using our password key byte[] cryptedMasterKey = response.MasterKey.FromBase64(); this.masterKey = Crypto.DecryptKey(cryptedMasterKey, authInfos.PasswordAesKey); // Decrypt RSA private key using decrypted master key byte[] cryptedRsaPrivateKey = response.PrivateKey.FromBase64(); BigInteger[] rsaPrivateKeyComponents = Crypto.GetRsaPrivateKeyComponents(cryptedRsaPrivateKey, this.masterKey); // Decrypt session id byte[] encryptedSid = response.SessionId.FromBase64(); byte[] sid = Crypto.RsaDecrypt(encryptedSid.FromMPINumber(), rsaPrivateKeyComponents[0], rsaPrivateKeyComponents[1], rsaPrivateKeyComponents[2]); // Session id contains only the first 58 base64 characters this.sessionId = sid.ToBase64().Substring(0, 58); return(new LogonSessionToken(this.sessionId, this.masterKey)); }
// Token: 0x06000938 RID: 2360 RVA: 0x0004B5FC File Offset: 0x000497FC public MegaApiClient.LogonSessionToken Login(MegaApiClient.AuthInfos authInfos) { if (authInfos == null) { throw new ArgumentNullException("authInfos"); } this.EnsureLoggedOut(); this.authenticatedLogin = true; LoginRequest request; if (!string.IsNullOrEmpty(authInfos.MFAKey)) { request = new LoginRequest(authInfos.Email, authInfos.Hash, authInfos.MFAKey); } else { request = new LoginRequest(authInfos.Email, authInfos.Hash); } LoginResponse loginResponse = this.Request <LoginResponse>(request, null); byte[] data = loginResponse.MasterKey.FromBase64(); this.masterKey = Crypto.DecryptKey(data, authInfos.PasswordAesKey); BigInteger[] rsaPrivateKeyComponents = Crypto.GetRsaPrivateKeyComponents(loginResponse.PrivateKey.FromBase64(), this.masterKey); byte[] source = Crypto.RsaDecrypt(loginResponse.SessionId.FromBase64().FromMPINumber(), rsaPrivateKeyComponents[0], rsaPrivateKeyComponents[1], rsaPrivateKeyComponents[2]); this.sessionId = source.Take(43).ToArray <byte>().ToBase64(); return(new MegaApiClient.LogonSessionToken(this.sessionId, this.masterKey)); }
/// <summary> /// Login to Mega.co.nz service using hashed credentials /// </summary> /// <param name="authInfos">Authentication informations generated by <see cref="GenerateAuthInfos"/> method</param> /// <exception cref="ApiException">Service is not available or authInfos is invalid</exception> /// <exception cref="ArgumentNullException">authInfos is null</exception> /// <exception cref="NotSupportedException">Already logged in</exception> public void Login(AuthInfos authInfos) { if (authInfos == null) { throw new ArgumentNullException("authInfos"); } this.EnsureLoggedOut(); // Store authInfos to relogin if required this._authInfos = authInfos; // Request Mega Api LoginRequest request = new LoginRequest(authInfos.Email, authInfos.Hash); LoginResponse response = this.Request <LoginResponse>(request); // Decrypt master key using our password key byte[] cryptedMasterKey = response.MasterKey.FromBase64(); this._masterKey = Crypto.DecryptKey(cryptedMasterKey, authInfos.PasswordAesKey); // Decrypt RSA private key using decrypted master key byte[] cryptedRsaPrivateKey = response.PrivateKey.FromBase64(); BigInteger[] rsaPrivateKeyComponents = Crypto.GetRsaPrivateKeyComponents(cryptedRsaPrivateKey, this._masterKey); // Decrypt session id byte[] encryptedSid = response.SessionId.FromBase64(); byte[] sid = Crypto.RsaDecrypt(encryptedSid.FromMPINumber(), rsaPrivateKeyComponents[0], rsaPrivateKeyComponents[1], rsaPrivateKeyComponents[2]); // Session id contains only the first 43 decrypted bytes this._sessionId = sid.CopySubArray(43).ToBase64(); }
public void OnDeserialized(StreamingContext ctx) { // Add key from incoming sharing. if (this.SharingKey != null && this.sharedKeys.Any(x => x.Id == this.Id) == false) { this.sharedKeys.Add(new SharedKey(this.Id, this.SharingKey)); } this.CreationDate = this.SerializedCreationDate.ToDateTime(); if (this.Type == NodeType.File || this.Type == NodeType.Directory) { // There are cases where the SerializedKey property contains multiple keys separated with / // This can occur when a folder is shared and the parent is shared too. // Both keys are working so we use the first one string serializedKey = this.SerializedKey.Split('/')[0]; int splitPosition = serializedKey.IndexOf(":", StringComparison.Ordinal); byte[] encryptedKey = serializedKey.Substring(splitPosition + 1).FromBase64(); // If node is shared, we need to retrieve shared masterkey if (this.sharedKeys != null) { string handle = serializedKey.Substring(0, splitPosition); SharedKey sharedKey = this.sharedKeys.FirstOrDefault(x => x.Id == handle); if (sharedKey != null) { this.masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), this.masterKey); if (this.Type == NodeType.Directory) { this.SharedKey = this.masterKey; } else { this.SharedKey = Crypto.DecryptKey(encryptedKey, this.masterKey); } } } this.FullKey = Crypto.DecryptKey(encryptedKey, this.masterKey); if (this.Type == NodeType.File) { byte[] iv, metaMac, fileKey; Crypto.GetPartsFromDecryptedKey(this.FullKey, out iv, out metaMac, out fileKey); this.Iv = iv; this.MetaMac = metaMac; this.Key = fileKey; } else { this.Key = this.FullKey; } this.Attributes = Crypto.DecryptAttributes(this.SerializedAttributes.FromBase64(), this.Key); } }
public void OnDeserialized(StreamingContext ctx) { if (this.SharingKey != null && !this.sharedKeys.Any((SharedKey x) => x.Id == base.Id)) { this.sharedKeys.Add(new SharedKey(base.Id, this.SharingKey)); } this.CreationDate = this.SerializedCreationDate.ToDateTime(); if (base.Type == NodeType.File || base.Type == NodeType.Directory) { if (string.IsNullOrEmpty(this.SerializedKey)) { this.EmptyKey = true; return; } string text = this.SerializedKey.Split(new char[] { '/' })[0]; int num = text.IndexOf(":", StringComparison.Ordinal); byte[] data = text.Substring(num + 1).FromBase64(); if (this.sharedKeys != null) { string handle = text.Substring(0, num); SharedKey sharedKey = this.sharedKeys.FirstOrDefault((SharedKey x) => x.Id == handle); if (sharedKey != null) { this.masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), this.masterKey); if (base.Type == NodeType.Directory) { this.SharedKey = this.masterKey; } else { this.SharedKey = Crypto.DecryptKey(data, this.masterKey); } } } this.FullKey = Crypto.DecryptKey(data, this.masterKey); if (base.Type == NodeType.File) { byte[] iv; byte[] metaMac; byte[] key; Crypto.GetPartsFromDecryptedKey(this.FullKey, out iv, out metaMac, out key); this.Iv = iv; this.MetaMac = metaMac; this.Key = key; } else { this.Key = this.FullKey; } base.Attributes = Crypto.DecryptAttributes(this.SerializedAttributes.FromBase64(), this.Key); } }
public void OnDeserialized(StreamingContext ctx) { byte[] masterKey = (byte[])((object[])ctx.Context)[0]; GetNodesResponse nodesResponse = (GetNodesResponse)((object[])ctx.Context)[1]; this.LastModificationDate = OriginalDateTime.AddSeconds(this.SerializedLastModificationDate).ToLocalTime(); if (this.Type == NodeType.File || this.Type == NodeType.Directory) { int splitPosition = this.SerializedKey.IndexOf(":", StringComparison.InvariantCulture); byte[] encryptedKey = this.SerializedKey.Substring(splitPosition + 1).FromBase64(); this.DecryptedKey = Crypto.DecryptKey(encryptedKey, masterKey); this.Key = this.DecryptedKey; // If node is shared, we need to retrieve shared masterkey if (nodesResponse.SharedKeys != null) { string owner = this.SerializedKey.Substring(0, splitPosition); GetNodesResponse.SharedKey sharedKey = nodesResponse.SharedKeys.FirstOrDefault(x => x.Id == owner); if (sharedKey != null) { masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), masterKey); if (this.Type == NodeType.Directory) { this.DecryptedKey = masterKey; } this.Key = Crypto.DecryptKey(encryptedKey, masterKey); } } if (this.Type == NodeType.File) { // Extract Iv and MetaMac byte[] iv = new byte[8]; byte[] metaMac = new byte[8]; Array.Copy(this.DecryptedKey, 16, iv, 0, 8); Array.Copy(this.DecryptedKey, 24, metaMac, 0, 8); this.Iv = iv; this.MetaMac = metaMac; // For files, key is 256 bits long. Compute the key to retrieve 128 AES key this.Key = new byte[16]; for (int idx = 0; idx < 16; idx++) { this.Key[idx] = (byte)(this.DecryptedKey[idx] ^ this.DecryptedKey[idx + 16]); } } Attributes attributes = Crypto.DecryptAttributes(this.SerializedAttributes.FromBase64(), this.Key); this.Name = attributes.Name; } }
// Token: 0x060007F3 RID: 2035 RVA: 0x0003997C File Offset: 0x00037B7C public static BigInteger[] GetRsaPrivateKeyComponents(byte[] encodedRsaPrivateKey, byte[] masterKey) { encodedRsaPrivateKey = encodedRsaPrivateKey.CopySubArray(encodedRsaPrivateKey.Length + (16 - encodedRsaPrivateKey.Length % 16), 0); byte[] array = Crypto.DecryptKey(encodedRsaPrivateKey, masterKey); BigInteger[] array2 = new BigInteger[4]; for (int i = 0; i < 4; i++) { array2[i] = array.FromMPINumber(); int num = ((int)array[0] * 256 + (int)array[1] + 7) / 8; array = array.CopySubArray(array.Length - num - 2, num + 2); } return(array2); }
public void OnDeserialized(StreamingContext ctx) { // Add key from incoming sharing. if (this.SharingKey != null && this.sharedKeys.Any(x => x.Id == this.Id) == false) { this.sharedKeys.Add(new SharedKey(this.Id, this.SharingKey)); } this.CreationDate = this.SerializedCreationDate.ToDateTime(); if (this.Type == NodeType.File || this.Type == NodeType.Directory) { // Check if file is not yet decrypted if (string.IsNullOrEmpty(this.SerializedKey)) { this.EmptyKey = true; return; } // There are cases where the SerializedKey property contains multiple keys separated with / // This can occur when a folder is shared and the parent is shared too. // Both keys are working so we use the first one string serializedKey = this.SerializedKey.Split('/')[0]; int splitPosition = serializedKey.IndexOf(":", StringComparison.Ordinal); byte[] encryptedKey = serializedKey.Substring(splitPosition + 1).FromBase64(); // If node is shared, we need to retrieve shared masterkey if (this.sharedKeys != null) { string handle = serializedKey.Substring(0, splitPosition); SharedKey sharedKey = this.sharedKeys.FirstOrDefault(x => x.Id == handle); if (sharedKey != null) { this.masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), this.masterKey); if (this.Type == NodeType.Directory) { this.SharedKey = this.masterKey; } else { this.SharedKey = Crypto.DecryptKey(encryptedKey, this.masterKey); } } } this.FullKey = Crypto.DecryptKey(encryptedKey, this.masterKey); if (this.Type == NodeType.File) { byte[] iv, metaMac, fileKey; Crypto.GetPartsFromDecryptedKey(this.FullKey, out iv, out metaMac, out fileKey); this.Iv = iv; this.MetaMac = metaMac; this.Key = fileKey; } else { this.Key = this.FullKey; } this.Attributes = Crypto.DecryptAttributes(this.SerializedAttributes.FromBase64(), this.Key); if (this.SerializedFileAttributes != null) { var attributes = this.SerializedFileAttributes.Split('/'); this.FileAttributes = attributes .Select(_ => FileAttributeRegex.Match(_)) .Where(_ => _.Success) .Select(_ => new FileAttribute( int.Parse(_.Groups["id"].Value), (FileAttributeType)Enum.Parse(typeof(FileAttributeType), _.Groups["type"].Value), _.Groups["handle"].Value)) .ToArray(); } } }
public void OnDeserialized(StreamingContext ctx) { object[] context = (object[])ctx.Context; GetNodesResponse nodesResponse = (GetNodesResponse)context[0]; if (context.Length == 1) { // Add key from incoming sharing. if (this.SharingKey != null) { nodesResponse.SharedKeys.Add(new GetNodesResponse.SharedKey(this.Id, this.SharingKey)); } return; } else { byte[] masterKey = (byte[])context[1]; this.LastModificationDate = OriginalDateTime.AddSeconds(this.SerializedLastModificationDate).ToLocalTime(); if (this.Type == NodeType.File || this.Type == NodeType.Directory) { // There are cases where the SerializedKey property contains multiple keys separated with / // This can occur when a folder is shared and the parent is shared too. // Both keys are working so we use the first one string serializedKey = this.SerializedKey.Split('/')[0]; int splitPosition = serializedKey.IndexOf(":", StringComparison.InvariantCulture); byte[] encryptedKey = serializedKey.Substring(splitPosition + 1).FromBase64(); // If node is shared, we need to retrieve shared masterkey if (nodesResponse.SharedKeys != null) { string handle = serializedKey.Substring(0, splitPosition); GetNodesResponse.SharedKey sharedKey = nodesResponse.SharedKeys.FirstOrDefault(x => x.Id == handle); if (sharedKey != null) { masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), masterKey); if (this.Type == NodeType.Directory) { this.SharedKey = masterKey; } else { this.SharedKey = Crypto.DecryptKey(encryptedKey, masterKey); } } } this.Key = Crypto.DecryptKey(encryptedKey, masterKey); if (this.Type == NodeType.File) { byte[] iv, metaMac, fileKey; Crypto.GetPartsFromDecryptedKey(this.Key, out iv, out metaMac, out fileKey); this.Iv = iv; this.MetaMac = metaMac; this.Key = fileKey; } Attributes attributes = Crypto.DecryptAttributes(this.SerializedAttributes.FromBase64(), this.Key); this.Name = attributes.Name; } } }
public void OnDeserialized(StreamingContext ctx) { // Add key from incoming sharing. if (SharingKey != null && _sharedKeys.Any(x => x.Id == Id) == false) { _sharedKeys.Add(new SharedKey(Id, SharingKey)); } CreationDate = SerializedCreationDate.ToDateTime(); if (Type == NodeType.File || Type == NodeType.Directory) { // Check if file is not yet decrypted if (string.IsNullOrEmpty(SerializedKey)) { EmptyKey = true; return; } // There are cases where the SerializedKey property contains multiple keys separated with / // This can occur when a folder is shared and the parent is shared too. // Both keys are working so we use the first one var serializedKey = SerializedKey.Split('/')[0]; var splitPosition = serializedKey.IndexOf(":", StringComparison.Ordinal); var encryptedKey = serializedKey.Substring(splitPosition + 1).FromBase64(); // If node is shared, we need to retrieve shared masterkey if (_sharedKeys != null) { var handle = serializedKey.Substring(0, splitPosition); var sharedKey = _sharedKeys.FirstOrDefault(x => x.Id == handle); if (sharedKey != null) { _masterKey = Crypto.DecryptKey(sharedKey.Key.FromBase64(), _masterKey); if (Type == NodeType.Directory) { SharedKey = _masterKey; } else { SharedKey = Crypto.DecryptKey(encryptedKey, _masterKey); } } } if (encryptedKey.Length != 16 && encryptedKey.Length != 32) { // Invalid key size return; } FullKey = Crypto.DecryptKey(encryptedKey, _masterKey); if (Type == NodeType.File) { Crypto.GetPartsFromDecryptedKey(FullKey, out var iv, out var metaMac, out var fileKey); Iv = iv; MetaMac = metaMac; Key = fileKey; } else { Key = FullKey; } Attributes = Crypto.DecryptAttributes(SerializedAttributes.FromBase64(), Key); FileAttributes = DeserializeFileAttributes(SerializedFileAttributes); } }