Beispiel #1
0
        internal async Task ConfigureAcmeClient()
        {
            var httpClient = _proxyService.GetHttpClient();

            httpClient.BaseAddress = _settings.BaseUri;

            _log.Verbose("Loading ACME account signer...");
            IJwsTool?signer        = null;
            var      accountSigner = AccountSigner;

            if (accountSigner != null)
            {
                signer = accountSigner.JwsTool();
            }

            _log.Verbose("Constructing ACME protocol client...");
            try
            {
                _client = new AcmeProtocolClient(
                    httpClient,
                    signer: signer,
                    usePostAsGet: _settings.Acme.PostAsGet);
            }
            catch (CryptographicException)
            {
                if (signer == null)
                {
                    // There has been a problem generate a signer for the
                    // new account, possibly because some EC curve is not
                    // on available on the system? So we give it another
                    // shot with a less fancy RSA signer
                    _log.Verbose("First chance error generating new signer, retrying with RSA instead of ECC");
                    signer = new RSJwsTool
                    {
                        KeySize = _settings.Security.RSAKeyBits
                    };
                    signer.Init();
                    _client = new AcmeProtocolClient(
                        httpClient,
                        signer: signer,
                        usePostAsGet: _settings.Acme.PostAsGet);
                }
                else
                {
                    throw;
                }
            }
            _client.BeforeHttpSend = (x, r) => _log.Debug("Send {method} request to {uri}", r.Method, r.RequestUri);
            _client.AfterHttpSend  = (x, r) => _log.Verbose("Request completed with status {s}", r.StatusCode);
            _client.Directory      = await _client.GetDirectoryAsync();

            await _client.GetNonceAsync();

            _client.Account = await LoadAccount(_client, signer);

            if (_client.Account == null)
            {
                throw new Exception("AcmeClient was unable to find or create an account");
            }
        }
Beispiel #2
0
        public IJwsTool JwsTool()
        {
            if (KeyType.StartsWith("ES"))
            {
                var tool = new ESJwsTool
                {
                    HashSize = int.Parse(KeyType.Substring(2))
                };
                tool.Init();
                tool.Import(KeyExport);
                return(tool);
            }

            if (KeyType.StartsWith("RS"))
            {
                var tool = new RSJwsTool
                {
                    KeySize = int.Parse(KeyType.Substring(2))
                };
                tool.Init();
                tool.Import(KeyExport);
                return(tool);
            }

            throw new Exception($"Unknown or unsupported KeyType [{KeyType}]");
        }
Beispiel #3
0
        public void SerDesRSA()
        {
            var rng = RandomNumberGenerator.Create();

            for (var i = 0; i < 1000; i++)
            {
                var original = new RSJwsTool(); // Default for ISigner
                original.Init();
                var rawX = new byte[8034];
                rng.GetBytes(rawX);
                var sigX = original.Sign(rawX);

                var exported = original.Export();
                var copy     = new RSJwsTool();
                copy.Init();
                copy.Import(exported);
                var verified = copy.Verify(rawX, sigX);

                Assert.AreEqual(true, verified);
            }
        }
Beispiel #4
0
        internal AcmeProtocolClient PrepareClient(HttpClient httpClient, IJwsTool?signer)
        {
            AcmeProtocolClient?client = null;

            _log.Verbose("Constructing ACME protocol client...");
            try
            {
                client = new AcmeProtocolClient(
                    httpClient,
                    signer: signer,
                    usePostAsGet: _settings.Acme.PostAsGet);
            }
            catch (CryptographicException)
            {
                if (signer == null)
                {
                    // There has been a problem generate a signer for the
                    // new account, possibly because some EC curve is not
                    // on available on the system? So we give it another
                    // shot with a less fancy RSA signer
                    _log.Verbose("First chance error generating new signer, retrying with RSA instead of ECC");
                    signer = new RSJwsTool
                    {
                        KeySize = _settings.Security.RSAKeyBits
                    };
                    signer.Init();
                    client = new AcmeProtocolClient(
                        httpClient,
                        signer: signer,
                        usePostAsGet: _settings.Acme.PostAsGet);
                }
                else
                {
                    throw;
                }
            }
            client.BeforeHttpSend = (x, r) => _log.Debug("Send {method} request to {uri}", r.Method, r.RequestUri);
            client.AfterHttpSend  = (x, r) => _log.Verbose("Request completed with status {s}", r.StatusCode);
            return(client);
        }
        internal AcmeProtocolClient PrepareClient(HttpClient httpClient, IJwsTool?signer)
        {
            _log.Verbose("Constructing ACME protocol client...");
            AcmeProtocolClient?client;

            try
            {
                client = new AcmeProtocolClient(
                    httpClient,
                    signer: signer,
                    usePostAsGet: _settings.Acme.PostAsGet);
            }
            catch (CryptographicException)
            {
                if (signer == null)
                {
                    // There has been a problem generate a signer for the
                    // new account, possibly because some EC curve is not
                    // on available on the system? So we give it another
                    // shot with a less fancy RSA signer
                    _log.Verbose("First chance error generating new signer, retrying with RSA instead of ECC");
                    signer = new RSJwsTool
                    {
                        KeySize = _settings.Security.RSAKeyBits
                    };
                    signer.Init();
                    client = new AcmeProtocolClient(
                        httpClient,
                        signer: signer,
                        usePostAsGet: _settings.Acme.PostAsGet);
                }
                else
                {
                    throw;
                }
            }
            return(client);
        }
