mirror of https://github.com/abpframework/abp.git
7 changed files with 245 additions and 1 deletions
@ -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); |
|||
} |
|||
} |
|||
@ -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"); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -0,0 +1,13 @@ |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Security |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpSecurityModule), |
|||
typeof(AbpTestBaseModule) |
|||
)] |
|||
public class AbpSecurityTestModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -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…
Reference in new issue