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 125 126 127 128 129 130 131 132 133 134 135
|
//------------------------------------------------------------------------------
// <copyright file="MachineKeyCryptoAlgorithmFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Security.Cryptography {
using System;
using System.Security.Cryptography;
using System.Web.Configuration;
// Can create cryptographic algorithms from a given <machineKey> element
internal sealed class MachineKeyCryptoAlgorithmFactory : ICryptoAlgorithmFactory {
private Func<SymmetricAlgorithm> _encryptionAlgorithmFactory;
private readonly MachineKeySection _machineKeySection;
private Func<KeyedHashAlgorithm> _validationAlgorithmFactory;
public MachineKeyCryptoAlgorithmFactory(MachineKeySection machineKeySection) {
_machineKeySection = machineKeySection;
}
public SymmetricAlgorithm GetEncryptionAlgorithm() {
if (_encryptionAlgorithmFactory == null) {
_encryptionAlgorithmFactory = GetEncryptionAlgorithmFactory();
}
return _encryptionAlgorithmFactory();
}
private Func<SymmetricAlgorithm> GetEncryptionAlgorithmFactory() {
return GetGenericAlgorithmFactory<SymmetricAlgorithm>(
configAttributeName: "decryption",
configAttributeValue: _machineKeySection.GetDecryptionAttributeSkipValidation(),
switchStatement: algorithmName => {
// We suppress CS0618 since some of the algorithms we support are marked with [Obsolete].
// These deprecated algorithms are *not* enabled by default. Developers must opt-in to
// them, so we're secure by default.
#pragma warning disable 618
switch (algorithmName) {
case "AES":
case "Auto": // currently "Auto" defaults to AES
return CryptoAlgorithms.CreateAes;
case "DES":
return CryptoAlgorithms.CreateDES;
case "3DES":
return CryptoAlgorithms.CreateTripleDES;
default:
return null; // unknown
#pragma warning restore 618
}
},
errorResourceString: SR.Wrong_decryption_enum);
}
public KeyedHashAlgorithm GetValidationAlgorithm() {
if (_validationAlgorithmFactory == null) {
_validationAlgorithmFactory = GetValidationAlgorithmFactory();
}
return _validationAlgorithmFactory();
}
private Func<KeyedHashAlgorithm> GetValidationAlgorithmFactory() {
return GetGenericAlgorithmFactory<KeyedHashAlgorithm>(
configAttributeName: "validation",
configAttributeValue: _machineKeySection.GetValidationAttributeSkipValidation(),
switchStatement: algorithmName => {
switch (algorithmName) {
case "SHA1":
return CryptoAlgorithms.CreateHMACSHA1;
case "HMACSHA256":
return CryptoAlgorithms.CreateHMACSHA256;
case "HMACSHA384":
return CryptoAlgorithms.CreateHMACSHA384;
case "HMACSHA512":
return CryptoAlgorithms.CreateHMACSHA512;
default:
return null; // unknown
}
},
errorResourceString: SR.Wrong_validation_enum_FX45);
}
// Contains common logic for creating encryption / validation factories, including
// custom algorithm lookup and exception handling.
private Func<TResult> GetGenericAlgorithmFactory<TResult>(string configAttributeName, string configAttributeValue, Func<string, Func<TResult>> switchStatement, string errorResourceString) where TResult : class, IDisposable {
Func<TResult> factory;
if (configAttributeValue != null && configAttributeValue.StartsWith("alg:", StringComparison.Ordinal)) {
string algorithmName = configAttributeValue.Substring("alg:".Length);
factory = () => {
// Since the custom algorithm might depend on the impersonated
// identity, we must instantiate it under app-level impersonation.
using (new ApplicationImpersonationContext()) {
return (TResult)CryptoConfig.CreateFromName(algorithmName);
}
};
}
else {
// If using a built-in algorithm, consult the switch statement to get the factory.
factory = switchStatement(configAttributeValue);
}
// Invoke the factory once to make sure there aren't any configuration errors.
Exception factoryCreationException = null;
try {
if (factory != null) {
TResult algorithm = factory();
if (algorithm != null) {
algorithm.Dispose();
return factory; // we know at this point the factory is good
}
}
}
catch (Exception ex) {
factoryCreationException = ex;
}
// If we reached this point, there was a failure:
// the factory returned null, threw, or did something else unexpected.
throw ConfigUtil.MakeConfigurationErrorsException(
message: SR.GetString(errorResourceString),
innerException: factoryCreationException, // can be null
configProperty: _machineKeySection.ElementInformation.Properties[configAttributeName]);
}
}
}
|