Browse Source

Resolved #645: Inttroduce IStringEncryptionService

pull/652/head
Halil ibrahim Kalkan 8 years ago
parent
commit
66fcaf9ebf
  1. 9
      framework/Volo.Abp.sln
  2. 31
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs
  3. 44
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs
  4. 103
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs
  5. 20
      framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj
  6. 13
      framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/AbpSecurityTestModule.cs
  7. 26
      framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Encryption/StringEncryptionService_Tests.cs

9
framework/Volo.Abp.sln

@ -212,7 +212,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Mvc.UI.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.EntityFrameworkCore.PostgreSql", "src\Volo.Abp.EntityFrameworkCore.PostgreSql\Volo.Abp.EntityFrameworkCore.PostgreSql.csproj", "{882E82F1-1A57-4BB9-B126-4CBF700C8F0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Localization.Abstractions", "src\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj", "{20513A4E-FAC7-4106-8976-5D79A3BDFED1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.Localization.Abstractions", "src\Volo.Abp.Localization.Abstractions\Volo.Abp.Localization.Abstractions.csproj", "{20513A4E-FAC7-4106-8976-5D79A3BDFED1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Security.Tests", "test\Volo.Abp.Security.Tests\Volo.Abp.Security.Tests.csproj", "{7CE07034-7E02-4C78-B981-F1039412CA5E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -604,6 +606,10 @@ Global
{20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{20513A4E-FAC7-4106-8976-5D79A3BDFED1}.Release|Any CPU.Build.0 = Release|Any CPU
{7CE07034-7E02-4C78-B981-F1039412CA5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CE07034-7E02-4C78-B981-F1039412CA5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CE07034-7E02-4C78-B981-F1039412CA5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CE07034-7E02-4C78-B981-F1039412CA5E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -707,6 +713,7 @@ Global
{77A621CF-9562-411B-A707-C7C02CC3B8FA} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{882E82F1-1A57-4BB9-B126-4CBF700C8F0C} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{20513A4E-FAC7-4106-8976-5D79A3BDFED1} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{7CE07034-7E02-4C78-B981-F1039412CA5E} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

31
framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/IStringEncryptionService.cs

@ -0,0 +1,31 @@
using JetBrains.Annotations;
namespace Volo.Abp.Security.Encryption
{
/// <summary>
/// Can be used to simply encrypt/decrypt texts.
/// Use <see cref="StringEncryptionOptions"/> to configure default values.
/// </summary>
public interface IStringEncryptionService
{
/// <summary>
/// Encrypts a text.
/// </summary>
/// <param name="plainText">The text in plain format</param>
/// <param name="passPhrase">A phrase to use as the encryption key (optional, uses default if not provided)</param>
/// <param name="salt">Salt value (optional, uses default if not provided)</param>
/// <returns>Enrypted text</returns>
[CanBeNull]
string Encrypt([CanBeNull] string plainText, string passPhrase = null, byte[] salt = null);
/// <summary>
/// Decrypts a text that is encrypted by the <see cref="Encrypt"/> method.
/// </summary>
/// <param name="cipherText">The text in encrypted format</param>
/// <param name="passPhrase">A phrase to use as the encryption key (optional, uses default if not provided)</param>
/// <param name="salt">Salt value (optional, uses default if not provided)</param>
/// <returns>Decrypted text</returns>
[CanBeNull]
string Decrypt([CanBeNull] string cipherText, string passPhrase = null, byte[] salt = null);
}
}

44
framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionOptions.cs

@ -0,0 +1,44 @@
using System.Text;
namespace Volo.Abp.Security.Encryption
{
/// <summary>
/// Options used by <see cref="IStringEncryptionService"/>.
/// </summary>
public class StringEncryptionOptions
{
/// <summary>
/// This constant is used to determine the keysize of the encryption algorithm.
/// Default value: 256.
/// </summary>
public int Keysize { get; set; }
/// <summary>
/// Default password to encrypt/decrypt texts.
/// It's recommented to set to another value for security.
/// Default value: "gsKnGZ041HLL4IM8"
/// </summary>
public string DefaultPassPhrase { get; set; }
/// <summary>
/// This constant string is used as a "salt" value for the PasswordDeriveBytes function calls.
/// This size of the IV (in bytes) must = (keysize / 8). Default keysize is 256, so the IV must be
/// 32 bytes long. Using a 16 character string here gives us 32 bytes when converted to a byte array.
/// Default value: Encoding.ASCII.GetBytes("jkE49230Tf093b42")
/// </summary>
public byte[] InitVectorBytes { get; set; }
/// <summary>
/// Default value: Encoding.ASCII.GetBytes("hgt!16kl")
/// </summary>
public byte[] DefaultSalt { get; set; }
public StringEncryptionOptions()
{
Keysize = 256;
DefaultPassPhrase = "gsKnGZ041HLL4IM8";
InitVectorBytes = Encoding.ASCII.GetBytes("jkE49230Tf093b42");
DefaultSalt = Encoding.ASCII.GetBytes("hgt!16kl");
}
}
}

103
framework/src/Volo.Abp.Security/Volo/Abp/Security/Encryption/StringEncryptionService.cs

@ -0,0 +1,103 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Security.Encryption
{
/// <summary>
/// Can be used to simply encrypt/decrypt texts.
/// </summary>
public class StringEncryptionService : IStringEncryptionService, ITransientDependency
{
protected StringEncryptionOptions Options { get; }
public StringEncryptionService(IOptions<StringEncryptionOptions> options)
{
Options = options.Value;
}
public virtual string Encrypt(string plainText, string passPhrase = null, byte[] salt = null)
{
if (plainText == null)
{
return null;
}
if (passPhrase == null)
{
passPhrase = Options.DefaultPassPhrase;
}
if (salt == null)
{
salt = Options.DefaultSalt;
}
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
using (var password = new Rfc2898DeriveBytes(passPhrase, salt))
{
var keyBytes = password.GetBytes(Options.Keysize / 8);
using (var symmetricKey = Aes.Create())
{
symmetricKey.Mode = CipherMode.CBC;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, Options.InitVectorBytes))
{
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
var cipherTextBytes = memoryStream.ToArray();
return Convert.ToBase64String(cipherTextBytes);
}
}
}
}
}
}
public virtual string Decrypt(string cipherText, string passPhrase = null, byte[] salt = null)
{
if (string.IsNullOrEmpty(cipherText))
{
return null;
}
if (passPhrase == null)
{
passPhrase = Options.DefaultPassPhrase;
}
if (salt == null)
{
salt = Options.DefaultSalt;
}
var cipherTextBytes = Convert.FromBase64String(cipherText);
using (var password = new Rfc2898DeriveBytes(passPhrase, salt))
{
var keyBytes = password.GetBytes(Options.Keysize / 8);
using (var symmetricKey = Aes.Create())
{
symmetricKey.Mode = CipherMode.CBC;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, Options.InitVectorBytes))
{
using (var memoryStream = new MemoryStream(cipherTextBytes))
{
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
var plainTextBytes = new byte[cipherTextBytes.Length];
var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
}
}
}
}

20
framework/test/Volo.Abp.Security.Tests/Volo.Abp.Security.Tests.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>Volo.Abp.Security.Tests</AssemblyName>
<PackageId>Volo.Abp.Security.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
</ItemGroup>
</Project>

13
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/AbpSecurityTestModule.cs

@ -0,0 +1,13 @@
using Volo.Abp.Modularity;
namespace Volo.Abp.Security
{
[DependsOn(
typeof(AbpSecurityModule),
typeof(AbpTestBaseModule)
)]
public class AbpSecurityTestModule : AbpModule
{
}
}

26
framework/test/Volo.Abp.Security.Tests/Volo/Abp/Security/Encryption/StringEncryptionService_Tests.cs

@ -0,0 +1,26 @@
using Shouldly;
using Xunit;
namespace Volo.Abp.Security.Encryption
{
public class StringEncryptionService_Tests : AbpIntegratedTest<AbpSecurityTestModule>
{
private readonly IStringEncryptionService _stringEncryptionService;
public StringEncryptionService_Tests()
{
_stringEncryptionService = GetRequiredService<IStringEncryptionService>();
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("This is a plain text!")]
public void Should_Enrypt_And_Decrpyt_With_Default_Options(string plainText)
{
_stringEncryptionService
.Decrypt(_stringEncryptionService.Encrypt(plainText))
.ShouldBe(plainText);
}
}
}
Loading…
Cancel
Save