mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
created SecureSerializer abstraction
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
9
mRemoteV1/Config/Serializers/ISecureSerializer.cs
Normal file
9
mRemoteV1/Config/Serializers/ISecureSerializer.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPa
|
||||
new CredentialRecordLoader(credRepoDataProvider, credRepoDeserializer)
|
||||
);
|
||||
_repositoryList.AddProvider(newCredentialRepository);
|
||||
newCredentialRepository.SaveCredentials(_repositoryConfig.Key);
|
||||
}
|
||||
RaiseNextPageEvent();
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user