/// <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.");
            }
        }
예제 #2
0
        /// <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.");
            }
        }