Add UnprotectKeysWithAnyCertificate
This commit is contained in:
parent
3d30ea8249
commit
70dcbf6ed6
|
|
@ -320,6 +320,33 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configures certificates which can be used to decrypt keys loaded from storage.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IDataProtectionBuilder"/>.</param>
|
||||||
|
/// <param name="certificates">Certificates that can be used to decrypt key data.</param>
|
||||||
|
/// <returns>A reference to the <see cref="IDataProtectionBuilder" /> after this operation has completed.</returns>
|
||||||
|
public static IDataProtectionBuilder UnprotectKeysWithAnyCertificate(this IDataProtectionBuilder builder, params X509Certificate2[] certificates)
|
||||||
|
{
|
||||||
|
if (builder == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Services.Configure<XmlKeyDecryptionOptions>(o =>
|
||||||
|
{
|
||||||
|
if (certificates != null)
|
||||||
|
{
|
||||||
|
foreach (var certificate in certificates)
|
||||||
|
{
|
||||||
|
o.AddKeyDecryptionCertificate(certificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configures keys to be encrypted with Windows DPAPI before being persisted to
|
/// Configures keys to be encrypted with Windows DPAPI before being persisted to
|
||||||
/// storage. The encrypted key will only be decryptable by the current Windows user account.
|
/// storage. The encrypted key will only be decryptable by the current Windows user account.
|
||||||
|
|
|
||||||
|
|
@ -171,16 +171,16 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
|
|
||||||
WithUniqueTempDirectory(directory =>
|
WithUniqueTempDirectory(directory =>
|
||||||
{
|
{
|
||||||
// Step 1: directory should be completely empty
|
// Step 1: directory should be completely empty
|
||||||
directory.Create();
|
directory.Create();
|
||||||
Assert.Empty(directory.GetFiles());
|
Assert.Empty(directory.GetFiles());
|
||||||
|
|
||||||
// Step 2: instantiate the system and round-trip a payload
|
// Step 2: instantiate the system and round-trip a payload
|
||||||
var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose");
|
var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose");
|
||||||
Assert.Equal("payload", protector.Unprotect(protector.Protect("payload")));
|
Assert.Equal("payload", protector.Unprotect(protector.Protect("payload")));
|
||||||
|
|
||||||
// Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate
|
// Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate
|
||||||
var allFiles = directory.GetFiles();
|
var allFiles = directory.GetFiles();
|
||||||
Assert.Single(allFiles);
|
Assert.Single(allFiles);
|
||||||
Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase);
|
Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase);
|
||||||
string fileText = File.ReadAllText(allFiles[0].FullName);
|
string fileText = File.ReadAllText(allFiles[0].FullName);
|
||||||
|
|
@ -189,6 +189,40 @@ namespace Microsoft.AspNetCore.DataProtection
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void System_CanUnprotectWithCert()
|
||||||
|
{
|
||||||
|
var filePath = Path.Combine(GetTestFilesPath(), "TestCert2.pfx");
|
||||||
|
var certificate = new X509Certificate2(filePath, "password");
|
||||||
|
|
||||||
|
WithUniqueTempDirectory(directory =>
|
||||||
|
{
|
||||||
|
// Step 1: directory should be completely empty
|
||||||
|
directory.Create();
|
||||||
|
Assert.Empty(directory.GetFiles());
|
||||||
|
|
||||||
|
// Step 2: instantiate the system and create some data
|
||||||
|
var protector = DataProtectionProvider
|
||||||
|
.Create(directory, certificate)
|
||||||
|
.CreateProtector("purpose");
|
||||||
|
|
||||||
|
var data = protector.Protect("payload");
|
||||||
|
|
||||||
|
// Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate
|
||||||
|
var allFiles = directory.GetFiles();
|
||||||
|
Assert.Single(allFiles);
|
||||||
|
Assert.StartsWith("key-", allFiles[0].Name, StringComparison.OrdinalIgnoreCase);
|
||||||
|
string fileText = File.ReadAllText(allFiles[0].FullName);
|
||||||
|
Assert.DoesNotContain("Warning: the key below is in an unencrypted form.", fileText, StringComparison.Ordinal);
|
||||||
|
Assert.Contains("X509Certificate", fileText, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
// Step 4: setup a second system and validate it can decrypt keys and unprotect data
|
||||||
|
var unprotector = DataProtectionProvider.Create(directory,
|
||||||
|
b => b.UnprotectKeysWithAnyCertificate(certificate));
|
||||||
|
Assert.Equal("payload", unprotector.CreateProtector("purpose").Unprotect(data));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a test and cleans up the temp directory afterward.
|
/// Runs a test and cleans up the temp directory afterward.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue