/// <summary> /// Adds a new ephemeral key used to sign the tokens issued by the OpenID Connect server: /// the key is discarded when the application shuts down and tokens signed using this key /// are automatically invalidated. This method should only be used during development. /// On production, using a X.509 certificate stored in the machine store is recommended. /// </summary> /// <param name="credentials">The signing credentials.</param> /// <param name="algorithm">The algorithm associated with the signing key.</param> /// <returns>The signing credentials.</returns> public static IList <SigningCredentials> AddEphemeralKey( [NotNull] this IList <SigningCredentials> credentials, [NotNull] string algorithm) { if (credentials == null) { throw new ArgumentNullException(nameof(credentials)); } if (string.IsNullOrEmpty(algorithm)) { throw new ArgumentException("The algorithm cannot be null or empty.", nameof(algorithm)); } switch (algorithm) { case SecurityAlgorithms.RsaSha256: case SecurityAlgorithms.RsaSha384: case SecurityAlgorithms.RsaSha512: case SecurityAlgorithms.RsaSha256Signature: case SecurityAlgorithms.RsaSha384Signature: case SecurityAlgorithms.RsaSha512Signature: { var key = new RsaSecurityKey(OpenIdConnectServerHelpers.GenerateRsaKey(2048)); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } #if SUPPORTS_ECDSA case SecurityAlgorithms.EcdsaSha256: case SecurityAlgorithms.EcdsaSha256Signature: { // Generate a new ECDSA key using the P-256 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } case SecurityAlgorithms.EcdsaSha384: case SecurityAlgorithms.EcdsaSha384Signature: { // Generate a new ECDSA key using the P-384 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } case SecurityAlgorithms.EcdsaSha512: case SecurityAlgorithms.EcdsaSha512Signature: { // Generate a new ECDSA key using the P-521 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP521); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } #else case SecurityAlgorithms.EcdsaSha256: case SecurityAlgorithms.EcdsaSha384: case SecurityAlgorithms.EcdsaSha512: case SecurityAlgorithms.EcdsaSha256Signature: case SecurityAlgorithms.EcdsaSha384Signature: case SecurityAlgorithms.EcdsaSha512Signature: throw new PlatformNotSupportedException("ECDSA signing keys are not supported on this platform."); #endif default: throw new InvalidOperationException("The specified algorithm is not supported."); } }
/// <summary> /// Adds a new ephemeral key used to sign the tokens issued by the OpenID Connect server: /// the key is discarded when the application shuts down and tokens signed using this key /// are automatically invalidated. This method should only be used during development. /// On production, using a X.509 certificate stored in the machine store is recommended. /// </summary> /// <param name="credentials">The signing credentials.</param> /// <param name="algorithm">The algorithm associated with the signing key.</param> /// <returns>The signing credentials.</returns> public static IList <SigningCredentials> AddEphemeralKey( [NotNull] this IList <SigningCredentials> credentials, [NotNull] string algorithm) { if (credentials == null) { throw new ArgumentNullException(nameof(credentials)); } if (string.IsNullOrEmpty(algorithm)) { throw new ArgumentException("The algorithm cannot be null or empty.", nameof(algorithm)); } switch (algorithm) { case SecurityAlgorithms.RsaSha256Signature: case SecurityAlgorithms.RsaSha384Signature: case SecurityAlgorithms.RsaSha512Signature: { // Note: a 1024-bit key might be returned by RSA.Create() on .NET Desktop/Mono, // where RSACryptoServiceProvider is still the default implementation and // where custom implementations can be registered via CryptoConfig. // To ensure the key size is always acceptable, replace it if necessary. var rsa = RSA.Create(); if (rsa.KeySize < 2048) { rsa.KeySize = 2048; } #if NET451 // Note: RSACng cannot be used as it's not available on Mono. if (rsa.KeySize < 2048 && rsa is RSACryptoServiceProvider) { rsa.Dispose(); rsa = new RSACryptoServiceProvider(2048); } #endif if (rsa.KeySize < 2048) { throw new InvalidOperationException("The ephemeral key generation failed."); } // Note: the RSA instance cannot be flowed as-is due to a bug in IdentityModel that disposes // the underlying algorithm when it can be cast to RSACryptoServiceProvider. To work around // this bug, the RSA public/private parameters are manually exported and re-imported when needed. SecurityKey key; #if NET451 if (rsa is RSACryptoServiceProvider) { var parameters = rsa.ExportParameters(includePrivateParameters: true); key = new RsaSecurityKey(parameters); key.KeyId = key.GetKeyIdentifier(); // Dispose the algorithm instance. rsa.Dispose(); } else { #endif key = new RsaSecurityKey(rsa); key.KeyId = key.GetKeyIdentifier(); #if NET451 } #endif credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } #if SUPPORTS_ECDSA case SecurityAlgorithms.EcdsaSha256Signature: { // Generate a new ECDSA key using the P-256 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } case SecurityAlgorithms.EcdsaSha384Signature: { // Generate a new ECDSA key using the P-384 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP384); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } case SecurityAlgorithms.EcdsaSha512Signature: { // Generate a new ECDSA key using the P-521 curve. var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP521); var key = new ECDsaSecurityKey(ecdsa); key.KeyId = key.GetKeyIdentifier(); credentials.Add(new SigningCredentials(key, algorithm)); return(credentials); } #endif default: throw new InvalidOperationException("The specified algorithm is not supported."); } }