created SecureSerializer abstraction

This commit is contained in:
David Sparer
2017-04-12 12:39:38 -06:00
parent d63177f3c7
commit 3291c24c8c
13 changed files with 44 additions and 45 deletions

View File

@@ -31,7 +31,7 @@ namespace mRemoteNG.Specs.Utilities
new CredentialRepositoryConfig(),
new CredentialRecordSaver(
dataProvider,
new StaticSerializerKeyProviderDecorator<IEnumerable<ICredentialRecord>, string>(encryptor, encryptor) { Key = EncryptionKey }
encryptor
), new CredentialRecordLoader(
dataProvider,
decryptor

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.CredentialSerializer;
@@ -17,6 +18,7 @@ namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
private const BlockCipherEngines CipherEngine = BlockCipherEngines.Twofish;
private const BlockCipherModes CipherMode = BlockCipherModes.EAX;
private const int KdfIterations = 2000;
private SecureString _key = "myKey1".ConvertToSecureString();
[SetUp]
public void Setup()
@@ -30,22 +32,14 @@ namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
[Test]
public void CantPassNullCredentialList()
{
Assert.Throws<ArgumentNullException>(() => _sut.Serialize(null));
}
[Test]
public void CanSetEncryptionKey()
{
const string newKey = "blah";
_sut.Key = newKey.ConvertToSecureString();
Assert.That(_sut.Key.ConvertToUnsecureString(), Is.EqualTo(newKey));
Assert.Throws<ArgumentNullException>(() => _sut.Serialize(null, new SecureString()));
}
[Test]
public void EncryptsPasswordAttributesInXml()
{
var credList = Substitute.For<IEnumerable<ICredentialRecord>>();
var output = _sut.Serialize(credList);
var output = _sut.Serialize(credList, _key);
var outputAsXdoc = XDocument.Parse(output);
var firstElementPassword = outputAsXdoc.Root?.Descendants().First().FirstAttribute.Value;
Assert.That(firstElementPassword, Is.EqualTo("encrypted"));
@@ -58,7 +52,7 @@ namespace mRemoteNGTests.Config.Serializers.CredentialSerializers
public void SetsRootNodeEncryptionAttributes(string attributeName, object expectedValue)
{
var credList = Substitute.For<IEnumerable<ICredentialRecord>>();
var output = _sut.Serialize(credList);
var output = _sut.Serialize(credList, _key);
var outputAsXdoc = XDocument.Parse(output);
var authField = outputAsXdoc.Root?.Attribute(attributeName)?.Value;
Assert.That(authField, Is.EqualTo(expectedValue.ToString()));

View File

@@ -14,7 +14,7 @@ namespace mRemoteNGTests.IntegrationTests
{
public class XmlCredentialSerializerLifeCycleTests
{
private ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private ISecureSerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
private readonly Guid _id = Guid.NewGuid();
private const string Title = "mycredential1";
@@ -28,7 +28,7 @@ namespace mRemoteNGTests.IntegrationTests
var keyProvider = Substitute.For<IKeyProvider>();
keyProvider.GetKey().Returns(_key);
var cryptoProvider = new CryptoProviderFactory(BlockCipherEngines.AES, BlockCipherModes.CCM).Build();
_serializer = new XmlCredentialPasswordEncryptorDecorator(cryptoProvider, new XmlCredentialRecordSerializer()) { Key = _key };
_serializer = new XmlCredentialPasswordEncryptorDecorator(cryptoProvider, new XmlCredentialRecordSerializer());
_deserializer = new XmlCredentialPasswordDecryptorDecorator(new XmlCredentialRecordDeserializer());
}
@@ -36,7 +36,7 @@ namespace mRemoteNGTests.IntegrationTests
public void WeCanSerializeAndDeserializeXmlCredentials()
{
var credentials = new[] { new CredentialRecord(), new CredentialRecord() };
var serializedCredentials = _serializer.Serialize(credentials);
var serializedCredentials = _serializer.Serialize(credentials, _key);
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials, _key);
Assert.That(deserializedCredentials.Count(), Is.EqualTo(2));
}
@@ -82,7 +82,7 @@ namespace mRemoteNGTests.IntegrationTests
{
new CredentialRecord(_id) {Title = Title, Username = Username, Domain = Domain, Password = _key}
};
var serializedCredentials = _serializer.Serialize(credentials);
var serializedCredentials = _serializer.Serialize(credentials, _key);
var deserializedCredentials = _deserializer.Deserialize(serializedCredentials, _key);
return deserializedCredentials.First();
}

View File

@@ -22,7 +22,7 @@ namespace mRemoteNG.App.Initialization
{
private readonly string _credentialRepoListPath = Path.Combine(SettingsFileInfo.SettingsPath, "credentialRepositories.xml");
private readonly ICredentialRepositoryList _credentialRepositoryList;
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _credRepoSerializer;
private readonly ISecureSerializer<IEnumerable<ICredentialRecord>, string> _credRepoSerializer;
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _credRepoDeserializer;
private readonly string _credentialFilePath;
@@ -79,7 +79,7 @@ namespace mRemoteNG.App.Initialization
var xmlRepoFactory = new XmlCredentialRepositoryFactory(_credRepoSerializer, _credRepoDeserializer);
var newCredentialRepository = xmlRepoFactory.Build(
new CredentialRepositoryConfig { Source = _credentialFilePath }
new CredentialRepositoryConfig { Source = _credentialFilePath, Title = "Converted Credentials", TypeName = "Xml"}
);
foreach (var credential in harvestedCredentials)
@@ -107,7 +107,11 @@ namespace mRemoteNG.App.Initialization
Runtime.CredentialProviderCatalog.AddProvider(repository);
}
Runtime.CredentialProviderCatalog.RepositoriesUpdated += (sender, args) => credRepoListSaver.Save(Runtime.CredentialProviderCatalog.CredentialProviders);
Runtime.CredentialProviderCatalog.CredentialsUpdated += (sender, args) => (sender as ICredentialRepository)?.SaveCredentials();
Runtime.CredentialProviderCatalog.CredentialsUpdated += (sender, args) =>
{
var repo = (sender as ICredentialRepository);
repo?.SaveCredentials(repo.Config.Key);
};
}
private void LoadDefaultConnectionCredentials()

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Security;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Credential;
@@ -10,9 +11,9 @@ namespace mRemoteNG.Config
public class CredentialRecordSaver
{
private readonly IDataProvider<string> _dataProvider;
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private readonly ISecureSerializer<IEnumerable<ICredentialRecord>, string> _serializer;
public CredentialRecordSaver(IDataProvider<string> dataProvider, ISerializer<IEnumerable<ICredentialRecord>, string> serializer)
public CredentialRecordSaver(IDataProvider<string> dataProvider, ISecureSerializer<IEnumerable<ICredentialRecord>, string> serializer)
{
if (dataProvider == null)
throw new ArgumentNullException(nameof(dataProvider));
@@ -23,9 +24,9 @@ namespace mRemoteNG.Config
_serializer = serializer;
}
public void Save(IEnumerable<ICredentialRecord> credentialRecords)
public void Save(IEnumerable<ICredentialRecord> credentialRecords, SecureString key)
{
var serializedCredentials = _serializer.Serialize(credentialRecords);
var serializedCredentials = _serializer.Serialize(credentialRecords, key);
_dataProvider.Save(serializedCredentials);
}
}

View File

@@ -9,10 +9,10 @@ namespace mRemoteNG.Config.Serializers.CredentialProviderSerializer
{
public class CredentialRepositoryListDeserializer
{
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private readonly ISecureSerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
public CredentialRepositoryListDeserializer(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
public CredentialRepositoryListDeserializer(ISecureSerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
{
if (serializer == null)
throw new ArgumentNullException(nameof(serializer));

View File

@@ -7,21 +7,10 @@ using mRemoteNG.Security;
namespace mRemoteNG.Config.Serializers.CredentialSerializer
{
public class XmlCredentialPasswordEncryptorDecorator : ISerializer<IEnumerable<ICredentialRecord>, string>, IHasKey
public class XmlCredentialPasswordEncryptorDecorator : ISecureSerializer<IEnumerable<ICredentialRecord>, string>
{
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _baseSerializer;
private readonly ICryptographyProvider _cryptographyProvider;
private SecureString _encryptionKey = new SecureString();
public SecureString Key
{
get { return _encryptionKey; }
set
{
if (value == null) return;
_encryptionKey = value;
}
}
public XmlCredentialPasswordEncryptorDecorator(ICryptographyProvider cryptographyProvider, ISerializer<IEnumerable<ICredentialRecord>, string> baseSerializer)
{
@@ -35,13 +24,13 @@ namespace mRemoteNG.Config.Serializers.CredentialSerializer
}
public string Serialize(IEnumerable<ICredentialRecord> credentialRecords)
public string Serialize(IEnumerable<ICredentialRecord> credentialRecords, SecureString key)
{
if (credentialRecords == null)
throw new ArgumentNullException(nameof(credentialRecords));
var baseReturn = _baseSerializer.Serialize(credentialRecords);
var encryptedReturn = EncryptPasswordAttributes(baseReturn, _encryptionKey);
var encryptedReturn = EncryptPasswordAttributes(baseReturn, key);
return encryptedReturn;
}

View File

@@ -0,0 +1,9 @@
using System.Security;
namespace mRemoteNG.Config.Serializers
{
public interface ISecureSerializer<in TIn, out TOut>
{
TOut Serialize(TIn model, SecureString key);
}
}

View File

@@ -13,7 +13,7 @@ namespace mRemoteNG.Credential
IList<ICredentialRecord> CredentialRecords { get; }
bool IsLoaded { get; }
void LoadCredentials(SecureString key);
void SaveCredentials();
void SaveCredentials(SecureString key);
void UnloadCredentials();
event EventHandler RepositoryConfigUpdated;
event EventHandler<CollectionUpdatedEventArgs<ICredentialRecord>> CredentialsUpdated;

View File

@@ -57,10 +57,10 @@ namespace mRemoteNG.Credential.Repositories
CredentialRecords.Clear();
}
public void SaveCredentials()
public void SaveCredentials(SecureString key)
{
if (!IsLoaded) return;
_credentialRecordSaver.Save(CredentialRecords);
//if (!IsLoaded) return;
_credentialRecordSaver.Save(CredentialRecords, key);
}
public event EventHandler RepositoryConfigUpdated;

View File

@@ -9,10 +9,10 @@ namespace mRemoteNG.Credential.Repositories
{
public class XmlCredentialRepositoryFactory
{
private readonly ISerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private readonly ISecureSerializer<IEnumerable<ICredentialRecord>, string> _serializer;
private readonly ISecureDeserializer<string, IEnumerable<ICredentialRecord>> _deserializer;
public XmlCredentialRepositoryFactory(ISerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
public XmlCredentialRepositoryFactory(ISecureSerializer<IEnumerable<ICredentialRecord>, string> serializer, ISecureDeserializer<string, IEnumerable<ICredentialRecord>> deserializer)
{
if (serializer == null)
throw new ArgumentNullException(nameof(serializer));

View File

@@ -73,6 +73,7 @@ namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPa
new CredentialRecordLoader(credRepoDataProvider, credRepoDeserializer)
);
_repositoryList.AddProvider(newCredentialRepository);
newCredentialRepository.SaveCredentials(_repositoryConfig.Key);
}
RaiseNextPageEvent();
}

View File

@@ -146,6 +146,7 @@
<Compile Include="Config\Serializers\CredentialSerializer\XmlCredentialPasswordDecryptorDecorator.cs" />
<Compile Include="Config\Serializers\CredentialSerializer\XmlCredentialPasswordEncryptorDecorator.cs" />
<Compile Include="Config\Serializers\ISecureDeserializer.cs" />
<Compile Include="Config\Serializers\ISecureSerializer.cs" />
<Compile Include="Config\Serializers\MiscSerializers\ActiveDirectoryDeserializer.cs" />
<Compile Include="Config\Serializers\CredentialProviderSerializer\CredentialRepositoryListSerializer.cs" />
<Compile Include="Config\Serializers\MiscSerializers\CsvConnectionsSerializerMremotengFormat.cs" />