Beispiel #6
0
        void ValidateAccount(DbAccount acct, JwsSignedPayload signedPayload)
        {
            var ph  = ExtractProtectedHeader(signedPayload);
            var jwk = JsonConvert.DeserializeObject <Dictionary <string, string> >(acct.Jwk);

            if (string.IsNullOrEmpty(ph.Alg))
            {
                throw new Exception("invalid JWS header, missing 'alg'");
            }
            if (string.IsNullOrEmpty(ph.Url))
            {
                throw new Exception("invalid JWS header, missing 'url'");
            }
            if (string.IsNullOrEmpty(ph.Nonce))
            {
                throw new Exception("invalid JWS header, missing 'nonce'");
            }

            IJwsTool tool = null;

            switch (ph.Alg)
            {
            case "RS256":
                tool = new RSJwsTool {
                    HashSize = 256
                };
                ((RSJwsTool)tool).ImportJwk(acct.Jwk);
                break;

            case "RS384":
                tool = new RSJwsTool {
                    HashSize = 384
                };
                ((RSJwsTool)tool).ImportJwk(acct.Jwk);
                break;

            case "RS512":
                tool = new RSJwsTool {
                    HashSize = 512
                };
                ((RSJwsTool)tool).ImportJwk(acct.Jwk);
                break;

            case "ES256":
                tool = new ESJwsTool {
                    HashSize = 256
                };
                break;

            case "ES384":
                tool = new ESJwsTool {
                    HashSize = 384
                };
                break;

            case "ES512":
                tool = new ESJwsTool {
                    HashSize = 512
                };
                break;

            default:
                throw new Exception("unknown or unsupported signature algorithm");
            }

            var sig = CryptoHelper.Base64.UrlDecode(signedPayload.Signature);
            var pld = CryptoHelper.Base64.UrlDecode(signedPayload.Payload);
            var prt = CryptoHelper.Base64.UrlDecode(signedPayload.Protected);

            var sigInput      = $"{signedPayload.Protected}.{signedPayload.Payload}";
            var sigInputBytes = Encoding.ASCII.GetBytes(sigInput);

            if (!tool.Verify(sigInputBytes, sig))
            {
                throw new Exception("account signature failure");
            }
        }
Beispiel #7
0
        private async Task <bool> ConfigureAcmeClient()
        {
            var httpClientHandler = new HttpClientHandler()
            {
                Proxy = _proxyService.GetWebProxy(),
            };
            var httpClient = new HttpClient(httpClientHandler)
            {
                BaseAddress = new Uri(_arguments.MainArguments.GetBaseUri())
            };

            _log.Verbose("Loading ACME account signer...");
            IJwsTool signer        = null;
            var      accountSigner = AccountSigner;

            if (accountSigner != null)
            {
                signer = accountSigner.JwsTool();
            }

            _log.Verbose("Constructing ACME protocol client...");
            try
            {
                _client = new AcmeProtocolClient(httpClient, signer: signer);
            }
            catch (CryptographicException)
            {
                if (signer == null)
                {
                    // There has been a problem generate a signer for the
                    // new account, possibly because some EC curve is not
                    // on available on the system? So we give it another
                    // shot with a less fancy RSA signer
                    _log.Verbose("First chance error generating new signer, retrying with RSA instead of ECC");
                    signer = new RSJwsTool {
                        KeySize = new Rsa(_log, new RsaOptions()).GetRsaKeyBits()
                    };
                    signer.Init();
                    _client = new AcmeProtocolClient(httpClient, signer: signer);
                }
                else
                {
                    throw;
                }
            }
            _client.BeforeHttpSend = (x, r) =>
            {
                _log.Debug("Send {method} request to {uri}", r.Method, r.RequestUri);
            };
            _client.AfterHttpSend = (x, r) =>
            {
                _log.Verbose("Request completed with status {s}", r.StatusCode);
            };
            _client.Directory = await _client.GetDirectoryAsync();

            await _client.GetNonceAsync();

            _client.Account = await LoadAccount(signer);

            if (_client.Account == null)
            {
                throw new Exception("AcmeClient was unable to find or create an account");
            }
            return(true);
        }