aspnetcore/src/Service.Core/CryptographyHelpers.cs

124 lines
4.0 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.Tokens;
namespace Microsoft.AspNetCore.Identity.Service
{
internal static class CryptographyHelpers
{
private static readonly RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();
public static string FindAlgorithm(X509Certificate2 certificate)
{
var rsapk = certificate.GetRSAPublicKey();
if (rsapk != null)
{
return "RS256";
}
else
{
throw new InvalidOperationException("Algorithm not supported.");
}
}
public static void ValidateRsaKeyLength(X509Certificate2 certificate)
{
var rsa = certificate.GetRSAPublicKey();
if (rsa == null)
{
throw new InvalidOperationException("Algorithm not supported.");
}
ValidateRsaKeyLength(rsa);
}
public static void ValidateRsaKeyLength(RSA rsa)
{
if (rsa.KeySize < 2048)
{
throw new InvalidOperationException("The RSA key must be at least 2048 bits long.");
}
return;
}
public static SHA256 CreateSHA256()
{
SHA256 sha256 = null;
try
{
sha256 = SHA256.Create();
return sha256;
}
// SHA256.Create is documented to throw this exception on FIPS compliant machines.
// See: https://msdn.microsoft.com/enus/library/z08hz7ad%28v=vs.110%29.aspx?f=255&MSPPError=2147217396
catch (System.Reflection.TargetInvocationException)
{
// Fallback to a FIPS compliant SHA256 algorithm.
sha256 = new SHA256CryptoServiceProvider();
}
return sha256;
}
public static RSAParameters GetRSAParameters(SigningCredentials credentials)
{
RSA algorithm = null;
if (credentials.Key is X509SecurityKey x509SecurityKey)
{
algorithm = x509SecurityKey.PublicKey as RSA;
}
if (credentials.Key is RsaSecurityKey rsaSecurityKey)
{
algorithm = rsaSecurityKey.Rsa;
if (algorithm == null)
{
var rsa = RSA.Create();
rsa.ImportParameters(rsaSecurityKey.Parameters);
algorithm = rsa;
}
}
var parameters = algorithm.ExportParameters(includePrivateParameters: false);
return parameters;
}
public static string GetAlgorithm(SigningCredentials credentials)
{
RSA algorithm = null;
if (credentials.Key is X509SecurityKey x509SecurityKey && x509SecurityKey.PublicKey is RSA)
{
return JsonWebAlgorithmsKeyTypes.RSA;
}
var rsaSecurityKey = credentials.Key as RsaSecurityKey;
// Check that the key has either an Asymmetric Algorithm assigned or that at least
// one of the RSA parameters are initialized to consider the key "valid".
if (rsaSecurityKey != null &&
(rsaSecurityKey.Rsa != null || rsaSecurityKey.Parameters.Modulus != null))
{
return JsonWebAlgorithmsKeyTypes.RSA;
}
if (algorithm != null)
{
return JsonWebAlgorithmsKeyTypes.RSA;
}
throw new NotSupportedException();
}
internal static string GenerateHighEntropyValue(int byteLength)
{
var bytes = new byte[byteLength];
randomNumberGenerator.GetBytes(bytes);
return Base64UrlEncoder.Encode(bytes);
}
}
}