mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge
--HG-- branch : 1.x
This commit is contained in:
@@ -99,8 +99,11 @@ namespace Orchard.Azure.Environment.Configuration {
|
|||||||
case "EncryptionKey":
|
case "EncryptionKey":
|
||||||
shellSettings.EncryptionKey = value;
|
shellSettings.EncryptionKey = value;
|
||||||
break;
|
break;
|
||||||
case "EncryptionIV":
|
case "HashAlgorithm":
|
||||||
shellSettings.EncryptionIV = value;
|
shellSettings.HashAlgorithm = value;
|
||||||
|
break;
|
||||||
|
case "HashKey":
|
||||||
|
shellSettings.HashKey = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,7 +116,7 @@ namespace Orchard.Azure.Environment.Configuration {
|
|||||||
if (settings == null)
|
if (settings == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\nEncryptionAlgorithm: {7}\r\nEncryptionKey: {8}\r\nEncryptionIV: {9}\r\n",
|
return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\nEncryptionAlgorithm: {7}\r\nEncryptionKey: {8}\r\nHashAlgorithm: {9}\r\nHashKey: {10}\r\n",
|
||||||
settings.Name,
|
settings.Name,
|
||||||
settings.DataProvider,
|
settings.DataProvider,
|
||||||
settings.DataConnectionString ?? EmptyValue,
|
settings.DataConnectionString ?? EmptyValue,
|
||||||
@@ -123,7 +126,8 @@ namespace Orchard.Azure.Environment.Configuration {
|
|||||||
settings.State != null ? settings.State.ToString() : String.Empty,
|
settings.State != null ? settings.State.ToString() : String.Empty,
|
||||||
settings.EncryptionAlgorithm ?? EmptyValue,
|
settings.EncryptionAlgorithm ?? EmptyValue,
|
||||||
settings.EncryptionKey ?? EmptyValue,
|
settings.EncryptionKey ?? EmptyValue,
|
||||||
settings.EncryptionIV ?? EmptyValue
|
settings.HashAlgorithm ?? EmptyValue,
|
||||||
|
settings.HashKey ?? EmptyValue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,22 +5,20 @@ using Orchard.Utility.Extensions;
|
|||||||
namespace Orchard.Tests.Modules.Users {
|
namespace Orchard.Tests.Modules.Users {
|
||||||
public class ShellSettingsUtility {
|
public class ShellSettingsUtility {
|
||||||
public static ShellSettings CreateEncryptionEnabled() {
|
public static ShellSettings CreateEncryptionEnabled() {
|
||||||
// generate random keys for encryption
|
|
||||||
var key = new byte[32];
|
const string encryptionAlgorithm = "AES";
|
||||||
var iv = new byte[16];
|
const string hashAlgorithm = "HMACSHA256";
|
||||||
using ( var random = new RNGCryptoServiceProvider() ) {
|
|
||||||
random.GetBytes(key);
|
|
||||||
random.GetBytes(iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ShellSettings {
|
return new ShellSettings {
|
||||||
Name = "Alpha",
|
Name = "Alpha",
|
||||||
RequestUrlHost = "wiki.example.com",
|
RequestUrlHost = "wiki.example.com",
|
||||||
RequestUrlPrefix = "~/foo",
|
RequestUrlPrefix = "~/foo",
|
||||||
EncryptionAlgorithm = "AES",
|
EncryptionAlgorithm = encryptionAlgorithm,
|
||||||
EncryptionKey = key.ToHexString(),
|
EncryptionKey = SymmetricAlgorithm.Create(encryptionAlgorithm).Key.ToHexString(),
|
||||||
EncryptionIV = iv.ToHexString()
|
HashAlgorithm = hashAlgorithm,
|
||||||
|
HashKey = HMAC.Create(hashAlgorithm).Key.ToHexString()
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -70,7 +70,7 @@ namespace Orchard.Tests.Environment.Configuration {
|
|||||||
[Test]
|
[Test]
|
||||||
public void EncryptionSettingsAreStoredAndReadable() {
|
public void EncryptionSettingsAreStoredAndReadable() {
|
||||||
IShellSettingsManager loader = new ShellSettingsManager(_appDataFolder, new Mock<IShellSettingsManagerEventHandler>().Object);
|
IShellSettingsManager loader = new ShellSettingsManager(_appDataFolder, new Mock<IShellSettingsManagerEventHandler>().Object);
|
||||||
var foo = new ShellSettings { Name = "Foo", DataProvider = "Bar", DataConnectionString = "Quux", EncryptionAlgorithm = "AES", EncryptionKey = "ABCDEFG", EncryptionIV= "HIJKL" };
|
var foo = new ShellSettings { Name = "Foo", DataProvider = "Bar", DataConnectionString = "Quux", EncryptionAlgorithm = "AES", EncryptionKey = "ABCDEFG", HashAlgorithm = "HMACSHA256", HashKey = "HIJKLMN" };
|
||||||
loader.SaveSettings(foo);
|
loader.SaveSettings(foo);
|
||||||
Assert.That(loader.LoadSettings().Count(), Is.EqualTo(1));
|
Assert.That(loader.LoadSettings().Count(), Is.EqualTo(1));
|
||||||
|
|
||||||
@@ -78,7 +78,8 @@ namespace Orchard.Tests.Environment.Configuration {
|
|||||||
|
|
||||||
Assert.That(settings.EncryptionAlgorithm, Is.EqualTo("AES"));
|
Assert.That(settings.EncryptionAlgorithm, Is.EqualTo("AES"));
|
||||||
Assert.That(settings.EncryptionKey, Is.EqualTo("ABCDEFG"));
|
Assert.That(settings.EncryptionKey, Is.EqualTo("ABCDEFG"));
|
||||||
Assert.That(settings.EncryptionIV, Is.EqualTo("HIJKL"));
|
Assert.That(settings.HashAlgorithm, Is.EqualTo("HMACSHA256"));
|
||||||
|
Assert.That(settings.HashKey, Is.EqualTo("HIJKLMN"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Security.Cryptography;
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@@ -10,36 +11,33 @@ using Orchard.Utility.Extensions;
|
|||||||
namespace Orchard.Tests.Security {
|
namespace Orchard.Tests.Security {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DefaultEncryptionServiceTests {
|
public class DefaultEncryptionServiceTests {
|
||||||
private IContainer container;
|
private IContainer _container;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Init() {
|
public void Init() {
|
||||||
|
|
||||||
var key = new byte[32];
|
const string encryptionAlgorithm = "AES";
|
||||||
var iv = new byte[16];
|
const string hashAlgorithm = "HMACSHA256";
|
||||||
using ( var random = new RNGCryptoServiceProvider() ) {
|
|
||||||
random.GetBytes(key);
|
|
||||||
random.GetBytes(iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
var shellSettings = new ShellSettings {
|
var shellSettings = new ShellSettings {
|
||||||
Name = "Foo",
|
Name = "Foo",
|
||||||
DataProvider = "Bar",
|
DataProvider = "Bar",
|
||||||
DataConnectionString = "Quux",
|
DataConnectionString = "Quux",
|
||||||
EncryptionAlgorithm = "AES",
|
EncryptionAlgorithm = encryptionAlgorithm,
|
||||||
EncryptionKey = key.ToHexString(),
|
EncryptionKey = SymmetricAlgorithm.Create(encryptionAlgorithm).Key.ToHexString(),
|
||||||
EncryptionIV = iv.ToHexString()
|
HashAlgorithm = hashAlgorithm,
|
||||||
|
HashKey = HMAC.Create(hashAlgorithm).Key.ToHexString()
|
||||||
};
|
};
|
||||||
|
|
||||||
var builder = new ContainerBuilder();
|
var builder = new ContainerBuilder();
|
||||||
builder.RegisterInstance(shellSettings);
|
builder.RegisterInstance(shellSettings);
|
||||||
builder.RegisterType<DefaultEncryptionService>().As<IEncryptionService>();
|
builder.RegisterType<DefaultEncryptionService>().As<IEncryptionService>();
|
||||||
container = builder.Build();
|
_container = builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CanEncodeAndDecodeData() {
|
public void CanEncodeAndDecodeData() {
|
||||||
var encryptionService = container.Resolve<IEncryptionService>();
|
var encryptionService = _container.Resolve<IEncryptionService>();
|
||||||
|
|
||||||
var secretData = Encoding.Unicode.GetBytes("this is secret data");
|
var secretData = Encoding.Unicode.GetBytes("this is secret data");
|
||||||
var encrypted = encryptionService.Encode(secretData);
|
var encrypted = encryptionService.Encode(secretData);
|
||||||
@@ -49,5 +47,42 @@ namespace Orchard.Tests.Security {
|
|||||||
Assert.That(decrypted, Is.EqualTo(secretData));
|
Assert.That(decrypted, Is.EqualTo(secretData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldDetectTamperedData() {
|
||||||
|
var encryptionService = _container.Resolve<IEncryptionService>();
|
||||||
|
|
||||||
|
var secretData = Encoding.Unicode.GetBytes("this is secret data");
|
||||||
|
var encrypted = encryptionService.Encode(secretData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// tamper the data
|
||||||
|
encrypted[encrypted.Length - 1] ^= 66;
|
||||||
|
var decrypted = encryptionService.Decode(encrypted);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SuccessiveEncodeCallsShouldNotReturnTheSameData() {
|
||||||
|
var encryptionService = _container.Resolve<IEncryptionService>();
|
||||||
|
|
||||||
|
var secretData = Encoding.Unicode.GetBytes("this is secret data");
|
||||||
|
byte[] previousEncrypted = null;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
var encrypted = encryptionService.Encode(secretData);
|
||||||
|
var decrypted = encryptionService.Decode(encrypted);
|
||||||
|
|
||||||
|
Assert.That(encrypted, Is.Not.EqualTo(decrypted));
|
||||||
|
Assert.That(decrypted, Is.EqualTo(secretData));
|
||||||
|
|
||||||
|
if(previousEncrypted != null) {
|
||||||
|
Assert.That(encrypted, Is.Not.EqualTo(previousEncrypted));
|
||||||
|
}
|
||||||
|
previousEncrypted = encrypted;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -126,17 +126,14 @@ namespace Orchard.Setup.Services {
|
|||||||
|
|
||||||
#region Encryption Settings
|
#region Encryption Settings
|
||||||
|
|
||||||
// generate random keys for encryption
|
|
||||||
var key = new byte[32];
|
|
||||||
var iv = new byte[16];
|
|
||||||
using ( var random = new RNGCryptoServiceProvider() ) {
|
|
||||||
random.GetBytes(key);
|
|
||||||
random.GetBytes(iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
shellSettings.EncryptionAlgorithm = "AES";
|
shellSettings.EncryptionAlgorithm = "AES";
|
||||||
shellSettings.EncryptionKey = key.ToHexString();
|
// randomly generated key
|
||||||
shellSettings.EncryptionIV = iv.ToHexString();
|
shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString();
|
||||||
|
|
||||||
|
shellSettings.HashAlgorithm = "HMACSHA256";
|
||||||
|
// randomly generated key
|
||||||
|
shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var shellDescriptor = new ShellDescriptor {
|
var shellDescriptor = new ShellDescriptor {
|
||||||
|
@@ -104,6 +104,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Orchard.Scripting", "Orchar
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{3E10BF6D-ADA5-417D-B36C-EBB0660B475E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{3E10BF6D-ADA5-417D-B36C-EBB0660B475E}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contrib.Taxonomies", "Orchard.Web\Modules\Contrib.Taxonomies\Contrib.Taxonomies.csproj", "{E649EA64-D213-461B-87F7-D67035801443}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contrib.Voting", "Orchard.Web\Modules\Contrib.Voting\Contrib.Voting.csproj", "{4DA5F35F-E62C-4B49-B5A8-379503257B3A}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
CodeCoverage|Any CPU = CodeCoverage|Any CPU
|
CodeCoverage|Any CPU = CodeCoverage|Any CPU
|
||||||
@@ -113,6 +117,10 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4DA5F35F-E62C-4B49-B5A8-379503257B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4DA5F35F-E62C-4B49-B5A8-379503257B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4DA5F35F-E62C-4B49-B5A8-379503257B3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4DA5F35F-E62C-4B49-B5A8-379503257B3A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{50B779EA-EC00-4699-84C0-03B395C365D2}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
|
{50B779EA-EC00-4699-84C0-03B395C365D2}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{50B779EA-EC00-4699-84C0-03B395C365D2}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
|
{50B779EA-EC00-4699-84C0-03B395C365D2}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
|
||||||
{50B779EA-EC00-4699-84C0-03B395C365D2}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
|
{50B779EA-EC00-4699-84C0-03B395C365D2}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -550,6 +558,16 @@ Global
|
|||||||
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.FxCop|Any CPU.Build.0 = Release|Any CPU
|
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.FxCop|Any CPU.Build.0 = Release|Any CPU
|
||||||
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.Release|Any CPU.Build.0 = Release|Any CPU
|
{99002B65-86F7-415E-BF4A-381AA8AB9CCC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.CodeCoverage|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.CodeCoverage|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Coverage|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Coverage|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.FxCop|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.FxCop|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -585,6 +603,7 @@ Global
|
|||||||
{FBC8B571-ED50-49D8-8D9D-64AB7454A0D6} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
{FBC8B571-ED50-49D8-8D9D-64AB7454A0D6} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||||
{2AD6973D-C7BB-416E-89FE-EEE34664E05F} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
{2AD6973D-C7BB-416E-89FE-EEE34664E05F} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||||
{99002B65-86F7-415E-BF4A-381AA8AB9CCC} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
{99002B65-86F7-415E-BF4A-381AA8AB9CCC} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||||
|
{E649EA64-D213-461B-87F7-D67035801443} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||||
{ABC826D4-2FA1-4F2F-87DE-E6095F653810} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
{ABC826D4-2FA1-4F2F-87DE-E6095F653810} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
||||||
{F112851D-B023-4746-B6B1-8D2E5AD8F7AA} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
{F112851D-B023-4746-B6B1-8D2E5AD8F7AA} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
||||||
{6CB3EB30-F725-45C0-9742-42599BA8E8D2} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
{6CB3EB30-F725-45C0-9742-42599BA8E8D2} = {74E681ED-FECC-4034-B9BD-01B0BB1BDECA}
|
||||||
@@ -593,8 +612,9 @@ Global
|
|||||||
{4AB4B5B6-277E-4FF6-B69B-7AE9E16D2A56} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
{4AB4B5B6-277E-4FF6-B69B-7AE9E16D2A56} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||||
{33B1BC8D-E292-4972-A363-22056B207156} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
{33B1BC8D-E292-4972-A363-22056B207156} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||||
{0DFA2E10-96C8-4E05-BC10-B710B97ECCDE} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
{0DFA2E10-96C8-4E05-BC10-B710B97ECCDE} = {383DBA32-4A3E-48D1-AAC3-75377A694452}
|
||||||
{CB70A642-8CEC-4DDE-8C9F-AD08900EC98D} = {74492CBC-7201-417E-BC29-28B4C25A58B0}
|
|
||||||
{7354DF37-934B-46CF-A13C-455D5F5F5413} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
|
|
||||||
{94E694A2-D140-468D-A277-C5FCE1D13E9B} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
|
{94E694A2-D140-468D-A277-C5FCE1D13E9B} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
|
||||||
|
{7354DF37-934B-46CF-A13C-455D5F5F5413} = {3E10BF6D-ADA5-417D-B36C-EBB0660B475E}
|
||||||
|
{CB70A642-8CEC-4DDE-8C9F-AD08900EC98D} = {74492CBC-7201-417E-BC29-28B4C25A58B0}
|
||||||
|
{4DA5F35F-E62C-4B49-B5A8-379503257B3A} = {E9C9F120-07BA-4DFB-B9C3-3AFB9D44C9D5}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@@ -18,7 +18,8 @@
|
|||||||
RequestUrlPrefix = settings.RequestUrlPrefix;
|
RequestUrlPrefix = settings.RequestUrlPrefix;
|
||||||
EncryptionAlgorithm = settings.EncryptionAlgorithm;
|
EncryptionAlgorithm = settings.EncryptionAlgorithm;
|
||||||
EncryptionKey = settings.EncryptionKey;
|
EncryptionKey = settings.EncryptionKey;
|
||||||
EncryptionIV = settings.EncryptionIV;
|
HashAlgorithm = settings.HashAlgorithm;
|
||||||
|
HashKey = settings.HashKey;
|
||||||
State = settings.State;
|
State = settings.State;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +34,9 @@
|
|||||||
|
|
||||||
public string EncryptionAlgorithm { get; set; }
|
public string EncryptionAlgorithm { get; set; }
|
||||||
public string EncryptionKey { get; set; }
|
public string EncryptionKey { get; set; }
|
||||||
public string EncryptionIV { get; set; }
|
|
||||||
|
public string HashAlgorithm { get; set; }
|
||||||
|
public string HashKey { get; set; }
|
||||||
|
|
||||||
public TenantState State { get; set; }
|
public TenantState State { get; set; }
|
||||||
}
|
}
|
||||||
|
@@ -49,15 +49,13 @@ namespace Orchard.Environment.Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ShellSettings ParseSettings(string text)
|
static ShellSettings ParseSettings(string text) {
|
||||||
{
|
|
||||||
var shellSettings = new ShellSettings();
|
var shellSettings = new ShellSettings();
|
||||||
if (String.IsNullOrEmpty(text))
|
if (String.IsNullOrEmpty(text))
|
||||||
return shellSettings;
|
return shellSettings;
|
||||||
|
|
||||||
var settings = text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
var settings = text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (var setting in settings)
|
foreach (var setting in settings) {
|
||||||
{
|
|
||||||
var separatorIndex = setting.IndexOf(Separator);
|
var separatorIndex = setting.IndexOf(Separator);
|
||||||
if (separatorIndex == -1)
|
if (separatorIndex == -1)
|
||||||
{
|
{
|
||||||
@@ -97,8 +95,11 @@ namespace Orchard.Environment.Configuration {
|
|||||||
case "EncryptionKey":
|
case "EncryptionKey":
|
||||||
shellSettings.EncryptionKey = value;
|
shellSettings.EncryptionKey = value;
|
||||||
break;
|
break;
|
||||||
case "EncryptionIV":
|
case "HashAlgorithm":
|
||||||
shellSettings.EncryptionIV = value;
|
shellSettings.HashAlgorithm = value;
|
||||||
|
break;
|
||||||
|
case "HashKey":
|
||||||
|
shellSettings.HashKey = value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,12 +108,11 @@ namespace Orchard.Environment.Configuration {
|
|||||||
return shellSettings;
|
return shellSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string ComposeSettings(ShellSettings settings)
|
static string ComposeSettings(ShellSettings settings) {
|
||||||
{
|
|
||||||
if (settings == null)
|
if (settings == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\nEncryptionAlgorithm: {7}\r\nEncryptionKey: {8}\r\nEncryptionIV: {9}\r\n",
|
return string.Format("Name: {0}\r\nDataProvider: {1}\r\nDataConnectionString: {2}\r\nDataPrefix: {3}\r\nRequestUrlHost: {4}\r\nRequestUrlPrefix: {5}\r\nState: {6}\r\nEncryptionAlgorithm: {7}\r\nEncryptionKey: {8}\r\nHashAlgorithm: {9}\r\nHashKey: {10}\r\n",
|
||||||
settings.Name,
|
settings.Name,
|
||||||
settings.DataProvider,
|
settings.DataProvider,
|
||||||
settings.DataConnectionString ?? EmptyValue,
|
settings.DataConnectionString ?? EmptyValue,
|
||||||
@@ -122,7 +122,8 @@ namespace Orchard.Environment.Configuration {
|
|||||||
settings.State != null ? settings.State.ToString() : String.Empty,
|
settings.State != null ? settings.State.ToString() : String.Empty,
|
||||||
settings.EncryptionAlgorithm ?? EmptyValue,
|
settings.EncryptionAlgorithm ?? EmptyValue,
|
||||||
settings.EncryptionKey ?? EmptyValue,
|
settings.EncryptionKey ?? EmptyValue,
|
||||||
settings.EncryptionIV ?? EmptyValue
|
settings.HashAlgorithm ?? EmptyValue,
|
||||||
|
settings.HashKey ?? EmptyValue
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,59 +3,91 @@ using System.Linq;
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using Orchard.Environment.Configuration;
|
using Orchard.Environment.Configuration;
|
||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Orchard.Security.Providers {
|
namespace Orchard.Security.Providers {
|
||||||
public class DefaultEncryptionService : IEncryptionService {
|
public class DefaultEncryptionService : IEncryptionService {
|
||||||
private readonly ShellSettings _shellSettings;
|
private readonly ShellSettings _shellSettings;
|
||||||
private const int SaltSize = 16;
|
|
||||||
|
|
||||||
public DefaultEncryptionService(ShellSettings shellSettings ) {
|
public DefaultEncryptionService(ShellSettings shellSettings ) {
|
||||||
_shellSettings = shellSettings;
|
_shellSettings = shellSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Decode(byte[] encodedData) {
|
public byte[] Decode(byte[] encodedData) {
|
||||||
using ( var ms = new MemoryStream() ) {
|
// extract parts of the encoded data
|
||||||
using (var algorithm = CreateAlgorithm()) {
|
using (var symmetricAlgorithm = CreateSymmetricAlgorithm()) {
|
||||||
using ( var cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write) ) {
|
using (var hashAlgorithm = CreateHashAlgorithm()) {
|
||||||
cs.Write(encodedData, 0, encodedData.Length);
|
var iv = new byte[symmetricAlgorithm.BlockSize / 8];
|
||||||
cs.FlushFinalBlock();
|
var signature = new byte[hashAlgorithm.HashSize / 8];
|
||||||
|
var data = new byte[encodedData.Length - iv.Length - signature.Length];
|
||||||
|
|
||||||
|
Array.Copy(encodedData, 0, iv, 0, iv.Length);
|
||||||
|
Array.Copy(encodedData, iv.Length, data, 0, data.Length);
|
||||||
|
Array.Copy(encodedData, iv.Length + data.Length, signature, 0, signature.Length);
|
||||||
|
|
||||||
|
// validate the signature
|
||||||
|
var mac = hashAlgorithm.ComputeHash(iv.Concat(data).ToArray());
|
||||||
|
|
||||||
|
if (!mac.SequenceEqual(signature)) {
|
||||||
|
// message has been tampered
|
||||||
|
throw new ArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the salt part
|
symmetricAlgorithm.IV = iv;
|
||||||
return ms.ToArray().Skip(SaltSize).ToArray();
|
|
||||||
|
using (var ms = new MemoryStream()) {
|
||||||
|
using (var cs = new CryptoStream(ms, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Write)) {
|
||||||
|
cs.Write(data, 0, data.Length);
|
||||||
|
cs.FlushFinalBlock();
|
||||||
|
}
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Encode(byte[] data) {
|
public byte[] Encode(byte[] data) {
|
||||||
var salt = new byte[SaltSize];
|
// cipherText ::= IV || ENC(EncryptionKey, IV, plainText) || HMAC(SigningKey, IV || ENC(EncryptionKey, IV, plainText))
|
||||||
|
|
||||||
|
byte[] encryptedData;
|
||||||
|
byte[] iv;
|
||||||
|
|
||||||
// generate a random salt to happend to encoded data
|
|
||||||
using ( var random = new RNGCryptoServiceProvider() ) {
|
|
||||||
random.GetBytes(salt);
|
|
||||||
}
|
|
||||||
using ( var ms = new MemoryStream() ) {
|
using ( var ms = new MemoryStream() ) {
|
||||||
using (var algorithm = CreateAlgorithm()) {
|
using (var symmetricAlgorithm = CreateSymmetricAlgorithm()) {
|
||||||
using ( var cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write) ) {
|
// generate a new IV each time the Encode is called
|
||||||
// append the salt to the data and encrypt
|
symmetricAlgorithm.GenerateIV();
|
||||||
var salted = salt.Concat(data).ToArray();
|
iv = symmetricAlgorithm.IV;
|
||||||
cs.Write(salted, 0, salted.Length);
|
|
||||||
|
using (var cs = new CryptoStream(ms, symmetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write)) {
|
||||||
|
cs.Write(data, 0, data.Length);
|
||||||
cs.FlushFinalBlock();
|
cs.FlushFinalBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ms.ToArray();
|
encryptedData = ms.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] signedData;
|
||||||
|
|
||||||
|
// signing IV || encrypted data
|
||||||
|
using (var hashAlgorithm = CreateHashAlgorithm()) {
|
||||||
|
signedData = hashAlgorithm.ComputeHash(iv.Concat(encryptedData).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return iv.Concat(encryptedData).Concat(signedData).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SymmetricAlgorithm CreateAlgorithm() {
|
private SymmetricAlgorithm CreateSymmetricAlgorithm() {
|
||||||
var encryptionAlgorithm = SymmetricAlgorithm.Create(_shellSettings.EncryptionAlgorithm);
|
var algorithm = SymmetricAlgorithm.Create(_shellSettings.EncryptionAlgorithm);
|
||||||
|
algorithm.Key = _shellSettings.EncryptionKey.ToByteArray();
|
||||||
encryptionAlgorithm.Key = _shellSettings.EncryptionKey.ToByteArray();
|
return algorithm;
|
||||||
encryptionAlgorithm.IV = _shellSettings.EncryptionIV.ToByteArray();
|
|
||||||
|
|
||||||
return encryptionAlgorithm;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HMAC CreateHashAlgorithm() {
|
||||||
|
var algorithm = HMAC.Create(_shellSettings.HashAlgorithm);
|
||||||
|
algorithm.Key = _shellSettings.HashKey.ToByteArray();
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user