Example #1
0
        /// <summary>
        /// Login anonymously to Mega.co.nz service
        /// </summary>
        /// <exception cref="ApiException">Throws if service is not available</exception>
        public void LoginAnonymous()
        {
            this.EnsureLoggedOut();
            this.authenticatedLogin = false;

            Random random = new Random();

            // Generate random master key
            this.masterKey = new byte[16];
            random.NextBytes(this.masterKey);

            // Generate a random password used to encrypt the master key
            byte[] passwordAesKey = new byte[16];
            random.NextBytes(passwordAesKey);

            // Generate a random session challenge
            byte[] sessionChallenge = new byte[16];
            random.NextBytes(sessionChallenge);

            byte[] encryptedMasterKey = Crypto.EncryptAes(this.masterKey, passwordAesKey);

            // Encrypt the session challenge with our generated master key
            byte[] encryptedSessionChallenge = Crypto.EncryptAes(sessionChallenge, this.masterKey);
            byte[] encryptedSession          = new byte[32];
            Array.Copy(sessionChallenge, 0, encryptedSession, 0, 16);
            Array.Copy(encryptedSessionChallenge, 0, encryptedSession, 16, encryptedSessionChallenge.Length);

            // Request Mega Api to obtain a temporary user handle
            AnonymousLoginRequest request = new AnonymousLoginRequest(encryptedMasterKey.ToBase64(), encryptedSession.ToBase64());
            string userHandle             = this.Request(request);

            // Request Mega Api to retrieve our temporary session id
            LoginRequest  request2  = new LoginRequest(userHandle, null);
            LoginResponse response2 = this.Request <LoginResponse>(request2);

            this.sessionId = response2.TemporarySessionId;
        }
        private static string GenerateHash(string email, byte[] passwordAesKey)
        {
            byte[] emailBytes = email.ToBytes();
            byte[] hash       = new byte[16];

            // Compute email in 16 bytes array
            for (int i = 0; i < emailBytes.Length; i++)
            {
                hash[i % 16] ^= emailBytes[i];
            }

            // Encrypt hash using password key
            for (int it = 0; it < 16384; it++)
            {
                hash = Crypto.EncryptAes(hash, passwordAesKey);
            }

            // Retrieve bytes 0-4 and 8-12 from the hash
            byte[] result = new byte[8];
            Array.Copy(hash, 0, result, 0, 4);
            Array.Copy(hash, 8, result, 4, 4);

            return(result.ToBase64());
        }
Example #3
0
 // Token: 0x060007F1 RID: 2033 RVA: 0x000398C0 File Offset: 0x00037AC0
 public static byte[] EncryptAttributes(Attributes attributes, byte[] nodeKey)
 {
     byte[] array = ("MEGA" + JsonConvert.SerializeObject(attributes, Formatting.None)).ToBytes();
     array = array.CopySubArray(array.Length + 16 - array.Length % 16, 0);
     return(Crypto.EncryptAes(array, nodeKey));
 }
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this._position == this._streamLength)
            {
                return(0);
            }

            for (long pos = this._position; pos < Math.Min(this._position + count, this._streamLength); pos += 16)
            {
                // We are on a chunk bondary
                if (this._chunksPositions.Any(chunk => chunk == pos) || pos == 0)
                {
                    if (pos != 0)
                    {
                        // Compute the current chunk mac data on each chunk bondary
                        this.ComputeChunk();
                    }

                    // Init chunk mac with Iv values
                    for (int i = 0; i < 8; i++)
                    {
                        _currentChunkMac[i]     = this._iv[i];
                        _currentChunkMac[i + 8] = this._iv[i];
                    }
                }

                this.IncrementCounter();

                // Iterate each AES 16 bytes block
                byte[] input       = new byte[16];
                byte[] output      = new byte[input.Length];
                int    inputLength = this._stream.Read(input, 0, input.Length);
                if (inputLength != input.Length)
                {
                    // Sometimes, the stream is not finished but the read is not complete
                    inputLength += this._stream.Read(input, inputLength, input.Length - inputLength);
                }

                // Merge Iv and counter
                byte[] ivCounter = new byte[16];
                Array.Copy(this._iv, ivCounter, 8);
                Array.Copy(this._counter, 0, ivCounter, 8, 8);

                byte[] encryptedIvCounter = Crypto.EncryptAes(ivCounter, this._fileKey);

                for (int inputPos = 0; inputPos < inputLength; inputPos++)
                {
                    output[inputPos] = (byte)(encryptedIvCounter[inputPos] ^ input[inputPos]);
                    this._currentChunkMac[inputPos] ^= (_mode == Mode.Crypt) ? input[inputPos] : output[inputPos];
                }

                // Copy to buffer
                Array.Copy(output, 0, buffer, offset + pos - this._position, Math.Min(output.Length, this._streamLength - pos));

                // Crypt to current chunk mac
                this._currentChunkMac = Crypto.EncryptAes(this._currentChunkMac, this._fileKey);
            }

            long len = (long)Math.Min(count, this._streamLength - this._position);

            this._position += len;

            // When stream is fully processed, we compute the last chunk
            if (this._position == this._streamLength)
            {
                this.ComputeChunk();

                // Compute Meta MAC
                for (int i = 0; i < 4; i++)
                {
                    this._metaMac[i]     = (byte)(this._fileMac[i] ^ this._fileMac[i + 4]);
                    this._metaMac[i + 4] = (byte)(this._fileMac[i + 8] ^ this._fileMac[i + 12]);
                }

                this.OnStreamRead();
            }

            return((int)len);
        }
