Skip to content

Commit

Permalink
Merge pull request #25 from RichardD2/feature/data-types
Browse files Browse the repository at this point in the history
Enahnced data type support
  • Loading branch information
Filipe GP authored Apr 18, 2021
2 parents 8cfe4c2 + 376b9ba commit 546e04a
Show file tree
Hide file tree
Showing 33 changed files with 1,742 additions and 212 deletions.
39 changes: 39 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[*.cs]
indent_style = space
indent_size = 4

csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = methods, object_collection_array_initializers, control_blocks, types
dotnet_sort_system_directives_first = true

csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false

csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
csharp_prefer_braces = true:warning

csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion

dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
csharp_preferred_modifier_order = public,private,internal,protected,static,readonly,sealed,async,override,abstract:suggestion

dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_object_initializer = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion

dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
4 changes: 4 additions & 0 deletions EntityFrameworkCore.DataEncryption.sln
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{
ProjectSection(SolutionItems) = preProject
.azure\pipelines\azure-pipelines.yml = .azure\pipelines\azure-pipelines.yml
EndProjectSection
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5EE4E8BE-6B15-49DB-A4A8-D2CD63D5E90C}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
27 changes: 22 additions & 5 deletions samples/AesSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
using Microsoft.EntityFrameworkCore.DataEncryption.Providers;
using System;
using System.Linq;
using System.Security;

namespace AesSample
{
class Program
static class Program
{
static void Main(string[] args)
static void Main()
{
var options = new DbContextOptionsBuilder<DatabaseContext>()
.UseInMemoryDatabase(databaseName: "MyInMemoryDatabase")
Expand All @@ -23,17 +24,33 @@ static void Main(string[] args)
{
FirstName = "John",
LastName = "Doe",
Email = "[email protected]"
Email = "[email protected]",
Password = BuildPassword(),
};

context.Users.Add(user);
context.SaveChanges();

Console.WriteLine($"Users count: {context.Users.Count()}");

user = context.Users.FirstOrDefault();
user = context.Users.First();

Console.WriteLine($"User: {user.FirstName} {user.LastName} - {user.Email}");
Console.WriteLine($"User: {user.FirstName} {user.LastName} - {user.Email} ({user.Password.Length})");
}

static SecureString BuildPassword()
{
SecureString result = new();
result.AppendChar('L');
result.AppendChar('e');
result.AppendChar('t');
result.AppendChar('M');
result.AppendChar('e');
result.AppendChar('I');
result.AppendChar('n');
result.AppendChar('!');
result.MakeReadOnly();
return result;
}
}
}
3 changes: 3 additions & 0 deletions samples/AesSample/UserEntity.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Security;

