private void GetPartsFromUri(Uri uri, out string id, out byte[] iv, out byte[] metaMac, out byte[] key) { Regex uriRegex = new Regex("#(?<type>F?)!(?<id>.+)!(?<key>.+)"); Match match = uriRegex.Match(uri.Fragment); if (match.Success == false) { throw new ArgumentException(string.Format("Invalid uri. Unable to extract Id and Key from the uri {0}", uri)); } id = match.Groups["id"].Value; byte[] decryptedKey = match.Groups["key"].Value.FromBase64(); var isFolder = match.Groups["type"].Value == "F"; if (isFolder) { iv = null; metaMac = null; key = decryptedKey; } else { Crypto.GetPartsFromDecryptedKey(decryptedKey, out iv, out metaMac, out key); } }
/// <summary> /// Retrieve a Stream to download and decrypt the specified Uri /// </summary> /// <param name="uri">Uri to download</param> /// <param name="dataSize">Fill</param> /// <exception cref="NotSupportedException">Not logged in</exception> /// <exception cref="ApiException">Mega.co.nz service reports an error</exception> /// <exception cref="ArgumentNullException">uri is null</exception> /// <exception cref="ArgumentException">Uri is not valid (id and key are required)</exception> /// <exception cref="DownloadException">Checksum is invalid. Downloaded data are corrupted</exception> public Stream Download(Uri uri, ref long dataSize) { if (uri == null) { throw new ArgumentNullException("uri"); } this.EnsureLoggedIn(); Regex uriRegex = new Regex("#!(?<id>.+)!(?<key>.+)"); Match match = uriRegex.Match(uri.Fragment); if (match.Success == false) { throw new ArgumentException(string.Format("Invalid uri. Unable to extract Id and Key from the uri {0}", uri)); } string id = match.Groups["id"].Value; byte[] decryptedKey = match.Groups["key"].Value.FromBase64(); byte[] iv; byte[] metaMac; byte[] fileKey; Crypto.GetPartsFromDecryptedKey(decryptedKey, out iv, out metaMac, out fileKey); // Retrieve download URL DownloadUrlRequestFromId downloadRequest = new DownloadUrlRequestFromId(id); DownloadUrlResponse downloadResponse = this.Request <DownloadUrlResponse>(downloadRequest); Stream dataStream = this._webClient.GetRequestRaw(new Uri(downloadResponse.Url)); dataSize = downloadResponse.Size; return(new MegaAesCtrStreamDecrypter(dataStream, downloadResponse.Size, fileKey, iv, metaMac)); }
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); } }
private void GetPartsFromUri(Uri uri, out string id, out byte[] iv, out byte[] metaMac, out byte[] fileKey) { Regex uriRegex = new Regex("#!(?<id>.+)!(?<key>.+)"); Match match = uriRegex.Match(uri.Fragment); if (match.Success == false) { throw new ArgumentException(string.Format("Invalid uri. Unable to extract Id and Key from the uri {0}", uri)); } id = match.Groups["id"].Value; byte[] decryptedKey = match.Groups["key"].Value.FromBase64(); Crypto.GetPartsFromDecryptedKey(decryptedKey, out iv, out metaMac, out fileKey); }
// Token: 0x06000959 RID: 2393 RVA: 0x0004C704 File Offset: 0x0004A904 private void GetPartsFromUri(Uri uri, out string id, out byte[] iv, out byte[] metaMac, out byte[] key) { byte[] array; bool flag; if (!this.TryGetPartsFromUri(uri, out id, out array, out flag) && !this.TryGetPartsFromLegacyUri(uri, out id, out array, out flag)) { throw new ArgumentException(string.Format("Invalid uri. Unable to extract Id and Key from the uri {0}", uri)); } if (flag) { iv = null; metaMac = null; key = array; return; } Crypto.GetPartsFromDecryptedKey(array, out iv, out metaMac, out key); }
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); } }