88 lines
2.6 KiB
C#
88 lines
2.6 KiB
C#
|
|
using System.Security.Cryptography;
|
||
|
|
using System.Text.Json;
|
||
|
|
using IdentityShroud.Core.Model;
|
||
|
|
using IdentityShroud.Core.Services;
|
||
|
|
|
||
|
|
namespace IdentityShroud.Core;
|
||
|
|
|
||
|
|
public class SignatureProviderFactory(DekEncryptionService dekCryptor, IServiceProvider services)
|
||
|
|
{
|
||
|
|
|
||
|
|
public static void SelectAlgorithmAndKey(Realm realm, Client client, out JwtSigAlgName alg, out byte[] key)
|
||
|
|
{
|
||
|
|
throw new NotImplementedException();
|
||
|
|
}
|
||
|
|
|
||
|
|
public IJwtSignatureProvider Create(JwtSigAlgName algorithm, byte[] keyData)
|
||
|
|
{
|
||
|
|
|
||
|
|
|
||
|
|
//realm.DefaultSignatureAlgorithm
|
||
|
|
//realm.TokenSigningKeys
|
||
|
|
|
||
|
|
//IJwtSignatureProvider? sigProvider = services.GetKeyedService<IJwtSignatureProvider>();
|
||
|
|
throw new NotImplementedException();
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class RsaJwtSignatureProvider : IJwtSignatureProvider
|
||
|
|
{
|
||
|
|
private JwtSigAlgName _sigAlgName;
|
||
|
|
private RealmSigningKeyId _keyId;
|
||
|
|
private readonly RSA _rsa;
|
||
|
|
|
||
|
|
public RsaJwtSignatureProvider(DekEncryptionService dekCryptor,
|
||
|
|
RealmSigningKey privateKey,
|
||
|
|
JwtSigAlgName sigAlgName)
|
||
|
|
{
|
||
|
|
_sigAlgName = sigAlgName;
|
||
|
|
_keyId = privateKey.Id;
|
||
|
|
|
||
|
|
byte[] key = dekCryptor.Decrypt(privateKey.Key);
|
||
|
|
_rsa = RSA.Create();
|
||
|
|
_rsa.ImportPkcs8PrivateKey(key, out int _);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
+-------------------+---------------------------------+
|
||
|
|
| "alg" Param Value | Digital Signature Algorithm |
|
||
|
|
+-------------------+---------------------------------+
|
||
|
|
| RS256 | RSASSA-PKCS1-v1_5 using SHA-256 |
|
||
|
|
| RS384 | RSASSA-PKCS1-v1_5 using SHA-384 |
|
||
|
|
| RS512 | RSASSA-PKCS1-v1_5 using SHA-512 |
|
||
|
|
+-------------------+---------------------------------+
|
||
|
|
*/
|
||
|
|
|
||
|
|
|
||
|
|
public void WriteJwtHeaderFields(Utf8JsonWriter writer)
|
||
|
|
{
|
||
|
|
writer.WriteString("alg"u8, _sigAlgName.ToString());
|
||
|
|
writer.WriteString("kid"u8, _keyId.ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
public int GetSignatureLength()
|
||
|
|
{
|
||
|
|
return _rsa.KeySize / 8;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void CalculateSignature(ReadOnlySpan<byte> jwt, Span<byte> sig)
|
||
|
|
{
|
||
|
|
_rsa.SignData(jwt, sig, GetHashAlgorithmName(), RSASignaturePadding.Pkcs1);
|
||
|
|
}
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
_rsa.Dispose();
|
||
|
|
}
|
||
|
|
|
||
|
|
private HashAlgorithmName GetHashAlgorithmName()
|
||
|
|
=> _sigAlgName.Name switch
|
||
|
|
{
|
||
|
|
"RS256" => HashAlgorithmName.SHA256,
|
||
|
|
"RS384" => HashAlgorithmName.SHA384,
|
||
|
|
"RS512" => HashAlgorithmName.SHA512,
|
||
|
|
_ => throw new ArgumentException("Invalid algorithm for RsaJwtSignatureProvider")
|
||
|
|
};
|
||
|
|
|
||
|
|
}
|