namespace AesSample
{
Expand All @@ -19,5 +20,7 @@ public class UserEntity
[Required]
[Encrypted]
public string Email { get; set; }

public SecureString Password { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,27 @@
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class EncryptedAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="EncryptedAttribute"/> class.
/// </summary>
/// <param name="format">
/// The storage format.
/// </param>
public EncryptedAttribute(StorageFormat format)
{
Format = format;
}

/// <summary>
/// Initializes a new instance of the <see cref="EncryptedAttribute"/> class.
/// </summary>
public EncryptedAttribute() : this(StorageFormat.Default)
{
}

/// <summary>
/// Returns the storage format for the database value.
/// </summary>
public StorageFormat Format { get; }
}
}
}
26 changes: 26 additions & 0 deletions src/EntityFrameworkCore.DataEncryption/Attributes/StorageFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace System.ComponentModel.DataAnnotations
{
/// <summary>
/// Represents the storage format for an encrypted value.
/// </summary>
public enum StorageFormat
{
/// <summary>
/// The format is determined by the model data type.
/// </summary>
Default,
/// <summary>
/// The value is stored in binary.
/// </summary>
Binary,
/// <summary>
/// The value is stored in a Base64-encoded string.
/// </summary>
/// <remarks>
/// <b>NB:</b> If the source property is a <see cref="string"/>,
/// and no encryption provider is configured,
/// the string will not be modified.
/// </remarks>
Base64,
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<AssemblyName>EntityFrameworkCore.DataEncryption</AssemblyName>
<RootNamespace>Microsoft.EntityFrameworkCore.DataEncryption</RootNamespace>
<Version>2.0.0</Version>
<Authors>Filipe GOMES PEIXOTO</Authors>
<PackageId>EntityFrameworkCore.DataEncryption</PackageId>
<PackageProjectUrl>https://github.com/Eastrall/EntityFrameworkCore.DataEncryption</PackageProjectUrl>
<RepositoryUrl>https://github.com/Eastrall/EntityFrameworkCore.DataEncryption.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>entity-framework-core, extensions, dotnet-core, dotnet, encryption, fluent-api</PackageTags>
<LangVersion>8.0</LangVersion>
<PackageIcon>icon.png</PackageIcon>
<Copyright>Filipe GOMES PEIXOTO © 2019 - 2020</Copyright>
<Description>A plugin for Microsoft.EntityFrameworkCore to add support of encrypted fields using built-in or custom encryption providers.</Description>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageReleaseNotes>- Remove initializationVector parameter from `AesProvider` constructor.
- Apply unique IV for each row.</PackageReleaseNotes>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>EntityFrameworkCore.DataEncryption</AssemblyName>
<RootNamespace>Microsoft.EntityFrameworkCore.DataEncryption</RootNamespace>
<Version>3.0.0</Version>
<Authors>Filipe GOMES PEIXOTO</Authors>
<PackageId>EntityFrameworkCore.DataEncryption</PackageId>
<PackageProjectUrl>https://github.com/Eastrall/EntityFrameworkCore.DataEncryption</PackageProjectUrl>
<RepositoryUrl>https://github.com/Eastrall/EntityFrameworkCore.DataEncryption.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>entity-framework-core, extensions, dotnet-core, dotnet, encryption, fluent-api</PackageTags>
<PackageIcon>icon.png</PackageIcon>
<Copyright>Filipe GOMES PEIXOTO © 2019 - 2020</Copyright>
<Description>A plugin for Microsoft.EntityFrameworkCore to add support of encrypted fields using built-in or custom encryption providers.</Description>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageReleaseNotes>
- Add support for storing data as binary or Base64
- Add support for SecureString and binary model properties
</PackageReleaseNotes>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.0" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<None Include="Resources/icon.png" Pack="true" Visible="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<None Include="Resources/icon.png" Pack="true" Visible="true" PackagePath="" />
</ItemGroup>

<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Microsoft.EntityFrameworkCore.Encryption.Test</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp90</s:String></wpf:ResourceDictionary>
63 changes: 54 additions & 9 deletions src/EntityFrameworkCore.DataEncryption/IEncryptionProvider.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,67 @@
namespace Microsoft.EntityFrameworkCore.DataEncryption
using System;
using System.IO;

namespace Microsoft.EntityFrameworkCore.DataEncryption
{
/// <summary>
/// Provides a mechanism for implementing a custom encryption provider.
/// </summary>
public interface IEncryptionProvider
{
/// <summary>
/// Encrypts a string.
/// Encrypts a value.
/// </summary>
/// <param name="dataToEncrypt">Input data as a string to encrypt.</param>
/// <returns>Encrypted data as a string.</returns>
string Encrypt(string dataToEncrypt);
/// <typeparam name="TStore">
/// The type of data stored in the database.
/// </typeparam>
/// <typeparam name="TModel">
/// The type of value stored in the model.
/// </typeparam>
/// <param name="dataToEncrypt">
/// Input data to encrypt.
/// </param>
/// <param name="converter">
/// Function which converts the model value to a byte array.
/// </param>
/// <param name="encoder">
/// Function which encodes the value for storing the the database.
/// </param>
/// <returns>
/// Encrypted data.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="converter"/> is <see langword="null"/>.</para>
/// <para>-or-</para>
/// <para><paramref name="encoder"/> is <see langword="null"/>.</para>
/// </exception>
TStore Encrypt<TStore, TModel>(TModel dataToEncrypt, Func<TModel, byte[]> converter, Func<Stream, TStore> encoder);

/// <summary>
/// Decrypts a string.
/// Decrypts a value.
/// </summary>
/// <param name="dataToDecrypt">Encrypted data as a string to decrypt.</param>
/// <returns>Decrypted data as a string.</returns>
string Decrypt(string dataToDecrypt);
/// <typeparam name="TStore">
/// The type of data stored in the database.
/// </typeparam>
/// <typeparam name="TModel">
/// The type of value stored in the model.
/// </typeparam>
/// <param name="dataToDecrypt">
/// Encrypted data to decrypt.
/// </param>
/// <param name="decoder">
/// Function which converts the stored data to a byte array.
/// </param>
/// <param name="converter">
/// Function which converts the decrypted <see cref="Stream"/> to the return value.
/// </param>
/// <returns>
/// Decrypted data.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="decoder"/> is <see langword="null"/>.</para>
/// <para>-or-</para>
/// <para><paramref name="converter"/> is <see langword="null"/>.</para>
/// </exception>
TModel Decrypt<TStore, TModel>(TStore dataToDecrypt, Func<TStore, byte[]> decoder, Func<Stream, TModel> converter);
}
}
Loading

0 comments on commit 546e04a

Please sign in to comment.