diff --git a/src/Agent/Agent.csproj b/src/Agent/Agent.csproj index 834b7aa..49c48b0 100644 --- a/src/Agent/Agent.csproj +++ b/src/Agent/Agent.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/LetsEncrypt/LetsEncrypt.csproj b/src/LetsEncrypt/LetsEncrypt.csproj index f73bee1..1ec2aa5 100644 --- a/src/LetsEncrypt/LetsEncrypt.csproj +++ b/src/LetsEncrypt/LetsEncrypt.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/LetsEncrypt/Models/Responses/SendResult.cs b/src/LetsEncrypt/Models/Responses/SendResult.cs index a083358..0442b3e 100644 --- a/src/LetsEncrypt/Models/Responses/SendResult.cs +++ b/src/LetsEncrypt/Models/Responses/SendResult.cs @@ -7,6 +7,5 @@ public string? ResponseText { get; set; } - - } + } } diff --git a/src/LetsEncrypt/Services/JwsService.cs b/src/LetsEncrypt/Services/JwsService.cs index 58d8069..165842d 100644 --- a/src/LetsEncrypt/Services/JwsService.cs +++ b/src/LetsEncrypt/Services/JwsService.cs @@ -3,14 +3,13 @@ * https://tools.ietf.org/html/rfc4648#section-5 */ -using System.Text; using System.Security.Cryptography; -using MaksIT.Core.Extensions; using MaksIT.LetsEncrypt.Entities.Jws; using MaksIT.Core.Security.JWK; using MaksIT.Core.Security.JWS; + namespace MaksIT.LetsEncrypt.Services; public interface IJwsService { @@ -28,72 +27,43 @@ public class JwsService : IJwsService { public JwsService(RSA rsa) { _rsa = rsa; - var publicParameters = rsa.ExportParameters(false); - - var exp = publicParameters.Exponent; - var mod = publicParameters.Modulus; - - _jwk = new Jwk() { - KeyType = JwkKeyType.Rsa.Name, - RsaExponent = Base64UrlUtility.Encode(exp), - RsaModulus = Base64UrlUtility.Encode(mod), - }; + if (!JwkGenerator.TryGenerateFromRSA(rsa, out _jwk, out var errorMessage)) { + throw new Exception(errorMessage); + } } public void SetKeyId(string location) { _jwk.KeyId = location; } - public JwsMessage Encode(ACMEJwsHeader protectedHeader) => + public JwsMessage Encode(ACMEJwsHeader protectedHeader) { + Encode(null, protectedHeader); - public JwsMessage Encode(T? payload, ACMEJwsHeader protectedHeader) { - - protectedHeader.Algorithm = JwkAlgorithm.Rs256.Name; - if (_jwk.KeyId != null) { - protectedHeader.KeyId = _jwk.KeyId; - } - else { - protectedHeader.Key = _jwk; + if (!JwsGenerator.TryEncode(_rsa, _jwk, protectedHeader, out var jwsMessage, out var errorMessage)) { + throw new Exception(errorMessage); } - var message = new JwsMessage { - Payload = "", - Protected = Base64UrlUtility.Encode(protectedHeader.ToJson()) - }; + return jwsMessage; - if (payload != null) { - if (payload is string stringPayload) - message.Payload = Base64UrlUtility.Encode(stringPayload); - else - message.Payload = Base64UrlUtility.Encode(payload.ToJson()); + } + + + public JwsMessage Encode(TPayload? payload, ACMEJwsHeader protectedHeader) { + + if (!JwsGenerator.TryEncode(_rsa, _jwk, protectedHeader, payload, out var jwsMessage, out var errorMessage)) { + throw new Exception(errorMessage); } - message.Signature = Base64UrlUtility.Encode( - _rsa.SignData(Encoding.ASCII.GetBytes($"{message.Protected}.{message.Payload}"), - HashAlgorithmName.SHA256, - RSASignaturePadding.Pkcs1)); + return jwsMessage; - return message; } - public string GetKeyAuthorization(string token) => - $"{token}.{GetSha256Thumbprint()}"; + public string GetKeyAuthorization(string token) { + if (!JwkThumbprintUtility.TryGetKeyAuthorization(_jwk, token, out var keyAuthorization, out var errorMessage)) + throw new Exception(errorMessage); + return keyAuthorization; - /// - /// For thumbprint calculation, always build the JSON string manually or use an anonymous object with the correct property order - /// - /// - private string GetSha256Thumbprint() { - - var thumbprint = new { - e = _jwk.RsaExponent, - kty = "RSA", - n = _jwk.RsaModulus - }; - - var json = thumbprint.ToJson(); - return Base64UrlUtility.Encode(SHA256.HashData(Encoding.UTF8.GetBytes(json))); } } diff --git a/src/LetsEncrypt/Services/LetsEncryptService.cs b/src/LetsEncrypt/Services/LetsEncryptService.cs index 7dfaaa9..73aced5 100644 --- a/src/LetsEncrypt/Services/LetsEncryptService.cs +++ b/src/LetsEncrypt/Services/LetsEncryptService.cs @@ -4,6 +4,7 @@ */ using MaksIT.Core.Extensions; +using MaksIT.Core.Security; using MaksIT.Core.Security.JWK; using MaksIT.LetsEncrypt.Entities; using MaksIT.LetsEncrypt.Entities.Jws; diff --git a/src/MaksIT.WebUI/public/certs-ui-logo-only.png b/src/MaksIT.WebUI/public/certs-ui-logo-only.png new file mode 100644 index 0000000..76df37c Binary files /dev/null and b/src/MaksIT.WebUI/public/certs-ui-logo-only.png differ diff --git a/src/MaksIT.WebUI/public/certs-ui-logo.png b/src/MaksIT.WebUI/public/certs-ui-logo.png new file mode 100644 index 0000000..800ce48 Binary files /dev/null and b/src/MaksIT.WebUI/public/certs-ui-logo.png differ diff --git a/src/MaksIT.WebUI/src/components/LoginScreen.tsx b/src/MaksIT.WebUI/src/components/LoginScreen.tsx index 8121577..28194e6 100644 --- a/src/MaksIT.WebUI/src/components/LoginScreen.tsx +++ b/src/MaksIT.WebUI/src/components/LoginScreen.tsx @@ -58,7 +58,7 @@ const LoginScreen: FC = () => {
{/* App logo and name above form */}
- {'App + {'CertsUI'} {import.meta.env.VITE_APP_TITLE}
{/* Form */} diff --git a/src/MaksIT.Webapi/MaksIT.Webapi.csproj b/src/MaksIT.Webapi/MaksIT.Webapi.csproj index 25876c2..18d7b12 100644 --- a/src/MaksIT.Webapi/MaksIT.Webapi.csproj +++ b/src/MaksIT.Webapi/MaksIT.Webapi.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/MaksIT.Webapi/Services/CertsFlowService.cs b/src/MaksIT.Webapi/Services/CertsFlowService.cs index 526139b..cc62017 100644 --- a/src/MaksIT.Webapi/Services/CertsFlowService.cs +++ b/src/MaksIT.Webapi/Services/CertsFlowService.cs @@ -175,31 +175,41 @@ public class CertsFlowService( var sessionResult = await ConfigureClientAsync(isStaging); if (!sessionResult.IsSuccess || sessionResult.Value == null) return sessionResult; + var sessionId = sessionResult.Value.Value; + var initResult = await InitAsync(sessionId, accountId, description, contacts); if (!initResult.IsSuccess || initResult.Value == null) return initResult.ToResultOfType(_ => null); + if (accountId == null) accountId = initResult.Value; + var challengesResult = await NewOrderAsync(sessionId, hostnames, challengeType); + if (!challengesResult.IsSuccess) return challengesResult.ToResultOfType(_ => null); + if (challengesResult.Value?.Count > 0) { var challengeResult = await CompleteChallengesAsync(sessionId); if (!challengeResult.IsSuccess) return challengeResult.ToResultOfType(default); } + var getOrderResult = await GetOrderAsync(sessionId, hostnames); if (!getOrderResult.IsSuccess) return getOrderResult.ToResultOfType(default); + var certsResult = await GetCertificatesAsync(sessionId, hostnames); if (!certsResult.IsSuccess) return certsResult.ToResultOfType(default); + if (!isStaging) { var applyCertsResult = await ApplyCertificatesAsync(accountId.Value); if (!applyCertsResult.IsSuccess) return applyCertsResult.ToResultOfType(_ => null); } + return Result.Ok(initResult.Value); } diff --git a/src/Models/MaksIT.Models.csproj b/src/Models/MaksIT.Models.csproj index 36b534b..d171089 100644 --- a/src/Models/MaksIT.Models.csproj +++ b/src/Models/MaksIT.Models.csproj @@ -11,7 +11,7 @@ - +