Skip to content

Commit

Permalink
Merge pull request #2344 from anurakt27/master
Browse files Browse the repository at this point in the history
  • Loading branch information
mbdavid authored Jul 20, 2023
2 parents 84faf67 + 5afa254 commit 967c413
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
83 changes: 82 additions & 1 deletion LiteDB.Tests/Internals/Aes_Tests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.IO;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using FluentAssertions;
using LiteDB.Engine;
using Xunit;
Expand Down Expand Up @@ -61,5 +64,83 @@ public void Encrypt_Decrypt_Stream()
output2.All(x => x == 102).Should().BeTrue();
}
}

/// <summary>
/// Test whether AesStream can handle stream that has invalid page size.
/// </summary>
[Fact]
public void AesStream_Invalid_Page_Size()
{
var fakeContent = new byte[] {
1,22,222,184,3,227,126,129,205,182,182,143,201,181,242,107,36,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
20,88,18,70,65,77,202,50,184,177,167,59,80,255,67,66,20,
88,18,70,65,77,202,50,184,177,167,59,80,255,67,66
};

// stream of 64bytes (invalid page size)
using (var memoryStream = new MemoryStream())
{
memoryStream.Write(fakeContent, 0, fakeContent.Length);
memoryStream.Position = 0;

using (var crypto = new AesStream("password", memoryStream))
{
// 1st page is hidden, so AesStream.Length returns (stream.Length - PAGE_SIZE)
Assert.Equal(0, crypto.Length);

// AesStream should add padding to the underlying stream to make its size equivalent to PAGE_SIZE
Assert.Equal(8192, memoryStream.Length);
}
}
}

/// <summary>
/// Test whether AesStream can handle stream where bytes 32-64 are empty.
/// </summary>
[Fact]
public void AesStream_Invalid_Password()
{
// stream of 8192 bytes where bytes 32 to 64 is empty.
using (var memoryStream = new MemoryStream())
{
// 1st byte to indicate the stream is encrypted
memoryStream.WriteByte(1);

// next 16 bytes contain salt
var salt = new byte[16];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
memoryStream.Write(salt, 0, salt.Length);

// remaining (8192 - 17) bytes are empty
var emptyContent = new byte[8175];
memoryStream.Write(emptyContent, 0, emptyContent.Length);

// reset the stream position to 0
memoryStream.Position = 0;

using (var crypto = new AesStream("password", memoryStream))
{
// 1st page is hidden, so AesStream.Length returns (stream.Length - PAGE_SIZE)
Assert.Equal(0, crypto.Length);

// AesStream should add padding to the underlying stream to make its size equivalent to PAGE_SIZE
Assert.Equal(8192, memoryStream.Length);

// AesStream should fill bytes 32-64 with encrypted 1s
var checkBytes = new byte[32];
var cryptoReader = typeof(AesStream)
.GetField("_reader", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(crypto) as CryptoStream;

memoryStream.Position = 32;
cryptoReader.Read(checkBytes, 0, checkBytes.Length);
Assert.All(checkBytes, b => Assert.Equal(1, b));
}
}
}
}
}
14 changes: 11 additions & 3 deletions LiteDB/Engine/Disk/Streams/AesStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ public AesStream(string password, Stream stream)
// first byte =1 means this datafile is encrypted
_stream.WriteByte(1);
_stream.Write(this.Salt, 0, ENCRYPTION_SALT_SIZE);

// fill with 0 full PAGE_SIZE
_stream.Write(_emptyContent, 0, _emptyContent.Length);
}
else
{
Expand Down Expand Up @@ -109,6 +106,17 @@ public AesStream(string password, Stream stream)

var checkBuffer = new byte[32];

if (!isNew)
{
// check whether bytes 32 to 64 is empty. This indicates LiteDb was unable to write encrypted 1s during last attempt.
_stream.Read(checkBuffer, 0, checkBuffer.Length);
isNew = checkBuffer.All(x => x == 0);

// reset checkBuffer and stream position
Array.Clear(checkBuffer, 0, checkBuffer.Length);
_stream.Position = 32;
}

// fill checkBuffer with encrypted 1 to check when open
if (isNew)
{
Expand Down

0 comments on commit 967c413

Please # to comment.