This repository has been archived by the owner on Oct 17, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 90
/
EphemeralDataProtectionProvider.cs
124 lines (107 loc) · 5.08 KB
/
EphemeralDataProtectionProvider.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 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 Microsoft.AspNetCore.Cryptography.Cng;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection
{
/// <summary>
/// An <see cref="IDataProtectionProvider"/> that is transient.
/// </summary>
/// <remarks>
/// Payloads generated by a given <see cref="EphemeralDataProtectionProvider"/> instance can only
/// be deciphered by that same instance. Once the instance is lost, all ciphertexts
/// generated by that instance are permanently undecipherable.
/// </remarks>
public sealed class EphemeralDataProtectionProvider : IDataProtectionProvider
{
private readonly KeyRingBasedDataProtectionProvider _dataProtectionProvider;
/// <summary>
/// Creates an ephemeral <see cref="IDataProtectionProvider"/>.
/// </summary>
public EphemeralDataProtectionProvider()
: this (NullLoggerFactory.Instance)
{ }
/// <summary>
/// Creates an ephemeral <see cref="IDataProtectionProvider"/> with logging.
/// </summary>
/// <param name="loggerFactory">The <see cref="ILoggerFactory" />.</param>
public EphemeralDataProtectionProvider(ILoggerFactory loggerFactory)
{
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
IKeyRingProvider keyringProvider;
if (OSVersionUtil.IsWindows())
{
// Fastest implementation: AES-256-GCM [CNG]
keyringProvider = new EphemeralKeyRing<CngGcmAuthenticatedEncryptorConfiguration>(loggerFactory);
}
else
{
// Slowest implementation: AES-256-CBC + HMACSHA256 [Managed]
keyringProvider = new EphemeralKeyRing<ManagedAuthenticatedEncryptorConfiguration>(loggerFactory);
}
var logger = loggerFactory.CreateLogger<EphemeralDataProtectionProvider>();
logger.UsingEphemeralDataProtectionProvider();
_dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyringProvider, loggerFactory);
}
public IDataProtector CreateProtector(string purpose)
{
if (purpose == null)
{
throw new ArgumentNullException(nameof(purpose));
}
// just forward to the underlying provider
return _dataProtectionProvider.CreateProtector(purpose);
}
private sealed class EphemeralKeyRing<T> : IKeyRing, IKeyRingProvider
where T : AlgorithmConfiguration, new()
{
public EphemeralKeyRing(ILoggerFactory loggerFactory)
{
DefaultAuthenticatedEncryptor = GetDefaultEncryptor(loggerFactory);
}
// Currently hardcoded to a 512-bit KDK.
private const int NUM_BYTES_IN_KDK = 512 / 8;
public IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; }
public Guid DefaultKeyId { get; } = default(Guid);
public IAuthenticatedEncryptor GetAuthenticatedEncryptorByKeyId(Guid keyId, out bool isRevoked)
{
isRevoked = false;
return (keyId == default(Guid)) ? DefaultAuthenticatedEncryptor : null;
}
public IKeyRing GetCurrentKeyRing()
{
return this;
}
private static IAuthenticatedEncryptor GetDefaultEncryptor(ILoggerFactory loggerFactory)
{
var configuration = new T();
if (configuration is CngGcmAuthenticatedEncryptorConfiguration)
{
var descriptor = (CngGcmAuthenticatedEncryptorDescriptor)new T().CreateNewDescriptor();
return new CngGcmAuthenticatedEncryptorFactory(loggerFactory)
.CreateAuthenticatedEncryptorInstance(
descriptor.MasterKey,
configuration as CngGcmAuthenticatedEncryptorConfiguration);
}
else if (configuration is ManagedAuthenticatedEncryptorConfiguration)
{
var descriptor = (ManagedAuthenticatedEncryptorDescriptor)new T().CreateNewDescriptor();
return new ManagedAuthenticatedEncryptorFactory(loggerFactory)
.CreateAuthenticatedEncryptorInstance(
descriptor.MasterKey,
configuration as ManagedAuthenticatedEncryptorConfiguration);
}
return null;
}
}
}
}