Skip to content

Commit

Permalink
Fixes for StringCypher
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisg32 committed Apr 27, 2021
1 parent e958133 commit ba60d54
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Commons.Test/Commons.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.0" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
Expand Down
26 changes: 26 additions & 0 deletions Commons.Test/Util/StringCypherTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using CG.Commons.Util;
using Xunit;
using FluentAssertions;

namespace CG.Commons.Test.Util
{
public class StringCypherTest
{
private const string Passphrase = "1F267C5E-FF0D-4C11-DG23-F0855348D2B8";

[Fact]
public void TestEncryptDecrypt()
{
//arrange
const string testString = "This is a test string. It will be encrypted and decrypted.";

//act
var encrypted = StringCipher.Encrypt(testString, Passphrase);
var decrypted = StringCipher.Decrypt(encrypted, Passphrase);

//assert
encrypted.Should().NotBeNullOrEmpty();
decrypted.Should().NotBeNullOrEmpty().And.Should().BeEquivalentTo(testString);
}
}
}
12 changes: 6 additions & 6 deletions Commons/Commons.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>A collection of useful C# utilities, extensions, and data structures.</Description>
<Authors>Chris Gonzales</Authors>
<Version>1.0.8</Version>
<Version>1.0.9</Version>
<PackageTags>Commons C# DataStructures Dictionary Extensions</PackageTags>
<Copyright>Copyright 2021 Chris Gonzales</Copyright>
<PackageIconUrl>https://chrisg32.github.io/assets/cg_logo.png</PackageIconUrl>
Expand All @@ -19,18 +19,18 @@
<Product>CG Commons Library</Product>
<RepositoryType>Git</RepositoryType>
<RepositoryUrl>https://github.com/chrisg32/Commons</RepositoryUrl>
<PackageReleaseNotes>Fix for string Cypher AES bit length.</PackageReleaseNotes>
<PackageReleaseNotes>Fix for string Cypher AES broken decryption. WARNING! make break the ability to decrypt strings encrypted with 1.0.7 and below.</PackageReleaseNotes>
<AssemblyName>CG.Commons</AssemblyName>
<NeutralLanguage>en-US</NeutralLanguage>
<PackageVersion>1.0.8</PackageVersion>
<PackageVersion>1.0.9</PackageVersion>
<Title>Commons</Title>
<LangVersion>9</LangVersion>
<AssemblyVersion>1.0.8</AssemblyVersion>
<FileVersion>1.0.8</FileVersion>
<AssemblyVersion>1.0.9</AssemblyVersion>
<FileVersion>1.0.9</FileVersion>
</PropertyGroup>

<ItemGroup>
<None Include="logo.png" Pack="true" PackagePath=""/>
<None Include="logo.png" Pack="true" PackagePath="" />
</ItemGroup>

</Project>
18 changes: 12 additions & 6 deletions Commons/Util/StringCipher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public static class StringCipher
// This constant is used to determine the keysize of the encryption algorithm in bits.
// We divide this by 8 within the code below to get the equivalent number of bytes.
private const int Keysize = 256;

private const int BlockSize = 128;

// This constant determines the number of iterations for the password bytes generation function.
private const int DerivationIterations = 1000;
Expand All @@ -29,7 +31,7 @@ public static string Encrypt(string plainText, string passPhrase)
using (var symmetricKey = Aes.Create())
{
//https://stackoverflow.com/questions/9300340/got-error-specified-block-size-is-not-valid-for-this-algorithm-while-initiali
symmetricKey.BlockSize = 128;
symmetricKey.BlockSize = BlockSize;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
Expand All @@ -55,22 +57,26 @@ public static string Encrypt(string plainText, string passPhrase)
public static string Decrypt(string cipherText, string passPhrase)
{
if (cipherText == null) return null;

var saltLength = Keysize / 8;
var ivLength = BlockSize / 8;

// Get the complete stream of bytes that represent:
// [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
// Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
// Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(saltLength).ToArray();
// Get the IV bytes by extracting the next 16 bytes from the supplied cipherText bytes.
var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(saltLength).Take(ivLength).ToArray();
// Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip(saltLength + ivLength).Take(cipherTextBytesWithSaltAndIv.Length - (saltLength + ivLength)).ToArray();

using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
{
var keyBytes = password.GetBytes(Keysize / 8);
using (var symmetricKey = Aes.Create())
{
symmetricKey.BlockSize = 256;
symmetricKey.BlockSize = BlockSize;
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
Expand Down

0 comments on commit ba60d54

Please sign in to comment.