Skip to content

Commit 28d88d5

Browse files
committed
Add fluent configuration support
1 parent 3a699ba commit 28d88d5

File tree

16 files changed

+317
-61
lines changed

16 files changed

+317
-61
lines changed

EntityFrameworkCore.DataEncryption.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
2929
.github\workflows\build.yml = .github\workflows\build.yml
3030
EndProjectSection
3131
EndProject
32+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AesSample.Fluent", "samples\AesSample.Fluent\AesSample.Fluent.csproj", "{CF04DE64-713F-4ED3-9C14-B7C11D22454C}"
33+
EndProject
3234
Global
3335
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3436
Debug|Any CPU = Debug|Any CPU
@@ -47,6 +49,10 @@ Global
4749
{8AA1E576-4016-4623-96C8-90330F05F9A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
4850
{8AA1E576-4016-4623-96C8-90330F05F9A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
4951
{8AA1E576-4016-4623-96C8-90330F05F9A8}.Release|Any CPU.Build.0 = Release|Any CPU
52+
{CF04DE64-713F-4ED3-9C14-B7C11D22454C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53+
{CF04DE64-713F-4ED3-9C14-B7C11D22454C}.Debug|Any CPU.Build.0 = Debug|Any CPU
54+
{CF04DE64-713F-4ED3-9C14-B7C11D22454C}.Release|Any CPU.ActiveCfg = Release|Any CPU
55+
{CF04DE64-713F-4ED3-9C14-B7C11D22454C}.Release|Any CPU.Build.0 = Release|Any CPU
5056
EndGlobalSection
5157
GlobalSection(SolutionProperties) = preSolution
5258
HideSolutionNode = FALSE
@@ -57,6 +63,7 @@ Global
5763
{8AA1E576-4016-4623-96C8-90330F05F9A8} = {64C3D7D1-67B8-4070-AE67-C71B761535CC}
5864
{EEF46CDC-C438-48FC-BEF7-83AEE26C63F7} = {3A8D800E-77BD-44EF-82DB-C672281ECAAA}
5965
{4F549FEF-C57B-4A34-A2C7-8A632762DF85} = {EEF46CDC-C438-48FC-BEF7-83AEE26C63F7}
66+
{CF04DE64-713F-4ED3-9C14-B7C11D22454C} = {64C3D7D1-67B8-4070-AE67-C71B761535CC}
6067
EndGlobalSection
6168
GlobalSection(ExtensibilityGlobals) = postSolution
6269
SolutionGuid = {4997BAE9-29BF-4D79-AE5E-5605E7A0F049}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net6.0;net5.0</TargetFrameworks>
6+
<LangVersion>10</LangVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup Condition="('$(TargetFramework)' == 'net5.0')">
10+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="[5,)" />
11+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="[5,)" />
12+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="[5,)" />
13+
</ItemGroup>
14+
<ItemGroup Condition="('$(TargetFramework)' == 'net6.0')">
15+
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="[6,)" />
16+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="[6,)" />
17+
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="[6,)" />
18+
</ItemGroup>
19+
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\EntityFrameworkCore.DataEncryption\EntityFrameworkCore.DataEncryption.csproj" />
22+
</ItemGroup>
23+
24+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.DataEncryption;
3+
using System.ComponentModel.DataAnnotations;
4+
5+
namespace AesSample.Fluent;
6+
7+
public class DatabaseContext : DbContext
8+
{
9+
private readonly IEncryptionProvider _encryptionProvider;
10+
11+
public DbSet<UserEntity> Users { get; set; }
12+
13+
public DatabaseContext(DbContextOptions<DatabaseContext> options, IEncryptionProvider encryptionProvider)
14+
: base(options)
15+
{
16+
_encryptionProvider = encryptionProvider;
17+
}
18+
19+
protected override void OnModelCreating(ModelBuilder modelBuilder)
20+
{
21+
var userEntityBuilder = modelBuilder.Entity<UserEntity>();
22+
23+
userEntityBuilder.HasKey(x => x.Id);
24+
userEntityBuilder.Property(x => x.Id).IsRequired().ValueGeneratedOnAdd();
25+
userEntityBuilder.Property(x => x.FirstName).IsRequired();
26+
userEntityBuilder.Property(x => x.LastName).IsRequired();
27+
userEntityBuilder.Property(x => x.Email).IsRequired().IsEncrypted();
28+
userEntityBuilder.Property(x => x.EncryptedData).IsRequired().IsEncrypted();
29+
userEntityBuilder.Property(x => x.EncryptedDataAsString).IsRequired().HasColumnType("TEXT").IsEncrypted(StorageFormat.Base64);
30+
31+
modelBuilder.UseEncryption(_encryptionProvider);
32+
33+
base.OnModelCreating(modelBuilder);
34+
}
35+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using Microsoft.Data.Sqlite;
2+
using Microsoft.EntityFrameworkCore.DataEncryption.Providers;
3+
using Microsoft.EntityFrameworkCore;
4+
using System;
5+
using System.Linq;
6+
7+
namespace AesSample.Fluent;
8+
9+
internal class Program
10+
{
11+
static void Main(string[] args)
12+
{
13+
using SqliteConnection connection = new("DataSource=:memory:");
14+
connection.Open();
15+
16+
var options = new DbContextOptionsBuilder<DatabaseContext>()
17+
.UseSqlite(connection)
18+
.Options;
19+
20+
// AES key randomly generated at each run.
21+
AesKeyInfo keyInfo = AesProvider.GenerateKey(AesKeySize.AES256Bits);
22+
byte[] encryptionKey = keyInfo.Key;
23+
byte[] encryptionIV = keyInfo.IV;
24+
var encryptionProvider = new AesProvider(encryptionKey, encryptionIV);
25+
26+
using var context = new DatabaseContext(options, encryptionProvider);
27+
context.Database.EnsureCreated();
28+
29+
var user = new UserEntity
30+
{
31+
FirstName = "John",
32+
LastName = "Doe",
33+
Email = "[email protected]",
34+
EncryptedData = new byte[2] { 1, 2 },
35+
EncryptedDataAsString = new byte[2] { 3, 4 }
36+
};
37+
38+
context.Users.Add(user);
39+
context.SaveChanges();
40+
41+
Console.WriteLine($"Users count: {context.Users.Count()}");
42+
43+
user = context.Users.First();
44+
45+
Console.WriteLine($"User: {user.FirstName} {user.LastName} - {user.Email}");
46+
}
47+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
3+
namespace AesSample.Fluent;
4+
5+
public class UserEntity
6+
{
7+
public Guid Id { get; set; }
8+
9+
public string FirstName { get; set; }
10+
11+
public string LastName { get; set; }
12+
13+
public string Email { get; set; }
14+
15+
public byte[] EncryptedData { get; set; }
16+
17+
public byte[] EncryptedDataAsString { get; set; }
18+
}

samples/AesSample/AesSample.csproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<PropertyGroup>
4-
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
6-
<LangVersion>10</LangVersion>
7-
</PropertyGroup>
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
6+
<LangVersion>10</LangVersion>
7+
</PropertyGroup>
88

99
<ItemGroup Condition="('$(TargetFramework)' == 'net5.0')">
1010
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="[5,)" />
@@ -17,8 +17,8 @@
1717
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="[6,)" />
1818
</ItemGroup>
1919

20-
<ItemGroup>
21-
<ProjectReference Include="..\..\src\EntityFrameworkCore.DataEncryption\EntityFrameworkCore.DataEncryption.csproj" />
22-
</ItemGroup>
20+
<ItemGroup>
21+
<ProjectReference Include="..\..\src\EntityFrameworkCore.DataEncryption\EntityFrameworkCore.DataEncryption.csproj" />
22+
</ItemGroup>
2323

2424
</Project>

samples/AesSample/Program.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
using Microsoft.EntityFrameworkCore;
1+
using Microsoft.Data.Sqlite;
2+
using Microsoft.EntityFrameworkCore;
23
using Microsoft.EntityFrameworkCore.DataEncryption.Providers;
34
using System;
45
using System.Linq;
5-
using System.Security;
66

77
namespace AesSample;
88

99
static class Program
1010
{
1111
static void Main()
1212
{
13+
using SqliteConnection connection = new("DataSource=:memory:");
14+
connection.Open();
15+
1316
var options = new DbContextOptionsBuilder<DatabaseContext>()
14-
.UseInMemoryDatabase(databaseName: "MyInMemoryDatabase")
17+
.UseSqlite(connection)
1518
.Options;
1619

1720
// AES key randomly generated at each run.
@@ -21,6 +24,7 @@ static void Main()
2124
var encryptionProvider = new AesProvider(encryptionKey, encryptionIV);
2225

2326
using var context = new DatabaseContext(options, encryptionProvider);
27+
context.Database.EnsureCreated();
2428

2529
var user = new UserEntity
2630
{

samples/AesSample/UserEntity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ public class UserEntity
2626

2727
[Required]
2828
[Encrypted(StorageFormat.Base64)]
29-
[Column(TypeName = "VARCHAR(MAX)")]
29+
[Column(TypeName = "TEXT")]
3030
public byte[] EncryptedDataAsString { get; set; }
3131
}

src/EntityFrameworkCore.DataEncryption/Internal/EncryptionConverter.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ private static TModel Decrypt<TInput, TOupout>(TProvider input, IEncryptionProvi
5454
StorageFormat.Default or StorageFormat.Base64 => Convert.FromBase64String(input.ToString()),
5555
_ => input as byte[]
5656
};
57-
5857
byte[] decryptedRawBytes = encryptionProvider.Decrypt(inputData);
59-
6058
object decryptedData = null;
6159

6260
if (destinationType == typeof(string))
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Microsoft.EntityFrameworkCore.DataEncryption.Internal;
2+
3+
internal class PropertyAnnotations
4+
{
5+
public const string IsEncrypted = "Microsoft.EntityFrameworkCore.DataEncryption.IsEncrypted";
6+
public const string StorageFormat = "Microsoft.EntityFrameworkCore.DataEncryption.StorageFormat";
7+
}

0 commit comments

Comments
 (0)