예제 #1
0
        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()));
        }
예제 #2
0
        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()));
        }
예제 #3
0
파일: AcmeContext.cs 프로젝트: sjkp/certes
        /// <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);
        }
예제 #4
0
        private void ShowThumbprint(AcmeContext context)
        {
            var account    = new AccountKey(context.Account.Key);
            var thumbprint = JwsConvert.ToBase64String(account.GenerateThumbprint());

            ConsoleLogger.Info(thumbprint);
        }
예제 #5
0
파일: IKey.cs 프로젝트: sjkp/certes
        /// <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));
        }
예제 #6
0
        private string GetChalangeDnsText(Account account, string token)
        {
            var key    = GetChalangeKey(account, token);
            var hashed = Sha256HashProvider.ComputeHash(Encoding.UTF8.GetBytes(key));

            return(JwsConvert.ToBase64String(hashed));
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <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}");
        }
예제 #9
0
        /// <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));
        }
예제 #10
0
        //

        //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}");
        }
예제 #11
0
        // Private Methods

        private RsaJsonWebKey ComposeJwk()
        {
            return(new RsaJsonWebKey
            {
                KeyType = KEY_TYPE,
                Exponent = JwsConvert.ToBase64String(Public.Exponent),
                Modulus = JwsConvert.ToBase64String(Public.Modulus)
            });
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
        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"));
            }
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
        // 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));
        }
예제 #16
0
        /// <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);
        }
예제 #17
0
        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);
        }
예제 #18
0
        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);
        }
예제 #19
0
        /// <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);
        }
예제 #20
0
        /// <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);
            }
        }
예제 #21
0
파일: IKey.cs 프로젝트: sjkp/certes
        /// <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));
        }