public void LoadFromFile_ThrowsIfPasswordIsNull() { // Arrange, Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("test.pfx", null, DefaultFlags)); Assert.Equal("There was an error loading the certificate. No password was provided.", exception.Message); }
public static void LoadDevelopment_ThrowsIfKeyDoesNotExist() { // Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadDevelopment("c:/inexistent.json", createIfMissing: false)); Assert.Equal("Couldn't find the file 'c:/inexistent.json' and creation of a development key was not requested.", exception.Message); }
public void LoadFromFile_ThrowsIfFileDoesNotExist() { // Arrange, Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("./nonexisting.pfx", "", DefaultFlags)); Assert.Equal($"There was an error loading the certificate. The file './nonexisting.pfx' was not found.", exception.Message); }
public static IIdentityServerBuilder ConfigureKey(this IIdentityServerBuilder identityServerBuilder, IConfiguration configuration) { if (configuration.GetValue <KeyKinds>("Type") != KeyKinds.KeysRotation) { identityServerBuilder.AddSigningCredentials(); return(identityServerBuilder); } var builder = identityServerBuilder.AddKeysRotation(options => configuration.GetSection(nameof(KeyRotationOptions))?.Bind(options)) .AddRsaEncryptorConfiguration(options => configuration.GetSection(nameof(RsaEncryptorConfiguration))?.Bind(options)); var dataProtectionsOptions = configuration.Get <DataProtectionOptions>(); switch (dataProtectionsOptions.StorageKind) { case StorageKind.AzureStorage: builder.PersistKeysToAzureBlobStorage(new Uri(dataProtectionsOptions.StorageConnectionString)); break; case StorageKind.EntityFramework: builder.PersistKeysToDbContext <OperationalDbContext>(); break; case StorageKind.FileSytem: builder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionsOptions.StorageConnectionString)); break; case StorageKind.Redis: var redis = ConnectionMultiplexer.Connect(dataProtectionsOptions.StorageConnectionString); if (string.IsNullOrEmpty(dataProtectionsOptions.RedisKey)) { builder.PersistKeysToStackExchangeRedis(redis); break; } builder.PersistKeysToStackExchangeRedis(redis, dataProtectionsOptions.RedisKey); break; } var protectOptions = dataProtectionsOptions.KeyProtectionOptions; if (protectOptions != null) { switch (protectOptions.KeyProtectionKind) { case KeyProtectionKind.AzureKeyVault: builder.ProtectKeysWithAzureKeyVault(protectOptions.AzureKeyVaultKeyId, protectOptions.AzureKeyVaultClientId, protectOptions.AzureKeyVaultClientSecret); break; case KeyProtectionKind.X509: if (!string.IsNullOrEmpty(protectOptions.X509CertificatePath)) { var certificate = SigningKeysLoader.LoadFromFile(protectOptions.X509CertificatePath, protectOptions.X509CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet); builder.ProtectKeysWithCertificate(certificate); break; } builder.ProtectKeysWithCertificate(protectOptions.X509CertificateThumbprint); break; } } return(identityServerBuilder); }
public SigningCredentials LoadKey() { // We can't know for sure if there was a configuration section explicitly defined. // Check if the current configuration has any children and avoid failing if that's the case. // This will avoid failing when no configuration has been specified but will still fail if partial data // was defined. if (!_configuration.GetChildren().Any()) { return(null); } var key = new KeyDefinition() { Type = _configuration[nameof(KeyDefinition.Type)], FilePath = _configuration[nameof(KeyDefinition.FilePath)], Password = _configuration[nameof(KeyDefinition.Password)], Name = _configuration[nameof(KeyDefinition.Name)], StoreLocation = _configuration[nameof(KeyDefinition.StoreLocation)], StoreName = _configuration[nameof(KeyDefinition.StoreName)], StorageFlags = _configuration[nameof(KeyDefinition.StorageFlags)] }; if (bool.TryParse(_configuration[nameof(KeyDefinition.Persisted)], out var value)) { key.Persisted = value; } switch (key.Type) { case KeySources.Development: var developmentKeyPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath ?? DefaultTempKeyRelativePath); var createIfMissing = key.Persisted ?? true; _logger.LogInformation(LoggerEventIds.DevelopmentKeyLoaded, "Loading development key at '{developmentKeyPath}'.", developmentKeyPath); var developmentKey = new RsaSecurityKey(SigningKeysLoader.LoadDevelopment(developmentKeyPath, createIfMissing)) { KeyId = "Development" }; return(new SigningCredentials(developmentKey, "RS256")); case KeySources.File: var pfxPath = Path.Combine(Directory.GetCurrentDirectory(), key.FilePath); var storageFlags = GetStorageFlags(key); _logger.LogInformation(LoggerEventIds.CertificateLoadedFromFile, "Loading certificate file at '{CertificatePath}' with storage flags '{CertificateStorageFlags}'.", pfxPath, key.StorageFlags); return(new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromFile(pfxPath, key.Password, storageFlags)), "RS256")); case KeySources.Store: if (!Enum.TryParse <StoreLocation>(key.StoreLocation, out var storeLocation)) { throw new InvalidOperationException($"Invalid certificate store location '{key.StoreLocation}'."); } _logger.LogInformation(LoggerEventIds.CertificateLoadedFromStore, "Loading certificate with subject '{CertificateSubject}' in '{CertificateStoreLocation}\\{CertificateStoreName}'.", key.Name, key.StoreLocation, key.StoreName); return(new SigningCredentials(new X509SecurityKey(SigningKeysLoader.LoadFromStoreCert(key.Name, key.StoreName, storeLocation, GetCurrentTime())), "RS256")); default: throw new InvalidOperationException($"Invalid key type '{key.Type ?? "(null)"}'."); } }
public void LoadFromFile_ThrowsIfPasswordIsIncorrect() { // Arrange, Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromFile("test.pfx", "incorrect", DefaultFlags)); Assert.Equal( $"There was an error loading the certificate. Either the password is incorrect or the process does not have permisions to store the key in the Keyset '{DefaultFlags}'", exception.Message); }
public static void LoadFromStoreCert_ThrowsIfThereIsNoCertificateAvailable() { // Arrange var time = new DateTimeOffset(2018, 09, 25, 12, 0, 0, TimeSpan.Zero); // Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => SigningKeysLoader.LoadFromStoreCert("Invalid", "My", StoreLocation.CurrentUser, time)); Assert.Equal("Couldn't find a valid certificate with subject 'Invalid' on the 'CurrentUser\\My'", exception.Message); }
public void Encrypt_retreive_cert_from_thumbrint() { var cert = SigningKeysLoader.LoadFromFile("TestCert1.pfx", "password", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet); var resolverMock = new Mock <Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver>(); resolverMock.Setup(m => m.ResolveCertificate(It.IsAny <string>())).Returns(cert); var sut = new CertificateXmlEncryptor(cert.Thumbprint, resolverMock.Object, NullLoggerFactory.Instance); var result = sut.Encrypt(new XElement("test")); Assert.NotNull(result); }
public static void LoadDevelopment_CreatesKeyIfItDoesNotExist() { // Arrange var path = "./tempkeyfolder/tempkey.json"; if (File.Exists(path)) { File.Delete(path); } // Act var key = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true); // Assert Assert.NotNull(key); Assert.True(File.Exists(path)); }
public static void LoadFromStoreCert_PrefersCertificatesCloserToExpirationDate() { try { SetupCertificates("./current.pfx", "./future.pfx"); // Arrange var time = new DateTimeOffset(2020, 10, 29, 12, 0, 0, TimeSpan.Zero); // Act var certificate = SigningKeysLoader.LoadFromStoreCert("CN=SigningKeysLoaderTest", "My", StoreLocation.CurrentUser, time); // Assert Assert.NotNull(certificate); Assert.Equal("C54CD513088C23EC2AFD256874CC6C0F81EA9D5E", certificate.Thumbprint); } finally { CleanupCertificates(); } }
public static void LoadFromStoreCert_SkipsExpiredCertificates() { try { SetupCertificates("./expired.pfx", "./current.pfx", "./future.pfx"); // Arrange var time = new DateTimeOffset(2024, 01, 01, 12, 0, 0, TimeSpan.Zero); // Act var certificate = SigningKeysLoader.LoadFromStoreCert("CN=SigningKeysLoaderTest", "My", StoreLocation.CurrentUser, time); // Assert Assert.NotNull(certificate); Assert.Equal("35840DD366107B89D2885A6B4F42CCBBAE6BA8E3", certificate.Thumbprint); } finally { CleanupCertificates(); } }
public static void LoadDevelopment_ReusesKeyIfExists() { // Arrange var path = "./tempkeyfolder/existing.json"; if (File.Exists(path)) { File.Delete(path); } var existingKey = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true); var existingParameters = existingKey.ExportParameters(includePrivateParameters: true); // Act var currentKey = SigningKeysLoader.LoadDevelopment(path, createIfMissing: true); var currentParameters = currentKey.ExportParameters(includePrivateParameters: true); // Assert Assert.NotNull(currentKey); Assert.Equal(existingParameters.P, currentParameters.P); Assert.Equal(existingParameters.Q, currentParameters.Q); }
public static IDataProtectionBuilder ConfigureDataProtection(this IDataProtectionBuilder builder, IConfiguration configuration) { var dataProtectionsOptions = configuration.Get <Aguacongas.TheIdServer.Models.DataProtectionOptions>(); if (dataProtectionsOptions == null) { return(builder); } builder.AddKeyManagementOptions(options => configuration.GetSection(nameof(KeyManagementOptions))?.Bind(options)); ConfigureEncryptionAlgorithm(builder, configuration); switch (dataProtectionsOptions.StorageKind) { case StorageKind.AzureStorage: builder.PersistKeysToAzureBlobStorage(new Uri(dataProtectionsOptions.StorageConnectionString)); break; case StorageKind.EntityFramework: builder.PersistKeysToDbContext <OperationalDbContext>(); break; case StorageKind.FileSytem: builder.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionsOptions.StorageConnectionString)); break; case StorageKind.Redis: var redis = ConnectionMultiplexer.Connect(dataProtectionsOptions.StorageConnectionString); if (string.IsNullOrEmpty(dataProtectionsOptions.RedisKey)) { builder.PersistKeysToStackExchangeRedis(redis); break; } builder.PersistKeysToStackExchangeRedis(redis, dataProtectionsOptions.RedisKey); break; case StorageKind.Registry: #pragma warning disable CA1416 // Validate platform compatibility builder.PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(dataProtectionsOptions.StorageConnectionString)); #pragma warning restore CA1416 // Validate platform compatibility break; } var protectOptions = dataProtectionsOptions.KeyProtectionOptions; if (protectOptions != null) { switch (protectOptions.KeyProtectionKind) { case KeyProtectionKind.AzureKeyVault: builder.ProtectKeysWithAzureKeyVault(protectOptions.AzureKeyVaultKeyId, protectOptions.AzureKeyVaultClientId, protectOptions.AzureKeyVaultClientSecret); break; case KeyProtectionKind.WindowsDpApi: builder.ProtectKeysWithDpapi(protectOptions.WindowsDPAPILocalMachine); break; case KeyProtectionKind.WindowsDpApiNg: ConfigureWindowsDpApiNg(builder, protectOptions); break; case KeyProtectionKind.X509: if (!string.IsNullOrEmpty(protectOptions.X509CertificatePath)) { var certificate = SigningKeysLoader.LoadFromFile(protectOptions.X509CertificatePath, protectOptions.X509CertificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.UserKeySet); builder.ProtectKeysWithCertificate(certificate); break; } builder.ProtectKeysWithCertificate(protectOptions.X509CertificateThumbprint); break; } } return(builder); }