From 1e52830e83dee5eed25519b1c34b6752d66dcf8e Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Tue, 19 Aug 2014 13:54:48 +1000 Subject: [PATCH] Add multi encryption key support finish encryption fix refactor breaking a test Multi decryption key support --- packages/repositories.config | 1 + .../ConfigureRijndaelEncryptionService.cs | 44 +++++- ...rviceBus.Encryption.Rijndael.Config.csproj | 3 +- .../Properties/AssemblyInfo.cs | Bin 1508 -> 1602 bytes .../RijndaelEncryptionServiceConfig.cs | 17 ++ .../RijndaelExpiredKey.cs | 35 +++++ .../RijndaelExpiredKeyCollection.cs | 148 ++++++++++++++++++ ...ConfigureRijndaelEncryptionServiceTests.cs | 140 +++++++++++++++++ .../EncryptionServiceTests.cs | 97 ++++++++++++ ...erviceBus.Encryption.Rijndael.Tests.csproj | 69 ++++++++ .../packages.config | 4 + .../EncryptionService.cs | 88 ++++++++++- .../Properties/AssemblyInfo.cs | Bin 1498 -> 1740 bytes src/impl/encryption/encryption.sln | 12 +- src/impl/encryption/nuget.config | 4 + 15 files changed, 651 insertions(+), 11 deletions(-) create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKey.cs create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKeyCollection.cs create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/ConfigureRijndaelEncryptionServiceTests.cs create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/EncryptionServiceTests.cs create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/NServiceBus.Encryption.Rijndael.Tests.csproj create mode 100644 src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/packages.config create mode 100644 src/impl/encryption/nuget.config diff --git a/packages/repositories.config b/packages/repositories.config index 41c5a3f89e..a35dc97ea8 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -43,6 +43,7 @@ + diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/ConfigureRijndaelEncryptionService.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/ConfigureRijndaelEncryptionService.cs index b8e8725245..ef3e669b1a 100644 --- a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/ConfigureRijndaelEncryptionService.cs +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/ConfigureRijndaelEncryptionService.cs @@ -1,8 +1,11 @@ -using System.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; using Common.Logging; using NServiceBus.Config; +using NServiceBus.Encryption; using NServiceBus.Encryption.Rijndael; -using NServiceBus.ObjectBuilder; namespace NServiceBus { @@ -24,13 +27,48 @@ public static Configure RijndaelEncryptionService(this Configure config) Logger.Warn("Could not find configuration section for Rijndael Encryption Service."); var encryptConfig = config.Configurer.ConfigureComponent(DependencyLifecycle.SingleInstance); - if (section != null) + { + if (string.IsNullOrWhiteSpace(section.Key)) + { + throw new Exception("The RijndaelEncryptionServiceConfig has an empty 'Key' attribute."); + } encryptConfig.ConfigureProperty(s => s.Key, Encoding.ASCII.GetBytes(section.Key)); + var expiredKeys = ExtractExpiredKeysFromConfigSection(section); + if (expiredKeys != null) + { + encryptConfig.ConfigureProperty(s => s.ExpiredKeys, expiredKeys.Select(x => Encoding.ASCII.GetBytes(x)).ToList()); + } + } return config; } + internal static List ExtractExpiredKeysFromConfigSection(RijndaelEncryptionServiceConfig section) + { + if (section.ExpiredKeys == null) + { + return new List(); + } + var encryptionKeys = section.ExpiredKeys + .Cast() + .Select(x => x.Key) + .ToList(); + if (encryptionKeys.Any(string.IsNullOrWhiteSpace)) + { + throw new Exception("The RijndaelEncryptionServiceConfig has a 'ExpiredKeys' property defined however some keys have no data."); + } + if (encryptionKeys.Any(x => x == section.Key)) + { + throw new Exception("The RijndaelEncryptionServiceConfig has a 'Key' that is also defined inside the 'ExpiredKeys'."); + } + + if (encryptionKeys.Count != encryptionKeys.Distinct().Count()) + { + throw new Exception("The RijndaelEncryptionServiceConfig has overlapping ExpiredKeys defined. Please ensure that no keys overlap in the 'ExpiredKeys' property."); + } + return encryptionKeys; + } private static readonly ILog Logger = LogManager.GetLogger(typeof(RijndaelEncryptionServiceConfig)); } } diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/NServiceBus.Encryption.Rijndael.Config.csproj b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/NServiceBus.Encryption.Rijndael.Config.csproj index 0f0016295c..263a06dcbf 100644 --- a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/NServiceBus.Encryption.Rijndael.Config.csproj +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/NServiceBus.Encryption.Rijndael.Config.csproj @@ -55,10 +55,11 @@ - + + diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/Properties/AssemblyInfo.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/Properties/AssemblyInfo.cs index fe272c36c45c562b47c86ca238f58fe90203cf0e..90c328d42f751c848d3ff73cd67d4e6d86bea4a1 100644 GIT binary patch delta 132 zcmaFDeTZkmo{4z^8~=2%OuoV*HF*iE&Ey*_V#=Njc?=~CsSHIxI*}oVp_n0zArnYu zG9&?csSF_u`IG-MOFQW?xB^uq1JzYB6aaN(GUNmKdJI88Ru+(z0@R%f)S(B|kqXpb R0>nxTnhdcFybN4m3;@|U9`gVI delta 45 zcmX@a^MrfC9{ym4REA`RQidXiOokGM%89;)8_#sHFmp0+PW&i6xq#J%g_nVg0RTn{ B44eP} diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelEncryptionServiceConfig.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelEncryptionServiceConfig.cs index 9f74c530cb..48aa516d04 100644 --- a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelEncryptionServiceConfig.cs +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelEncryptionServiceConfig.cs @@ -2,6 +2,7 @@ namespace NServiceBus.Config { + public class RijndaelEncryptionServiceConfig : ConfigurationSection { /// @@ -19,5 +20,21 @@ public string Key this["Key"] = value; } } + + /// + /// Contains the expired decryptions that are currently being phased out. + /// + [ConfigurationProperty("ExpiredKeys", IsRequired = false)] + public RijndaelExpiredKeyCollection ExpiredKeys + { + get + { + return this["ExpiredKeys"] as RijndaelExpiredKeyCollection; + } + set + { + this["ExpiredKeys"] = value; + } + } } } diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKey.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKey.cs new file mode 100644 index 0000000000..6b2411c8fc --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKey.cs @@ -0,0 +1,35 @@ +using System; +using System.Configuration; + +namespace NServiceBus.Config +{ + /// + /// A configuration element representing a Rijndael encryption key. + /// + public class RijndaelExpiredKey : ConfigurationElement, IComparable + { + + /// + /// The keys value. + /// + [ConfigurationProperty("Key", IsRequired = true)] + public string Key + { + get + { + return (string)this["Key"]; + } + set + { + this["Key"] = value; + } + } + + + int IComparable.CompareTo(RijndaelExpiredKey other) + { + return String.Compare(Key, other.Key, StringComparison.Ordinal); + } + + } +} \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKeyCollection.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKeyCollection.cs new file mode 100644 index 0000000000..f57b3cd5d4 --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Config/RijndaelExpiredKeyCollection.cs @@ -0,0 +1,148 @@ +using System; +using System.Configuration; + +namespace NServiceBus.Config +{ + /// + /// A configuration element collection of s. + /// + public class RijndaelExpiredKeyCollection : ConfigurationElementCollection + { + /// + /// Returns AddRemoveClearMap. + /// + public override ConfigurationElementCollectionType CollectionType + { + get + { + return ConfigurationElementCollectionType.AddRemoveClearMap; + } + } + + /// + /// Creates a new . + /// + protected override ConfigurationElement CreateNewElement() + { + return new RijndaelExpiredKey(); + } + + /// + /// Creates a new , setting its property to the given value. + /// + protected override ConfigurationElement CreateNewElement(string elementName) + { + return new RijndaelExpiredKey + { + Key = elementName + }; + } + + /// + /// Returns the Messages property of the given element. + /// + protected override Object GetElementKey(ConfigurationElement element) + { + var encryptionKey = (RijndaelExpiredKey)element; + + return encryptionKey.Key; + } + + /// + /// Gets/sets the at the given index. + /// + public RijndaelExpiredKey this[int index] + { + get + { + return (RijndaelExpiredKey)BaseGet(index); + } + set + { + if (BaseGet(index) != null) + { + BaseRemoveAt(index); + } + BaseAdd(index, value); + } + } + + /// + /// Gets the for the given key. + /// + new public RijndaelExpiredKey this[string key] + { + get + { + return (RijndaelExpiredKey)BaseGet(key); + } + } + + /// + /// Calls BaseIndexOf on the given . + /// + public int IndexOf(RijndaelExpiredKey encryptionKey) + { + return BaseIndexOf(encryptionKey); + } + + /// + /// Calls BaseAdd. + /// + public void Add(RijndaelExpiredKey encryptionKey) + { + BaseAdd(encryptionKey); + } + + /// + /// Calls BaseAdd with true as the additional parameter. + /// + protected override void BaseAdd(ConfigurationElement element) + { + BaseAdd(element, true); + } + + /// + /// If the key exists, calls BaseRemove on it. + /// + public void Remove(RijndaelExpiredKey encryptionKey) + { + if (BaseIndexOf(encryptionKey) >= 0) + { + BaseRemove(encryptionKey.Key); + } + } + + /// + /// Calls BaseRemoveAt. + /// + public void RemoveAt(int index) + { + BaseRemoveAt(index); + } + + /// + /// Calls BaseRemove. + /// + public void Remove(string name) + { + BaseRemove(name); + } + + /// + /// Calls BaseClear. + /// + public void Clear() + { + BaseClear(); + } + + /// + /// True if the collection is readonly + /// + public override bool IsReadOnly() + { + return false; + } + } +} \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/ConfigureRijndaelEncryptionServiceTests.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/ConfigureRijndaelEncryptionServiceTests.cs new file mode 100644 index 0000000000..fa2ac30673 --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/ConfigureRijndaelEncryptionServiceTests.cs @@ -0,0 +1,140 @@ +namespace NServiceBus.Core.Tests.Encryption +{ + using System; + using System.Configuration; + using System.IO; + using System.Linq; + using NServiceBus.Config; + using NUnit.Framework; + + [TestFixture] + public class ConfigureRijndaelEncryptionServiceTests + { + + [Test] + public void Can_read_from_xml() + { + var xml = +@" + + +
+ + + + + + + +"; + + var section = ReadSectionFromText(xml); + var keys = section.ExpiredKeys.Cast() + .Select(x => x.Key) + .ToList(); + Assert.AreEqual("key1", section.Key); + Assert.AreEqual(2, keys.Count); + Assert.Contains("key2", keys); + Assert.Contains("key3", keys); + } + + static T ReadSectionFromText(string s) where T : ConfigurationSection + { + var xml = s.Replace("'", "\""); + var tempPath = Path.GetTempFileName(); + try + { + File.WriteAllText(tempPath, xml); + + var fileMap = new ExeConfigurationFileMap + { + ExeConfigFilename = tempPath + }; + + var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + return (T)configuration.GetSection(typeof(T).Name); + } + finally + { + if (File.Exists(tempPath)) + { + File.Delete(tempPath); + } + } + } + + [Test] + public void Should_throw_for_whitespace_keys_in_config() + { + var config = new RijndaelEncryptionServiceConfig + { + ExpiredKeys = new RijndaelExpiredKeyCollection + { + new RijndaelExpiredKey + { + Key = " " + } + } + }; + var exception = Assert.Throws(() => ConfigureRijndaelEncryptionService.ExtractExpiredKeysFromConfigSection(config)); + Assert.AreEqual("The RijndaelEncryptionServiceConfig has a 'ExpiredKeys' property defined however some keys have no data.", exception.Message); + } + + [Test] + public void Should_throw_for_null_keys_in_config() + { + var config = new RijndaelEncryptionServiceConfig + { + ExpiredKeys = new RijndaelExpiredKeyCollection + { + new RijndaelExpiredKey() + } + }; + var exception = Assert.Throws(() => ConfigureRijndaelEncryptionService.ExtractExpiredKeysFromConfigSection(config)); + Assert.AreEqual("The RijndaelEncryptionServiceConfig has a 'ExpiredKeys' property defined however some keys have no data.", exception.Message); + } + + [Test] + public void Should_throw_for_duplicate_between_key_and_keys_in_config() + { + var config = new RijndaelEncryptionServiceConfig + { + Key = "a", + ExpiredKeys = new RijndaelExpiredKeyCollection + { + new RijndaelExpiredKey + { + Key = "a" + } + } + }; + var exception = Assert.Throws(() => ConfigureRijndaelEncryptionService.ExtractExpiredKeysFromConfigSection(config)); + Assert.AreEqual("The RijndaelEncryptionServiceConfig has a 'Key' that is also defined inside the 'ExpiredKeys'.", exception.Message); + } + + [Test] + public void Duplicates_should_be_skipped() + { + var config = new RijndaelEncryptionServiceConfig + { + ExpiredKeys = new RijndaelExpiredKeyCollection + { + new RijndaelExpiredKey + { + Key = "a" + }, + new RijndaelExpiredKey + { + Key = "a" + } + } + }; + var keys = ConfigureRijndaelEncryptionService.ExtractExpiredKeysFromConfigSection(config); + + Assert.That(new[] { "a" }, Is.EquivalentTo(keys)); + } + } + +} \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/EncryptionServiceTests.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/EncryptionServiceTests.cs new file mode 100644 index 0000000000..6824d5a527 --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/EncryptionServiceTests.cs @@ -0,0 +1,97 @@ +namespace NServiceBus.Core.Tests.Encryption +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography; + using System.Text; + using NServiceBus.Encryption; + using NServiceBus.Encryption.Rijndael; + using NUnit.Framework; + + [TestFixture] + public class EncryptionServiceTests + { + [Test] + public void Should_encrypt_and_decrypt() + { + var service = (IEncryptionService)new EncryptionService + { + Key = Encoding.ASCII.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6") + }; + var encryptedValue = service.Encrypt("string to encrypt"); + Assert.AreNotEqual("string to encrypt", encryptedValue.EncryptedBase64Value); + var decryptedValue = service.Decrypt(encryptedValue); + Assert.AreEqual("string to encrypt", decryptedValue); + } + + [Test] + public void Should_encrypt_and_decrypt_for_expired_key() + { + var service1 = (IEncryptionService)new EncryptionService + { + Key = Encoding.ASCII.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6"), + }; + var encryptedValue = service1.Encrypt("string to encrypt"); + Assert.AreNotEqual("string to encrypt", encryptedValue.EncryptedBase64Value); + + + var service2 = (IEncryptionService)new EncryptionService + { + Key = Encoding.ASCII.GetBytes("adDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6"), + ExpiredKeys = new List + { + Encoding.ASCII.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6") + } + }; + + var decryptedValue = service2.Decrypt(encryptedValue); + Assert.AreEqual("string to encrypt", decryptedValue); + } + + [Test] + public void Should_throw_when_decrypt_with_wrong_key() + { + var service1 = (IEncryptionService)new EncryptionService + { + Key = Encoding.ASCII.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6"), + }; + var encryptedValue = service1.Encrypt("string to encrypt"); + Assert.AreNotEqual("string to encrypt", encryptedValue.EncryptedBase64Value); + + var invalidKey = "adDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6"; + var invalidExpiredKeys = new List { "bdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6" }; + + var service2 = (IEncryptionService)new EncryptionService + { + Key = Encoding.ASCII.GetBytes(invalidKey), + ExpiredKeys = invalidExpiredKeys.Select(s => Encoding.ASCII.GetBytes(s)).ToList() + }; + + var exception = Assert.Throws(() => service2.Decrypt(encryptedValue)); + Assert.AreEqual("Could not decrypt message. Tried 2 keys.", exception.Message); + Assert.AreEqual(2, exception.InnerExceptions.Count); + foreach (var inner in exception.InnerExceptions) + { + Assert.IsInstanceOf(inner); + } + } + + [Test] + public void Should_throw_when_encrypt_and_decrypt_keys_are_too_similar() + { + var key = Encoding.ASCII.GetBytes("gdDbqRpqdRbTs3mhdZh9qCaDaxJXl+e6"); + + var exception = Assert.Throws(() => + { + new EncryptionService + { + Key = key, + ExpiredKeys = new List { key } //note that we use the same key to get the code to throw + }; + }); + + Assert.AreEqual("The new Encryption Key is too similar to the Expired Key at index 0. This can cause issues when decrypting data. To fix this issue please ensure the new encryption key is not too similar to the existing Expired Keys.", exception.Message); + } + } +} \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/NServiceBus.Encryption.Rijndael.Tests.csproj b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/NServiceBus.Encryption.Rijndael.Tests.csproj new file mode 100644 index 0000000000..b0b6d41357 --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/NServiceBus.Encryption.Rijndael.Tests.csproj @@ -0,0 +1,69 @@ + + + + + Debug + AnyCPU + {9EF046BF-9F50-4768-BF1D-0310B9025BC4} + Library + Properties + NServiceBus.Encryption.Rijndael.Tests + NServiceBus.Encryption.Rijndael.Tests + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\..\..\build\nservicebus.core\NServiceBus.dll + + + ..\..\..\..\build\nservicebus.core\NServiceBus.Encryption.dll + + + ..\..\..\..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + {C1B44A57-9231-49A7-8217-739514788A98} + NServiceBus.Encryption.Rijndael.Config + + + {BBA5F232-FD46-4A6D-AC16-02FA80BCBD92} + NServiceBus.Encryption.Rijndael + + + + \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/packages.config b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/packages.config new file mode 100644 index 0000000000..0c8217846d --- /dev/null +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael.Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael/EncryptionService.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael/EncryptionService.cs index 168bd1aa9e..c6b9d5d21b 100644 --- a/src/impl/encryption/NServiceBus.Encryption.Rijndael/EncryptionService.cs +++ b/src/impl/encryption/NServiceBus.Encryption.Rijndael/EncryptionService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using Common.Logging; @@ -12,10 +13,33 @@ namespace NServiceBus.Encryption.Rijndael ///
public class EncryptionService : IEncryptionService { + byte[] key; /// /// Symmetric key used for encryption. /// - public byte[] Key { get; set; } + public byte[] Key + { + get { return key; } + set + { + key = value; + VerifyKeysAreNotTooSimilar(); + } + } + + List expiredKeys; + /// + /// Expired keys that are being phased out but still used for decryption + /// + public List ExpiredKeys + { + get { return expiredKeys; } + set + { + expiredKeys = value; + VerifyKeysAreNotTooSimilar(); + } + } string IEncryptionService.Decrypt(EncryptedValue encryptedValue) { @@ -25,13 +49,36 @@ string IEncryptionService.Decrypt(EncryptedValue encryptedValue) return encryptedValue.EncryptedBase64Value; } - var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value); + var decryptionKeys = new List { Key }; + if (ExpiredKeys != null) + { + decryptionKeys.AddRange(ExpiredKeys); + } + var cryptographicExceptions = new List(); + + foreach (var key in decryptionKeys) + { + try + { + return Decrypt(encryptedValue, key); + } + catch (CryptographicException exception) + { + cryptographicExceptions.Add(exception); + } + } + var message = string.Format("Could not decrypt message. Tried {0} keys.", decryptionKeys.Count); + throw new AggregateException(message, cryptographicExceptions); + } + + static string Decrypt(EncryptedValue encryptedValue, byte[] key) + { using (var rijndael = new RijndaelManaged()) { - rijndael.Key = Key; + var encrypted = Convert.FromBase64String(encryptedValue.EncryptedBase64Value); rijndael.IV = Convert.FromBase64String(encryptedValue.Base64Iv); rijndael.Mode = CipherMode.CBC; - + rijndael.Key = key; using (var decryptor = rijndael.CreateDecryptor()) using (var memoryStream = new MemoryStream(encrypted)) using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) @@ -71,6 +118,37 @@ EncryptedValue IEncryptionService.Encrypt(string value) } } - private static readonly ILog Logger = LogManager.GetLogger(typeof (EncryptionService)); + void VerifyKeysAreNotTooSimilar() + { + if (ExpiredKeys == null) + { + return; + } + if (Key == null) + { + return; + } + for (var index = 0; index < ExpiredKeys.Count; index++) + { + var decryption = ExpiredKeys[index]; + CryptographicException exception = null; + var encryptedValue = ((IEncryptionService)this).Encrypt("a"); + try + { + Decrypt(encryptedValue, decryption); + } + catch (CryptographicException cryptographicException) + { + exception = cryptographicException; + } + if (exception == null) + { + var message = string.Format("The new Encryption Key is too similar to the Expired Key at index {0}. This can cause issues when decrypting data. To fix this issue please ensure the new encryption key is not too similar to the existing Expired Keys.", index); + throw new Exception(message); + } + } + } + + static readonly ILog Logger = LogManager.GetLogger(typeof(EncryptionService)); } } diff --git a/src/impl/encryption/NServiceBus.Encryption.Rijndael/Properties/AssemblyInfo.cs b/src/impl/encryption/NServiceBus.Encryption.Rijndael/Properties/AssemblyInfo.cs index c464a1b99b8a74a438c5831c9c5db57d9008b311..5bf552d4056a9d8e1682778b2033344f0fd68f06 100644 GIT binary patch delta 230 zcmcb`eTH|!o{4z^8~-%0Og3YdnmmiuX0jEtn6f8B9zzL3Dnk*FPGrboC}s#_$OMv^ z3`syXzBGb<8nz6Jzy-zt*t9UC delta 45 zcmX@Zdy9L*9{ym4REA`RQidXiOokGM%89;)8_zVbFmp0+PW&i6IgQnZg_nVg0RTlt B42b{$ diff --git a/src/impl/encryption/encryption.sln b/src/impl/encryption/encryption.sln index f0ab64f8bd..4de2d12851 100644 --- a/src/impl/encryption/encryption.sln +++ b/src/impl/encryption/encryption.sln @@ -1,10 +1,14 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30723.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Encryption.Rijndael", "NServiceBus.Encryption.Rijndael\NServiceBus.Encryption.Rijndael.csproj", "{BBA5F232-FD46-4A6D-AC16-02FA80BCBD92}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Encryption.Rijndael.Config", "NServiceBus.Encryption.Rijndael.Config\NServiceBus.Encryption.Rijndael.Config.csproj", "{C1B44A57-9231-49A7-8217-739514788A98}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NServiceBus.Encryption.Rijndael.Tests", "NServiceBus.Encryption.Rijndael.Tests\NServiceBus.Encryption.Rijndael.Tests.csproj", "{9EF046BF-9F50-4768-BF1D-0310B9025BC4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -19,6 +23,10 @@ Global {C1B44A57-9231-49A7-8217-739514788A98}.Debug|Any CPU.Build.0 = Debug|Any CPU {C1B44A57-9231-49A7-8217-739514788A98}.Release|Any CPU.ActiveCfg = Release|Any CPU {C1B44A57-9231-49A7-8217-739514788A98}.Release|Any CPU.Build.0 = Release|Any CPU + {9EF046BF-9F50-4768-BF1D-0310B9025BC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9EF046BF-9F50-4768-BF1D-0310B9025BC4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9EF046BF-9F50-4768-BF1D-0310B9025BC4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9EF046BF-9F50-4768-BF1D-0310B9025BC4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/impl/encryption/nuget.config b/src/impl/encryption/nuget.config new file mode 100644 index 0000000000..cd17f414bd --- /dev/null +++ b/src/impl/encryption/nuget.config @@ -0,0 +1,4 @@ + + + ../../packages + \ No newline at end of file