public void ResolvePolicy_CngCbcEncryption_WithExplicitSettings() { IServiceCollection serviceCollection = new ServiceCollection(); RunTestWithRegValues(serviceCollection, new Dictionary <string, object>() { ["EncryptionType"] = "cng-cbc", ["EncryptionAlgorithm"] = "enc-alg", ["EncryptionAlgorithmKeySize"] = 2048, ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider", ["HashAlgorithm"] = "hash-alg", ["HashAlgorithmProvider"] = "my-hash-alg-provider" }); var services = serviceCollection.BuildServiceProvider(); var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration(new CngCbcAuthenticatedEncryptionOptions() { EncryptionAlgorithm = "enc-alg", EncryptionAlgorithmKeySize = 2048, EncryptionAlgorithmProvider = "my-enc-alg-provider", HashAlgorithm = "hash-alg", HashAlgorithmProvider = "my-hash-alg-provider" }); var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)services.GetService <IAuthenticatedEncryptorConfiguration>(); Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithm, actualConfiguration.Options.EncryptionAlgorithm); Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithmKeySize, actualConfiguration.Options.EncryptionAlgorithmKeySize); Assert.Equal(expectedConfiguration.Options.EncryptionAlgorithmProvider, actualConfiguration.Options.EncryptionAlgorithmProvider); Assert.Equal(expectedConfiguration.Options.HashAlgorithm, actualConfiguration.Options.HashAlgorithm); Assert.Equal(expectedConfiguration.Options.HashAlgorithmProvider, actualConfiguration.Options.HashAlgorithmProvider); }
internal IAuthenticatedEncryptor?CreateAuthenticatedEncryptorInstance( ISecret secret, AuthenticatedEncryptorConfiguration?authenticatedConfiguration) { if (authenticatedConfiguration == null) { return(null); } if (IsGcmAlgorithm(authenticatedConfiguration.EncryptionAlgorithm)) { #if NETCOREAPP return(new AesGcmAuthenticatedEncryptor(secret, GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm) / 8)); #else // GCM requires CNG, and CNG is only supported on Windows. if (!OSVersionUtil.IsWindows()) { throw new PlatformNotSupportedException(Resources.Platform_WindowsRequiredForGcm); } Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); var configuration = new CngGcmAuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm) }; return(new CngGcmAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); #endif } else { if (OSVersionUtil.IsWindows()) { Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); // CNG preferred over managed implementations if running on Windows var configuration = new CngCbcAuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), HashAlgorithm = GetBCryptAlgorithmNameFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) }; return(new CngCbcAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); } else { // Use managed implementations as a fallback var configuration = new ManagedAuthenticatedEncryptorConfiguration() { EncryptionAlgorithmType = GetManagedTypeFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), ValidationAlgorithmType = GetManagedTypeFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) }; return(new ManagedAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); } } }
public void ResolvePolicy_CngCbcEncryption_WithExplicitSettings() { // Arrange var registryEntries = new Dictionary <string, object>() { ["EncryptionType"] = "cng-cbc", ["EncryptionAlgorithm"] = "enc-alg", ["EncryptionAlgorithmKeySize"] = 2048, ["EncryptionAlgorithmProvider"] = "my-enc-alg-provider", ["HashAlgorithm"] = "hash-alg", ["HashAlgorithmProvider"] = "my-hash-alg-provider" }; var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = "enc-alg", EncryptionAlgorithmKeySize = 2048, EncryptionAlgorithmProvider = "my-enc-alg-provider", HashAlgorithm = "hash-alg", HashAlgorithmProvider = "my-hash-alg-provider" }; // Act var context = RunTestWithRegValues(registryEntries); // Assert var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration; Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm); Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize); Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider); Assert.Equal(expectedConfiguration.HashAlgorithm, actualConfiguration.HashAlgorithm); Assert.Equal(expectedConfiguration.HashAlgorithmProvider, actualConfiguration.HashAlgorithmProvider); }
/// <summary> /// Imports the <see cref="CngCbcAuthenticatedEncryptorDescriptor"/> from serialized XML. /// </summary> public IAuthenticatedEncryptorDescriptor ImportFromXml(XElement element) { if (element == null) { throw new ArgumentNullException(nameof(element)); } // <descriptor> // <!-- Windows CNG-CBC --> // <encryption algorithm="..." keyLength="..." [provider="..."] /> // <hash algorithm="..." [provider="..."] /> // <masterKey>...</masterKey> // </descriptor> var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); var encryptionElement = element.Element("encryption") !; configuration.EncryptionAlgorithm = (string)encryptionElement.Attribute("algorithm") !; configuration.EncryptionAlgorithmKeySize = (int)encryptionElement.Attribute("keyLength") !; configuration.EncryptionAlgorithmProvider = (string?)encryptionElement.Attribute("provider"); // could be null var hashElement = element.Element("hash") !; configuration.HashAlgorithm = (string)hashElement.Attribute("algorithm") !; configuration.HashAlgorithmProvider = (string?)hashElement.Attribute("provider"); // could be null Secret masterKey = ((string)element.Element("masterKey")) !.ToSecret(); return(new CngCbcAuthenticatedEncryptorDescriptor(configuration, masterKey)); }
public void CreateNewDescriptor_PropagatesOptions() { // Arrange var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); // Act var descriptor = (CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor(); // Assert Assert.Equal(configuration, descriptor.Configuration); }
internal IAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( ISecret secret, AuthenticatedEncryptorConfiguration authenticatedConfiguration) { if (authenticatedConfiguration == null) { return(null); } if (IsGcmAlgorithm(authenticatedConfiguration.EncryptionAlgorithm)) { // GCM requires CNG, and CNG is only supported on Windows. if (!OSVersionUtil.IsWindows()) { throw new PlatformNotSupportedException("GCM algorithms require the Windows platform."); } var configuration = new CngGcmAuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm) }; return(new CngGcmAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); } else { if (OSVersionUtil.IsWindows()) { // CNG preferred over managed implementations if running on Windows var configuration = new CngCbcAuthenticatedEncryptorConfiguration() { EncryptionAlgorithm = GetBCryptAlgorithmNameFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), HashAlgorithm = GetBCryptAlgorithmNameFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) }; return(new CngCbcAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); } else { // Use managed implementations as a fallback var configuration = new ManagedAuthenticatedEncryptorConfiguration() { EncryptionAlgorithmType = GetManagedTypeFromEncryptionAlgorithm(authenticatedConfiguration.EncryptionAlgorithm), EncryptionAlgorithmKeySize = GetAlgorithmKeySizeInBits(authenticatedConfiguration.EncryptionAlgorithm), ValidationAlgorithmType = GetManagedTypeFromValidationAlgorithm(authenticatedConfiguration.ValidationAlgorithm) }; return(new ManagedAuthenticatedEncryptorFactory(_loggerFactory).CreateAuthenticatedEncryptorInstance(secret, configuration)); } } }
public void CreateNewDescriptor_CreatesUniqueCorrectlySizedMasterKey() { // Arrange var configuration = new CngCbcAuthenticatedEncryptorConfiguration(); // Act var masterKey1 = ((CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; var masterKey2 = ((CngCbcAuthenticatedEncryptorDescriptor)configuration.CreateNewDescriptor()).MasterKey; // Assert SecretAssert.NotEqual(masterKey1, masterKey2); SecretAssert.LengthIs(512 /* bits */, masterKey1); SecretAssert.LengthIs(512 /* bits */, masterKey2); }
internal CbcAuthenticatedEncryptor CreateAuthenticatedEncryptorInstance( ISecret secret, CngCbcAuthenticatedEncryptorConfiguration configuration) { if (configuration == null) { return(null); } return(new CbcAuthenticatedEncryptor( keyDerivationKey: new Secret(secret), symmetricAlgorithmHandle: GetSymmetricBlockCipherAlgorithmHandle(configuration), symmetricAlgorithmKeySizeInBytes: (uint)(configuration.EncryptionAlgorithmKeySize / 8), hmacAlgorithmHandle: GetHmacAlgorithmHandle(configuration))); }
/// <summary> /// Initializes a new instance of <see cref="CngCbcAuthenticatedEncryptorDescriptor"/>. /// </summary> /// <param name="configuration">The <see cref="CngCbcAuthenticatedEncryptorConfiguration"/>.</param> /// <param name="masterKey">The master key.</param> public CngCbcAuthenticatedEncryptorDescriptor(CngCbcAuthenticatedEncryptorConfiguration configuration, ISecret masterKey) { if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (masterKey == null) { throw new ArgumentNullException(nameof(masterKey)); } Configuration = configuration; MasterKey = masterKey; }
public void CreateEncrptorInstance_ExpectedDescriptorType_ReturnsEncryptor() { // Arrange var descriptor = new CngCbcAuthenticatedEncryptorConfiguration().CreateNewDescriptor(); var key = new Mock <IKey>(); key.Setup(k => k.Descriptor).Returns(descriptor); var factory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance); // Act var encryptor = factory.CreateEncryptorInstance(key.Object); // Assert Assert.NotNull(encryptor); Assert.IsType <CbcAuthenticatedEncryptor>(encryptor); }
public void ResolvePolicy_CngCbcEncryption_WithoutExplicitSettings() { IServiceCollection serviceCollection = new ServiceCollection(); RunTestWithRegValues(serviceCollection, new Dictionary <string, object>() { ["EncryptionType"] = "cng-cbc" }); var services = serviceCollection.BuildServiceProvider(); var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration(new CngCbcAuthenticatedEncryptionSettings()); var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)services.GetService <IAuthenticatedEncryptorConfiguration>(); Assert.Equal(expectedConfiguration.Settings.EncryptionAlgorithm, actualConfiguration.Settings.EncryptionAlgorithm); Assert.Equal(expectedConfiguration.Settings.EncryptionAlgorithmKeySize, actualConfiguration.Settings.EncryptionAlgorithmKeySize); Assert.Equal(expectedConfiguration.Settings.EncryptionAlgorithmProvider, actualConfiguration.Settings.EncryptionAlgorithmProvider); Assert.Equal(expectedConfiguration.Settings.HashAlgorithm, actualConfiguration.Settings.HashAlgorithm); Assert.Equal(expectedConfiguration.Settings.HashAlgorithmProvider, actualConfiguration.Settings.HashAlgorithmProvider); }
private BCryptAlgorithmHandle GetHmacAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) { // basic argument checking if (String.IsNullOrEmpty(configuration.HashAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(configuration.HashAlgorithm)); } _logger.OpeningCNGAlgorithmFromProviderWithHMAC(configuration.HashAlgorithm, configuration.HashAlgorithmProvider); BCryptAlgorithmHandle?algorithmHandle = null; // Special-case cached providers if (configuration.HashAlgorithmProvider == null) { if (configuration.HashAlgorithm == Constants.BCRYPT_SHA1_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA1; } else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA256_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA256; } else if (configuration.HashAlgorithm == Constants.BCRYPT_SHA512_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.HMAC_SHA512; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.HashAlgorithm, configuration.HashAlgorithmProvider, hmac: true); } // Make sure we're using a hash algorithm. We require a minimum 128-bit digest. uint digestSize = algorithmHandle.GetHashDigestLength(); AlgorithmAssert.IsAllowableValidationAlgorithmDigestSize(checked (digestSize * 8)); // all good! return(algorithmHandle); }
private BCryptAlgorithmHandle GetSymmetricBlockCipherAlgorithmHandle(CngCbcAuthenticatedEncryptorConfiguration configuration) { // basic argument checking if (String.IsNullOrEmpty(configuration.EncryptionAlgorithm)) { throw Error.Common_PropertyCannotBeNullOrEmpty(nameof(EncryptionAlgorithm)); } if (configuration.EncryptionAlgorithmKeySize < 0) { throw Error.Common_PropertyMustBeNonNegative(nameof(configuration.EncryptionAlgorithmKeySize)); } _logger.OpeningCNGAlgorithmFromProviderWithChainingModeCBC(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); BCryptAlgorithmHandle?algorithmHandle = null; // Special-case cached providers if (configuration.EncryptionAlgorithmProvider == null) { if (configuration.EncryptionAlgorithm == Constants.BCRYPT_AES_ALGORITHM) { algorithmHandle = CachedAlgorithmHandles.AES_CBC; } } // Look up the provider dynamically if we couldn't fetch a cached instance if (algorithmHandle == null) { algorithmHandle = BCryptAlgorithmHandle.OpenAlgorithmHandle(configuration.EncryptionAlgorithm, configuration.EncryptionAlgorithmProvider); algorithmHandle.SetChainingMode(Constants.BCRYPT_CHAIN_MODE_CBC); } // make sure we're using a block cipher with an appropriate key size & block size AlgorithmAssert.IsAllowableSymmetricAlgorithmBlockSize(checked (algorithmHandle.GetCipherBlockLength() * 8)); AlgorithmAssert.IsAllowableSymmetricAlgorithmKeySize(checked ((uint)configuration.EncryptionAlgorithmKeySize)); // make sure the provided key length is valid algorithmHandle.GetSupportedKeyLengths().EnsureValidKeyLength((uint)configuration.EncryptionAlgorithmKeySize); // all good! return(algorithmHandle); }
private RegistryPolicy?ResolvePolicyCore(RegistryKey?policyRegKey) { if (policyRegKey == null) { return(null); } // Read the encryption options type: CNG-CBC, CNG-GCM, Managed AlgorithmConfiguration?configuration = null; var encryptionType = (string?)policyRegKey.GetValue("EncryptionType"); if (String.Equals(encryptionType, "CNG-CBC", StringComparison.OrdinalIgnoreCase)) { configuration = new CngCbcAuthenticatedEncryptorConfiguration(); } else if (String.Equals(encryptionType, "CNG-GCM", StringComparison.OrdinalIgnoreCase)) { configuration = new CngGcmAuthenticatedEncryptorConfiguration(); } else if (String.Equals(encryptionType, "Managed", StringComparison.OrdinalIgnoreCase)) { configuration = new ManagedAuthenticatedEncryptorConfiguration(); } else if (!String.IsNullOrEmpty(encryptionType)) { throw CryptoUtil.Fail("Unrecognized EncryptionType: " + encryptionType); } if (configuration != null) { PopulateOptions(configuration, policyRegKey); } // Read ancillary data var defaultKeyLifetime = (int?)policyRegKey.GetValue("DefaultKeyLifetime"); var keyEscrowSinks = ReadKeyEscrowSinks(policyRegKey).Select(item => _activator.CreateInstance <IKeyEscrowSink>(item)); return(new RegistryPolicy(configuration, keyEscrowSinks, defaultKeyLifetime)); }
private static CngCbcAuthenticatedEncryptorConfiguration GetCngCbcAuthenticatedEncryptorConfiguration(RegistryKey key) { var options = new CngCbcAuthenticatedEncryptorConfiguration(); var valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithm)); if (valueFromRegistry != null) { options.EncryptionAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture) !; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmProvider)); if (valueFromRegistry != null) { options.EncryptionAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture) !; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.EncryptionAlgorithmKeySize)); if (valueFromRegistry != null) { options.EncryptionAlgorithmKeySize = Convert.ToInt32(valueFromRegistry, CultureInfo.InvariantCulture); } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithm)); if (valueFromRegistry != null) { options.HashAlgorithm = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture) !; } valueFromRegistry = key.GetValue(nameof(CngCbcAuthenticatedEncryptorConfiguration.HashAlgorithmProvider)); if (valueFromRegistry != null) { options.HashAlgorithmProvider = Convert.ToString(valueFromRegistry, CultureInfo.InvariantCulture); } return(options); }
public static IDataProtectionBuilder UseCustomCryptographicAlgorithms(this IDataProtectionBuilder builder, CngCbcAuthenticatedEncryptorConfiguration configuration) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } return(UseCryptographicAlgorithmsCore(builder, configuration)); }