diff --git a/MegaApiClient/Cryptography/Crypto.cs b/MegaApiClient/Cryptography/Crypto.cs
index 978f822..4862da0 100644
--- a/MegaApiClient/Cryptography/Crypto.cs
+++ b/MegaApiClient/Cryptography/Crypto.cs
@@ -38,12 +38,14 @@ public static byte[] DecryptKey(byte[] data, byte[] key)
public static byte[] EncryptKey(byte[] data, byte[] key)
{
byte[] result = new byte[data.Length];
-
- for (int idx = 0; idx < data.Length; idx += 16)
+ using (var encryptor = CreateAesEncryptor(key))
{
- byte[] block = data.CopySubArray(16, idx);
- byte[] encryptedBlock = EncryptAes(block, key);
- Array.Copy(encryptedBlock, 0, result, idx, 16);
+ for (int idx = 0; idx < data.Length; idx += 16)
+ {
+ byte[] block = data.CopySubArray(16, idx);
+ byte[] encryptedBlock = EncryptAes(block, encryptor);
+ Array.Copy(encryptedBlock, 0, result, idx, 16);
+ }
}
return result;
@@ -77,9 +79,19 @@ public static byte[] DecryptAes(byte[] data, byte[] key)
}
}
+ public static ICryptoTransform CreateAesEncryptor(byte[] key)
+ {
+ return AesCbc.CreateEncryptor(key, DefaultIv);
+ }
+
+ public static byte[] EncryptAes(byte[] data, ICryptoTransform encryptor)
+ {
+ return encryptor.TransformFinalBlock(data, 0, data.Length);
+ }
+
public static byte[] EncryptAes(byte[] data, byte[] key)
{
- using (ICryptoTransform encryptor = AesCbc.CreateEncryptor(key, DefaultIv))
+ using (ICryptoTransform encryptor = CreateAesEncryptor(key))
{
return encryptor.TransformFinalBlock(data, 0, data.Length);
}
diff --git a/MegaApiClient/MegaApiClient.cs b/MegaApiClient/MegaApiClient.cs
index 6c0d759..5a100ac 100644
--- a/MegaApiClient/MegaApiClient.cs
+++ b/MegaApiClient/MegaApiClient.cs
@@ -909,9 +909,12 @@ private static string GenerateHash(string email, byte[] passwordAesKey)
}
// Encrypt hash using password key
- for (int it = 0; it < 16384; it++)
+ using (var encryptor = Crypto.CreateAesEncryptor(passwordAesKey))
{
- hash = Crypto.EncryptAes(hash, passwordAesKey);
+ for (int it = 0; it < 16384; it++)
+ {
+ hash = Crypto.EncryptAes(hash, encryptor);
+ }
}
// Retrieve bytes 0-4 and 8-12 from the hash
diff --git a/MegaApiClient/MegaApiClient.csproj b/MegaApiClient/MegaApiClient.csproj
index 2cd86b0..aa80385 100644
--- a/MegaApiClient/MegaApiClient.csproj
+++ b/MegaApiClient/MegaApiClient.csproj
@@ -25,6 +25,9 @@
true
true
true
+ false
+ false
+ false
@@ -88,6 +91,7 @@
+
diff --git a/MegaApiClient/Stream/MegaAesCtrStream.cs b/MegaApiClient/Stream/MegaAesCtrStream.cs
index 9628f34..1fa4b3a 100644
--- a/MegaApiClient/Stream/MegaAesCtrStream.cs
+++ b/MegaApiClient/Stream/MegaAesCtrStream.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+ using System.Security.Cryptography;
internal class MegaAesCtrStreamCrypter : MegaAesCtrStream
{
@@ -70,8 +71,9 @@ internal abstract class MegaAesCtrStream : Stream
private readonly Stream stream;
private readonly Mode mode;
- private readonly long[] chunksPositions;
+ private readonly HashSet chunksPositionsCache;
private readonly byte[] counter = new byte[8];
+ private readonly ICryptoTransform encryptor;
private long currentCounter = 0;
private byte[] currentChunkMac = new byte[16];
private byte[] fileMac = new byte[16];
@@ -99,7 +101,16 @@ protected MegaAesCtrStream(Stream stream, long streamLength, Mode mode, byte[] f
this.fileKey = fileKey;
this.iv = iv;
- this.chunksPositions = this.GetChunksPositions(this.streamLength);
+ this.ChunksPositions = this.GetChunksPositions(this.streamLength).ToArray();
+ this.chunksPositionsCache = new HashSet(this.ChunksPositions);
+
+ this.encryptor = Crypto.CreateAesEncryptor(this.fileKey);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ this.encryptor.Dispose();
}
protected enum Mode
@@ -108,10 +119,7 @@ protected enum Mode
Decrypt
}
- public long[] ChunksPositions
- {
- get { return this.chunksPositions; }
- }
+ public long[] ChunksPositions { get; }
public override bool CanRead
{
@@ -159,12 +167,12 @@ public override int Read(byte[] buffer, int offset, int count)
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))
+ if (this.chunksPositionsCache.Contains(pos))
{
if (pos != 0)
{
// Compute the current chunk mac data on each chunk bondary
- this.ComputeChunk();
+ this.ComputeChunk(encryptor);
}
// Init chunk mac with Iv values
@@ -192,7 +200,7 @@ public override int Read(byte[] buffer, int offset, int count)
Array.Copy(this.iv, ivCounter, 8);
Array.Copy(this.counter, 0, ivCounter, 8, 8);
- byte[] encryptedIvCounter = Crypto.EncryptAes(ivCounter, this.fileKey);
+ byte[] encryptedIvCounter = Crypto.EncryptAes(ivCounter, encryptor);
for (int inputPos = 0; inputPos < inputLength; inputPos++)
{
@@ -204,7 +212,7 @@ public override int Read(byte[] buffer, int offset, int count)
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, this.fileKey);
+ this.currentChunkMac = Crypto.EncryptAes(this.currentChunkMac, encryptor);
}
long len = Math.Min(count, this.streamLength - this.position);
@@ -213,7 +221,7 @@ public override int Read(byte[] buffer, int offset, int count)
// When stream is fully processed, we compute the last chunk
if (this.position == this.streamLength)
{
- this.ComputeChunk();
+ this.ComputeChunk(encryptor);
// Compute Meta MAC
for (int i = 0; i < 4; i++)
@@ -263,35 +271,32 @@ private void IncrementCounter()
Array.Copy(counter, this.counter, 8);
}
- private void ComputeChunk()
+ private void ComputeChunk(ICryptoTransform encryptor)
{
for (int i = 0; i < 16; i++)
{
this.fileMac[i] ^= this.currentChunkMac[i];
}
- this.fileMac = Crypto.EncryptAes(this.fileMac, this.fileKey);
+ this.fileMac = Crypto.EncryptAes(this.fileMac, encryptor);
}
- private long[] GetChunksPositions(long size)
+ private IEnumerable GetChunksPositions(long size)
{
- List chunks = new List();
- chunks.Add(0);
+ yield return 0;
long chunkStartPosition = 0;
for (int idx = 1; (idx <= 8) && (chunkStartPosition < (size - (idx * 131072))); idx++)
{
chunkStartPosition += idx * 131072;
- chunks.Add(chunkStartPosition);
+ yield return chunkStartPosition;
}
while ((chunkStartPosition + 1048576) < size)
{
chunkStartPosition += 1048576;
- chunks.Add(chunkStartPosition);
+ yield return chunkStartPosition;
}
-
- return chunks.ToArray();
}
}
}
diff --git a/tools/packages.config b/tools/packages.config
new file mode 100644
index 0000000..85fc75c
--- /dev/null
+++ b/tools/packages.config
@@ -0,0 +1,4 @@
+
+
+
+