Example #5
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this.position == this.streamLength)
            {
                return(0);
            }

            if (this.position + count < this.streamLength && count < 16)
            {
                throw new NotSupportedException($"Invalid '{nameof(count)}' argument. Minimal read operation must be greater than 16 bytes (except for last read operation).");
            }

            // Validate count boundaries
            count = (this.position + count < this.streamLength)
        ? count - (count % 16) // Make count divisible by 16 for partial reads (as the minimal block is 16)
        : count;

            for (long pos = this.position; pos < Math.Min(this.position + count, this.streamLength); pos += 16)
            {
                // We are on a chunk bondary
                if (this.chunksPositionsCache.Contains(pos))
                {
                    if (pos != 0)
                    {
                        // Compute the current chunk mac data on each chunk bondary
                        this.ComputeChunk(encryptor);
                    }

                    // Init chunk mac with Iv values
                    for (int i = 0; i < 8; i++)
                    {
                        this.currentChunkMac[i]     = this.iv[i];
                        this.currentChunkMac[i + 8] = this.iv[i];
                    }
                }

                this.IncrementCounter();

                // Iterate each AES 16 bytes block
                byte[] input       = new byte[16];
                byte[] output      = new byte[input.Length];
                int    inputLength = this.stream.Read(input, 0, input.Length);
                if (inputLength != input.Length)
                {
                    // Sometimes, the stream is not finished but the read is not complete
                    inputLength += this.stream.Read(input, inputLength, input.Length - inputLength);
                }

                // Merge Iv and counter
                byte[] ivCounter = new byte[16];
                Array.Copy(this.iv, ivCounter, 8);
                Array.Copy(this.counter, 0, ivCounter, 8, 8);

                byte[] encryptedIvCounter = Crypto.EncryptAes(ivCounter, encryptor);

                for (int inputPos = 0; inputPos < inputLength; inputPos++)
                {
                    output[inputPos] = (byte)(encryptedIvCounter[inputPos] ^ input[inputPos]);
                    this.currentChunkMac[inputPos] ^= (this.mode == Mode.Crypt) ? input[inputPos] : output[inputPos];
                }

                // Copy to buffer
                Array.Copy(output, 0, buffer, (int)(offset + pos - this.position), (int)Math.Min(output.Length, this.streamLength - pos));

                // Crypt to current chunk mac
                this.currentChunkMac = Crypto.EncryptAes(this.currentChunkMac, encryptor);
            }

            long len = Math.Min(count, this.streamLength - this.position);

            this.position += len;

            // When stream is fully processed, we compute the last chunk
            if (this.position == this.streamLength)
            {
                this.ComputeChunk(encryptor);

                // Compute Meta MAC
                for (int i = 0; i < 4; i++)
                {
                    this.metaMac[i]     = (byte)(this.fileMac[i] ^ this.fileMac[i + 4]);
                    this.metaMac[i + 4] = (byte)(this.fileMac[i + 8] ^ this.fileMac[i + 12]);
                }

                this.OnStreamRead();
            }

            return((int)len);
        }
Example #6
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            count = (int)Math.Min(count, Length - Position);

            if (buffer.Length - offset < count)
            {
                throw new ArgumentException();
            }

            if (Position >= Length)
            {
                return(0);
            }

            var originalPosition = Position;

            this.stream.Seek(Position, SeekOrigin.Begin);
            var readCount = this.stream.Read(buffer, offset, count);

            var endPosition = Math.Min(originalPosition + count, this.streamLength);

            for (long pos = originalPosition; pos < endPosition; pos += 16)
            {
                // We are on a chunk bondary
                if (this.chunksPositionsCache.Contains(pos))
                {
                    if (pos != 0)
                    {
                        // Compute the current chunk mac data on each chunk bondary
                        this.ComputeChunk(encryptor);
                    }

                    // Init chunk mac with Iv values
                    for (int i = 0; i < 8; i++)
                    {
                        this.currentChunkMac[i]     = this.iv[i];
                        this.currentChunkMac[i + 8] = this.iv[i];
                    }
                }

                this.IncrementCounter();

                // Iterate each AES 16 bytes block
                var    inputLength = Math.Min(16, endPosition - pos);
                byte[] input       = new byte[inputLength];
                byte[] output      = new byte[inputLength];
                Array.Copy(buffer, (int)(pos - originalPosition), input, 0, input.Length);

                // Merge Iv and counter
                byte[] ivCounter = new byte[16];
                Array.Copy(this.iv, ivCounter, 8);
                Array.Copy(this.counter, 0, ivCounter, 8, 8);

                byte[] encryptedIvCounter = Crypto.EncryptAes(ivCounter, encryptor);

                for (int inputPos = 0; inputPos < inputLength; inputPos++)
                {
                    output[inputPos] = (byte)(encryptedIvCounter[inputPos] ^ input[inputPos]);
                    this.currentChunkMac[inputPos] ^= (this.mode == Mode.Crypt) ? input[inputPos] : output[inputPos];
                }

                // Copy to buffer
                Array.Copy(output, 0, buffer, (int)(offset + pos - this.position), (int)Math.Min(output.Length, this.streamLength - pos));

                // Crypt to current chunk mac
                this.currentChunkMac = Crypto.EncryptAes(this.currentChunkMac, encryptor);
            }

            long len = Math.Min(count, this.streamLength - this.position);

            this.position += len;

            // When stream is fully processed, we compute the last chunk
            if (this.position == this.streamLength)
            {
                this.ComputeChunk(encryptor);

                // Compute Meta MAC
                for (int i = 0; i < 4; i++)
                {
                    this.metaMac[i]     = (byte)(this.fileMac[i] ^ this.fileMac[i + 4]);
                    this.metaMac[i + 4] = (byte)(this.fileMac[i + 8] ^ this.fileMac[i + 12]);
                }

                this.OnStreamRead();
            }

            return(readCount);
        }