From e5f400749e1f01b90bfacb4de310454fb1bc30d8 Mon Sep 17 00:00:00 2001 From: Maksym Sadovnychyy Date: Wed, 12 Nov 2025 23:12:39 +0100 Subject: [PATCH] (refactor): jwk base64 encode core usage --- src/LetsEncrypt/Services/JwsService.cs | 30 ++++++------------- .../Services/LetsEncryptService.cs | 21 ++++++------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/LetsEncrypt/Services/JwsService.cs b/src/LetsEncrypt/Services/JwsService.cs index 266f014..97fdfb9 100644 --- a/src/LetsEncrypt/Services/JwsService.cs +++ b/src/LetsEncrypt/Services/JwsService.cs @@ -18,8 +18,6 @@ public interface IJwsService { JwsMessage Encode(ACMEJwsHeader protectedHeader); JwsMessage Encode(TPayload payload, ACMEJwsHeader protectedHeader); string GetKeyAuthorization(string token); - string Base64UrlEncoded(string s); - string Base64UrlEncoded(byte[] arg); } public class JwsService : IJwsService { @@ -36,9 +34,9 @@ public class JwsService : IJwsService { var mod = publicParameters.Modulus ?? throw new ArgumentNullException(nameof(publicParameters.Modulus)); _jwk = new Jwk() { - KeyType = "RSA", - RsaExponent = Base64UrlEncoded(exp), - RsaModulus = Base64UrlEncoded(mod), + KeyType = JwkKeyType.Rsa.Name, + RsaExponent = Base64UrlUtility.Encode(exp), + RsaModulus = Base64UrlUtility.Encode(mod), }; } @@ -51,7 +49,7 @@ public class JwsService : IJwsService { public JwsMessage Encode(T? payload, ACMEJwsHeader protectedHeader) { - protectedHeader.Algorithm = "RS256"; + protectedHeader.Algorithm = JwkAlgorithm.Rs256.Name; if (_jwk.KeyId != null) { protectedHeader.KeyId = _jwk.KeyId; } @@ -61,17 +59,17 @@ public class JwsService : IJwsService { var message = new JwsMessage { Payload = "", - Protected = Base64UrlEncoded(protectedHeader.ToJson()) + Protected = Base64UrlUtility.Encode(protectedHeader.ToJson()) }; if (payload != null) { if (payload is string stringPayload) - message.Payload = Base64UrlEncoded(stringPayload); + message.Payload = Base64UrlUtility.Encode(stringPayload); else - message.Payload = Base64UrlEncoded(payload.ToJson()); + message.Payload = Base64UrlUtility.Encode(payload.ToJson()); } - message.Signature = Base64UrlEncoded( + message.Signature = Base64UrlUtility.Encode( _rsa.SignData(Encoding.ASCII.GetBytes($"{message.Protected}.{message.Payload}"), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); @@ -91,16 +89,6 @@ public class JwsService : IJwsService { }; var json = "{\"e\":\"" + _jwk.RsaExponent + "\",\"kty\":\"RSA\",\"n\":\"" + _jwk.RsaModulus + "\"}"; - return Base64UrlEncoded(SHA256.HashData(Encoding.UTF8.GetBytes(json))); + return Base64UrlUtility.Encode(SHA256.HashData(Encoding.UTF8.GetBytes(json))); } - - public string Base64UrlEncoded(string s) => - Base64UrlEncoded(Encoding.UTF8.GetBytes(s)); - - // https://tools.ietf.org/html/rfc4648#section-5 - public string Base64UrlEncoded(byte[] bytes) => - Convert.ToBase64String(bytes) // Regular base64 encoder - .Split('=').First() // Remove any trailing '='s - .Replace('+', '-') // 62nd char of encoding - .Replace('/', '_'); // 63rd char of encoding } diff --git a/src/LetsEncrypt/Services/LetsEncryptService.cs b/src/LetsEncrypt/Services/LetsEncryptService.cs index eb81592..7dfaaa9 100644 --- a/src/LetsEncrypt/Services/LetsEncryptService.cs +++ b/src/LetsEncrypt/Services/LetsEncryptService.cs @@ -3,14 +3,8 @@ * https://datatracker.ietf.org/doc/html/draft-ietf-acme-acme-12 */ -using System.Text; -using System.Net.Http.Headers; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Logging; -using MaksIT.Results; using MaksIT.Core.Extensions; +using MaksIT.Core.Security.JWK; using MaksIT.LetsEncrypt.Entities; using MaksIT.LetsEncrypt.Entities.Jws; using MaksIT.LetsEncrypt.Entities.LetsEncrypt; @@ -18,6 +12,13 @@ using MaksIT.LetsEncrypt.Exceptions; using MaksIT.LetsEncrypt.Models.Interfaces; using MaksIT.LetsEncrypt.Models.Requests; using MaksIT.LetsEncrypt.Models.Responses; +using MaksIT.Results; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; +using System.Net.Http.Headers; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; namespace MaksIT.LetsEncrypt.Services; @@ -354,7 +355,7 @@ public class LetsEncryptService : ILetsEncryptService { case "dns-01": using (var sha256 = SHA256.Create()) { var dnsToken = state.JwsService != null - ? state.JwsService.Base64UrlEncoded(sha256.ComputeHash(Encoding.UTF8.GetBytes(keyToken ?? string.Empty))) + ? Base64UrlUtility.Encode(sha256.ComputeHash(Encoding.UTF8.GetBytes(keyToken ?? string.Empty))) : string.Empty; results[challengeResponse.Result?.Identifier?.Value ?? string.Empty] = dnsToken; @@ -482,7 +483,7 @@ public class LetsEncryptService : ILetsEncryptService { csr.CertificateExtensions.Add(san.Build()); var letsEncryptOrder = new FinalizeRequest { - Csr = state.JwsService!.Base64UrlEncoded(csr.CreateSigningRequest()) + Csr = Base64UrlUtility.Encode(csr.CreateSigningRequest()) }; Uri? certificateUrl = default; @@ -606,7 +607,7 @@ public class LetsEncryptService : ILetsEncryptService { var derEncodedCert = certificate.Export(X509ContentType.Cert); - var base64UrlEncodedCert = state.JwsService!.Base64UrlEncoded(derEncodedCert); + var base64UrlEncodedCert = Base64UrlUtility.Encode(derEncodedCert); var revokeRequest = new RevokeRequest { Certificate = base64UrlEncodedCert,