private async Task <T> ParsePayload <T>(HttpRequestMessage message) { var accountKey = await Helper.LoadkeyV1(); var content = message.Content; Assert.Equal(JsonContentType, content.Headers.ContentType.MediaType); var json = await content.ReadAsStringAsync(); dynamic body = JObject.Parse(json); var protectedBase64 = body.GetValue("protected").Value; var protectedJson = Encoding.UTF8.GetString(JwsConvert.FromBase64String(protectedBase64)); dynamic @protected = JObject.Parse(protectedJson); Assert.Equal(string.Format(NonceFormat, this.nonce), @protected.nonce?.Value); var payloadBase64 = body.GetValue("payload").Value; var payloadJson = Encoding.UTF8.GetString(JwsConvert.FromBase64String(payloadBase64)); var signature = $"{protectedBase64}.{payloadBase64}"; var signatureBytes = Encoding.UTF8.GetBytes(signature); var signedSignatureBytes = accountKey.SignData(signatureBytes); var signedSignatureEncoded = JwsConvert.ToBase64String(signedSignatureBytes); Assert.Equal(signedSignatureEncoded, body.GetValue("signature").Value); return(JsonConvert.DeserializeObject <T>(payloadJson, JsonUtil.CreateSettings())); }
private async Task <T> ParsePayload <T>(HttpRequestMessage message) { var content = message.Content; Assert.Equal(JsonContentType, content.Headers.ContentType.MediaType); var json = await content.ReadAsStringAsync(); dynamic body = JObject.Parse(json); Assert.Equal("RS256", body.header?.alg?.Value); Assert.Equal("AQAB", body.header?.jwk?.e?.Value); Assert.Equal("RSA", body.header?.jwk?.kty?.Value); Assert.Equal("maeT6EsXTVHAdwuq3IlAl9uljXE5CnkRpr6uSw_Fk9nQshfZqKFdeZHkSBvIaLirE2ZidMEYy-rpS1O2j-viTG5U6bUSWo8aoeKoXwYfwbXNboEA-P4HgGCjD22XaXAkBHdhgyZ0UBX2z-jCx1smd7nucsi4h4RhC_2cEB1x_mE6XS5VlpvG91Hbcgml4cl0NZrWPtJ4DhFdPNUtQ8q3AYXkOr_OSFZgRKjesRaqfnSdJNABqlO_jEzAx0fgJfPZe1WlRWOfGRVBVopZ4_N5HpR_9lsNDzCZyidFsHwzvpkP6R6HbS8CMrNWgtkTbnz27EVqIhkYdiPVIN2Xkwj0BQ", body.header?.jwk?.n?.Value); var protectedBase64 = body.GetValue("protected").Value; var protectedJson = Encoding.UTF8.GetString(JwsConvert.FromBase64String(protectedBase64)); dynamic @protected = JObject.Parse(protectedJson); Assert.Equal(string.Format(NonceFormat, this.nonce), @protected.nonce?.Value); var payloadBase64 = body.GetValue("payload").Value; var payloadJson = Encoding.UTF8.GetString(JwsConvert.FromBase64String(payloadBase64)); var signature = $"{protectedBase64}.{payloadBase64}"; var signatureBytes = Encoding.ASCII.GetBytes(signature); var signedSignatureBytes = accountKey.SignData(signatureBytes); var signedSignatureEncoded = JwsConvert.ToBase64String(signedSignatureBytes); Assert.Equal(signedSignatureEncoded, body.GetValue("signature").Value); return(JsonConvert.DeserializeObject <T>(payloadJson, JsonUtil.CreateSettings())); }
/// <summary> /// Revokes the certificate. /// </summary> /// <param name="certificate">The certificate in DER format.</param> /// <param name="reason">The reason for revocation.</param> /// <param name="certificatePrivateKey">The certificate's private key.</param> /// <returns> /// The awaitable. /// </returns> public async Task RevokeCertificate(byte[] certificate, RevocationReason reason, IKey certificatePrivateKey) { var endpoint = await this.GetResourceUri(d => d.RevokeCert); var body = new CertificateRevocation { Certificate = JwsConvert.ToBase64String(certificate), Reason = reason }; JwsPayload payload; if (certificatePrivateKey != null) { var jws = new JwsSigner(certificatePrivateKey); payload = jws.Sign(body, url: endpoint, nonce: await HttpClient.ConsumeNonce()); } else { payload = await Sign(body, endpoint); } await HttpClient.Post <string>(endpoint, payload, true); }
private void ShowThumbprint(AcmeContext context) { var account = new AccountKey(context.Account.Key); var thumbprint = JwsConvert.ToBase64String(account.GenerateThumbprint()); ConsoleLogger.Info(thumbprint); }
/// <summary> /// Generates the value for DNS TXT record. /// </summary> /// <param name="key">The key.</param> /// <param name="token">The challenge token.</param> /// <returns></returns> public static string DnsTxt(this IKey key, string token) { var keyAuthz = key.KeyAuthorization(token); var hashed = DigestUtilities.CalculateDigest("SHA256", Encoding.UTF8.GetBytes(keyAuthz)); return(JwsConvert.ToBase64String(hashed)); }
private string GetChalangeDnsText(Account account, string token) { var key = GetChalangeKey(account, token); var hashed = Sha256HashProvider.ComputeHash(Encoding.UTF8.GetBytes(key)); return(JwsConvert.ToBase64String(hashed)); }
/// <summary> /// Encodes the specified entity for ACME requests. /// </summary> /// <param name="entity">The entity.</param> /// <param name="keyPair">The key pair.</param> /// <param name="nonce">The nonce.</param> /// <returns>The encoded JSON.</returns> private static object Encode(EntityBase entity, IAccountKey keyPair, string nonce) { var jsonSettings = JsonUtil.CreateSettings(); var unprotectedHeader = new { alg = keyPair.Algorithm.ToJwsAlgorithm(), jwk = keyPair.Jwk }; var protectedHeader = new { nonce = nonce }; var entityJson = JsonConvert.SerializeObject(entity, Formatting.None, jsonSettings); var protectedHeaderJson = JsonConvert.SerializeObject(protectedHeader, Formatting.None, jsonSettings); var payloadEncoded = JwsConvert.ToBase64String(Encoding.UTF8.GetBytes(entityJson)); var protectedHeaderEncoded = JwsConvert.ToBase64String(Encoding.UTF8.GetBytes(protectedHeaderJson)); var signature = $"{protectedHeaderEncoded}.{payloadEncoded}"; var signatureBytes = Encoding.ASCII.GetBytes(signature); var signedSignatureBytes = keyPair.SignData(signatureBytes); var signedSignatureEncoded = JwsConvert.ToBase64String(signedSignatureBytes); var body = new { header = unprotectedHeader, @protected = protectedHeaderEncoded, payload = payloadEncoded, signature = signedSignatureEncoded }; return(body); }
/// <summary> /// Computes the key authorization string for <paramref name="challenge"/>. /// </summary> /// <param name="challenge">The challenge.</param> /// <param name="key">The key.</param> /// <returns>The key authorization string.</returns> public static string ComputeKeyAuthorization(this Challenge challenge, IAccountKey key) { var jwkThumbprint = key.GenerateThumbprint(); var jwkThumbprintEncoded = JwsConvert.ToBase64String(jwkThumbprint); var token = challenge.Token; return($"{token}.{jwkThumbprintEncoded}"); }
/// <summary> /// Post to the new account endpoint. /// </summary> /// <param name="context">The ACME context.</param> /// <param name="body">The payload.</param> /// <param name="ensureSuccessStatusCode">if set to <c>true</c>, throw exception if the request failed.</param> /// <param name="eabKeyId">Optional key identifier, if using external account binding.</param> /// <param name="eabKey">Optional EAB key, if using external account binding.</param> /// <param name="eabKeyAlg">Optional EAB key algorithm, if using external account binding, defaults to HS256 if not specified</param> /// <returns>The ACME response.</returns> internal static async Task <AcmeHttpResponse <Account> > NewAccount( IAcmeContext context, Account body, bool ensureSuccessStatusCode, string eabKeyId = null, string eabKey = null, string eabKeyAlg = null) { var endpoint = await context.GetResourceUri(d => d.NewAccount); var jws = new JwsSigner(context.AccountKey); if (eabKeyId != null && eabKey != null) { var header = new { alg = eabKeyAlg?.ToUpper() ?? "HS256", kid = eabKeyId, url = endpoint }; var headerJson = Newtonsoft.Json.JsonConvert.SerializeObject(header, Newtonsoft.Json.Formatting.None, JsonUtil.CreateSettings()); var protectedHeaderBase64 = JwsConvert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(headerJson)); var accountKeyBase64 = JwsConvert.ToBase64String( System.Text.Encoding.UTF8.GetBytes( Newtonsoft.Json.JsonConvert.SerializeObject(context.AccountKey.JsonWebKey, Newtonsoft.Json.Formatting.None) ) ); var signingBytes = System.Text.Encoding.ASCII.GetBytes($"{protectedHeaderBase64}.{accountKeyBase64}"); // eab signature is the hash of the header and account key, using the eab key byte[] signatureHash; switch (header.alg) { case "HS512": using (var hs512 = new HMACSHA512(JwsConvert.FromBase64String(eabKey))) signatureHash = hs512.ComputeHash(signingBytes); break; case "HS384": using (var hs384 = new HMACSHA384(JwsConvert.FromBase64String(eabKey))) signatureHash = hs384.ComputeHash(signingBytes); break; default: using (var hs256 = new HMACSHA256(JwsConvert.FromBase64String(eabKey))) signatureHash = hs256.ComputeHash(signingBytes); break; } var signatureBase64 = JwsConvert.ToBase64String(signatureHash); body.ExternalAccountBinding = new { Protected = protectedHeaderBase64, Payload = accountKeyBase64, Signature = signatureBase64 }; } return(await context.HttpClient.Post <Account>(jws, endpoint, body, ensureSuccessStatusCode)); }
// //private async Task<Authorization> DeactivateChallengeAsync(Uri location) //{ // var auth = new Authorization { Status = AuthorizationStatus.Deactivated }; // var signedData = _jws.Sign(auth, location, location, Nonce); // return await PostAsync<Authorization>(location, signedData); //} private string GetChalangeKey(Account account, string token) { var jwkJson = JsonConvert.SerializeObject(account.Key.Jwk, Formatting.None, _jsonSettings); var jwkBytes = Encoding.UTF8.GetBytes(jwkJson); var jwkThumbprint = Sha256HashProvider.ComputeHash(jwkBytes); var jwkThumbprintEncoded = JwsConvert.ToBase64String(jwkThumbprint); return($"{token}.{jwkThumbprintEncoded}"); }
// Private Methods private RsaJsonWebKey ComposeJwk() { return(new RsaJsonWebKey { KeyType = KEY_TYPE, Exponent = JwsConvert.ToBase64String(Public.Exponent), Modulus = JwsConvert.ToBase64String(Public.Modulus) }); }
/// <summary> /// Creates a new certificate. /// </summary> /// <param name="csrBytes">The certificate signing request data.</param> /// <returns>The certificate issued.</returns> public async Task <AcmeCertificate> NewCertificate(byte[] csrBytes) { var payload = new Certificate { Csr = JwsConvert.ToBase64String(csrBytes), Resource = ResourceTypes.NewCertificate }; var uri = await this.handler.GetResourceUri(ResourceTypes.NewCertificate); var result = await this.handler.Post(uri, payload, key); ThrowIfError(result); byte[] pem; using (var buffer = new MemoryStream()) { pem = buffer.ToArray(); } var cert = new AcmeCertificate { Raw = result.Raw, Links = result.Links, Location = result.Location, ContentType = result.ContentType }; var currentCert = cert; while (true) { var upLink = currentCert.Links?.Where(l => l.Rel == "up").FirstOrDefault(); if (upLink == null) { break; } else { var issuerResult = await this.handler.Get <AcmeCertificate>(upLink.Uri); currentCert.Issuer = new AcmeCertificate { Raw = issuerResult.Raw, Links = issuerResult.Links, Location = issuerResult.Location, ContentType = issuerResult.ContentType }; currentCert = currentCert.Issuer; } } return(cert); }
public void CanGenerateDnsRecordValue() { var key = KeyFactory.NewKey(KeyAlgorithm.ES256); using (var sha256 = SHA256.Create()) { Assert.Equal( JwsConvert.ToBase64String(sha256.ComputeHash(Encoding.UTF8.GetBytes(key.KeyAuthorization("token")))), key.DnsTxt("token")); } }
/// <summary> /// Finalizes the certificate order. /// </summary> /// <param name="csr">The CSR in DER.</param> /// <returns> /// The order finalized. /// </returns> public async Task <Order> Finalize(byte[] csr) { var order = await Resource(); var payload = new Order.Payload { Csr = JwsConvert.ToBase64String(csr) }; var resp = await Context.HttpClient.Post <Order>(Context, order.Finalize, payload, true); return(resp.Resource); }
// Private Methods private async Task <Order> Finalize(Account account, Order order, byte[] cert) { var nonce = await GetNonceAsync(); var orderCert = new OrderCertificate() { Csr = JwsConvert.ToBase64String(cert) }; var signedData = account.Signer.Sign(orderCert, account.Location, order.Finalize, nonce); return(await PostAsync <Order>(order.Finalize, signedData)); }
/// <summary> /// Computes the DNS value for the <paramref name="challenge"/>. /// </summary> /// <param name="challenge">The challenge.</param> /// <param name="key">The key.</param> /// <returns>The value for the text DNS record.</returns> public static string ComputeDnsValue(this ChallengeEntity challenge, IAccountKey key) { var keyAuthString = challenge.ComputeKeyAuthorization(key); var keyAuthBytes = Encoding.UTF8.GetBytes(keyAuthString); var sha256 = new Sha256Digest(); var hashed = new byte[sha256.GetDigestSize()]; sha256.BlockUpdate(keyAuthBytes, 0, keyAuthBytes.Length); sha256.DoFinal(hashed, 0); var dnsValue = JwsConvert.ToBase64String(hashed); return(dnsValue); }
private string ComputeDnsValue(IChallengeContext challenge, IKey key) { // From Certes/Acme/Challenge.cs var keyAuthString = ComputeKeyAuthorization(challenge, key); var keyAuthBytes = Encoding.UTF8.GetBytes(keyAuthString); var sha256 = new Sha256Digest(); var hashed = new byte[sha256.GetDigestSize()]; sha256.BlockUpdate(keyAuthBytes, 0, keyAuthBytes.Length); sha256.DoFinal(hashed, 0); var dnsValue = JwsConvert.ToBase64String(hashed); return(dnsValue); }
public async Task RevokeCertificateAsync(Certificate certificate, RevocationReason reason = RevocationReason.Unspecified) { var certificateRevocation = new CertificateRevocation { Certificate = JwsConvert.ToBase64String(certificate.GetOriginalCertificate()), Reason = reason }; var directory = await GetDirectoryAsync(); var nonce = await GetNonceAsync(); var signedData = new JwsSigner(certificate.Key).Sign(certificateRevocation, url: directory.RevokeCert, nonce: nonce); var result = await PostAsync <Empty>(directory.RevokeCert, signedData); }
/// <summary> /// Revokes the certificate. /// </summary> /// <param name="certificate">The certificate.</param> /// <returns>The certificate revoked.</returns> public async Task <AcmeCertificate> RevokeCertificate(AcmeCertificate certificate) { var payload = new RevokeCertificate { Certificate = JwsConvert.ToBase64String(certificate.Raw), Resource = ResourceTypes.RevokeCertificate }; var uri = await this.handler.GetResourceUri(ResourceTypes.RevokeCertificate); var result = await this.handler.Post(uri, payload, key); ThrowIfError(result); certificate.Revoked = true; return(certificate); }
/// <summary> /// Revokes the certificate. /// </summary> /// <param name="certificate">The certificate in DER format.</param> /// <param name="reason">The reason for revocation.</param> /// <param name="certificatePrivateKey">The certificate's private key.</param> /// <returns> /// The awaitable. /// </returns> public async Task RevokeCertificate(byte[] certificate, RevocationReason reason, IKey certificatePrivateKey) { var endpoint = await this.GetResourceUri(d => d.RevokeCert); var body = new CertificateRevocation { Certificate = JwsConvert.ToBase64String(certificate), Reason = reason }; if (certificatePrivateKey != null) { var jws = new JwsSigner(certificatePrivateKey); await HttpClient.Post <string>(jws, endpoint, body, true); } else { await HttpClient.Post <string>(this, endpoint, body, true); } }
/// <summary> /// Generates the base64 encoded thumbprint for the given account <paramref name="key"/>. /// </summary> /// <param name="key">The account key.</param> /// <returns>The thumbprint.</returns> public static string Thumbprint(this IKey key) { var jwkThumbprint = key.GenerateThumbprint(); return(JwsConvert.ToBase64String(jwkThumbprint)); }