Я столкнулся с исключением при попытке создать токен JWT в приложении C# Web API.
Тестовая среда
Вот код, отвечающий за создание ключей RSA:
public SignatureInformation CreateNewSignatureInformation(int length = 0)
{
try
{
var signatureInformation = new SignatureInformation();
var rsaProvider = new RSACryptoServiceProvider(length);
var publicKey = rsaProvider.ToXmlString(false);
signatureInformation.Public = publicKey;
var privateKey = rsaProvider.ToXmlString(true);
signatureInformation.Private = privateKey;
return signatureInformation;
}
catch (Exception)
{
return null;
}
}
А вот код, отвечающий за создание токена JTW, подписанного парой ключей RSA, созданной с помощью приведенного выше кода:
private string GenerateToken(string privateKeyInXml)
{
var cryptoServiceProvider = new RSACryptoServiceProvider();
cryptoServiceProvider.FromXmlString(privateKeyInXml);
var creds = new SigningCredentials(new RsaSecurityKey(cryptoServiceProvider),
SecurityAlgorithms.RsaSha256Signature,
SecurityAlgorithms.Sha256Digest);
var nbf = DateTime.UtcNow;
var exp = nbf.AddMinutes(10);
var jwtToken = new JwtSecurityToken("SAMPLE_ISSUER",
"SAMPLE_AUDIENCE",
null, //null is given as claims list in this sample
nbf,
exp,
creds);
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.WriteToken(jwtToken); //the exception is thrown here
return token;
}
выброшенное исключение относится к типу System.ArgumentOutOfRangeException
, а сообщение имеет следующий вид:
"IDX10630: The 'System.IdentityModel.Tokens.RsaSecurityKey' for signing cannot be smaller than '2048' bits.\r\nParameter name: key.KeySize\r\nActual value was 512."
Вопрос
Как я могу сгенерировать токен JWT с помощью ключа безопасности RSA с размером ключа менее 2048?
@Evk Да, это так. Фактически, я создаю еще один набор ключей RSA с размером ключа 2048 для некоторых других целей в моем сервисе. Однако он должен быть меньше, чтобы уменьшить накладные расходы на вычисление ЦП, поскольку система находится под нагрузкой примерно 10 КБ запросов в секунду.
Ограничение минимального размера ключа в этом случае контролируется свойством SignatureProviderFactory.MinimumAsymmetricKeySizeInBitsForSigning
. К сожалению, существует также «абсолютный» минимум, который контролируется только для чтения полем SignatureProviderFactory.AbsoluteMinimumAsymmetricKeySizeInBitsForSigning
, и этот «абсолютный» минимум установлен на 2048.
Вы должны использовать отражение, чтобы изменить значение этого поля только для чтения на желаемое значение. После этого вы можете установить MinimumAsymmetricKeySizeInBitsForSigning
на то же желаемое значение.
Образец кода:
var absoluteField = typeof(SignatureProviderFactory).GetField(nameof(SignatureProviderFactory.AbsoluteMinimumAsymmetricKeySizeInBitsForSigning), BindingFlags.Public | BindingFlags.Static);
absoluteField.SetValue(null, 512);
SignatureProviderFactory.MinimumAsymmetricKeySizeInBitsForSigning = 512;
После этого ваш код должен работать нормально и принимать любые асимметричные ключи размером 512 и выше.
Любой код euivalnet для .net core 3.1. столкнулся с аналогичной проблемой в stackoverflow.com/questions/60599339/…
Обязательно ли использовать ключи меньшего размера? Я имею в виду, что вы можете просто настроить свой код, чтобы вместо этого генерировать ключи с требуемым размером.