// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.DataProtection
{
///
/// Contains factory methods for creating an where keys are stored
/// at a particular location on the file system.
///
/// Use these methods when not using dependency injection to provide the service to the application.
public static class DataProtectionProvider
{
///
/// Creates a that store keys in a location based on
/// the platform and operating system.
///
/// An identifier that uniquely discriminates this application from all other
/// applications on the machine.
public static IDataProtectionProvider Create(string applicationName)
{
if (string.IsNullOrEmpty(applicationName))
{
throw new ArgumentNullException(nameof(applicationName));
}
return CreateProvider(
keyDirectory: null,
setupAction: builder => { builder.SetApplicationName(applicationName); },
certificate: null);
}
///
/// Creates an given a location at which to store keys.
///
/// The in which keys should be stored. This may
/// represent a directory on a local disk or a UNC share.
public static IDataProtectionProvider Create(DirectoryInfo keyDirectory)
{
if (keyDirectory == null)
{
throw new ArgumentNullException(nameof(keyDirectory));
}
return CreateProvider(keyDirectory, setupAction: builder => { }, certificate: null);
}
///
/// Creates an given a location at which to store keys and an
/// optional configuration callback.
///
/// The in which keys should be stored. This may
/// represent a directory on a local disk or a UNC share.
/// An optional callback which provides further configuration of the data protection
/// system. See for more information.
public static IDataProtectionProvider Create(
DirectoryInfo keyDirectory,
Action setupAction)
{
if (keyDirectory == null)
{
throw new ArgumentNullException(nameof(keyDirectory));
}
if (setupAction == null)
{
throw new ArgumentNullException(nameof(setupAction));
}
return CreateProvider(keyDirectory, setupAction, certificate: null);
}
#if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml
///
/// Creates a that store keys in a location based on
/// the platform and operating system and uses the given to encrypt the keys.
///
/// An identifier that uniquely discriminates this application from all other
/// applications on the machine.
/// The to be used for encryption.
public static IDataProtectionProvider Create(string applicationName, X509Certificate2 certificate)
{
if (string.IsNullOrEmpty(applicationName))
{
throw new ArgumentNullException(nameof(applicationName));
}
if (certificate == null)
{
throw new ArgumentNullException(nameof(certificate));
}
return CreateProvider(
keyDirectory: null,
setupAction: builder => { builder.SetApplicationName(applicationName); },
certificate: certificate);
}
///
/// Creates an given a location at which to store keys
/// and a used to encrypt the keys.
///
/// The in which keys should be stored. This may
/// represent a directory on a local disk or a UNC share.
/// The to be used for encryption.
public static IDataProtectionProvider Create(
DirectoryInfo keyDirectory,
X509Certificate2 certificate)
{
if (keyDirectory == null)
{
throw new ArgumentNullException(nameof(keyDirectory));
}
if (certificate == null)
{
throw new ArgumentNullException(nameof(certificate));
}
return CreateProvider(keyDirectory, setupAction: builder => { }, certificate: certificate);
}
///
/// Creates an given a location at which to store keys, an
/// optional configuration callback and a used to encrypt the keys.
///
/// The in which keys should be stored. This may
/// represent a directory on a local disk or a UNC share.
/// An optional callback which provides further configuration of the data protection
/// system. See for more information.
/// The to be used for encryption.
public static IDataProtectionProvider Create(
DirectoryInfo keyDirectory,
Action setupAction,
X509Certificate2 certificate)
{
if (keyDirectory == null)
{
throw new ArgumentNullException(nameof(keyDirectory));
}
if (setupAction == null)
{
throw new ArgumentNullException(nameof(setupAction));
}
if (certificate == null)
{
throw new ArgumentNullException(nameof(certificate));
}
return CreateProvider(keyDirectory, setupAction, certificate);
}
#endif
private static IDataProtectionProvider CreateProvider(
DirectoryInfo keyDirectory,
Action setupAction,
X509Certificate2 certificate)
{
// build the service collection
var serviceCollection = new ServiceCollection();
var builder = serviceCollection.AddDataProtection();
if (keyDirectory != null)
{
builder.PersistKeysToFileSystem(keyDirectory);
}
#if !NETSTANDARD1_3 // [[ISSUE60]] Remove this #ifdef when Core CLR gets support for EncryptedXml
if (certificate != null)
{
builder.ProtectKeysWithCertificate(certificate);
}
#endif
setupAction(builder);
// extract the provider instance from the service collection
return serviceCollection.BuildServiceProvider().GetRequiredService();
}
}
}