Exemple #1
0
        public object SerializeSignedObject()
        {
            object token = null;

            if (Payload == null)
            {
                throw new ArgumentException("Payload must be set before the token can be created and signed.");
            }

            JWK    jwk = null;
            string kid = null;

            if (string.IsNullOrEmpty(_kid))
            {
                //Create the JWK
                jwk = new JWK()
                {
                    e   = Base64Tool.Encode(_rsaParameters.Exponent),
                    kty = "RSA",
                    n   = Base64Tool.Encode(_rsaParameters.Modulus)
                };
            }
            else
            {
                kid = _kid;
            }

            //Create the Protected Header
            PROTECTED @protected = new PROTECTED()
            {
                alg   = "RS256",
                jwk   = jwk,
                kid   = kid,
                nonce = _nonce,
                url   = _directory
            };

            //Encode jwk and payload
            string encodedProtected = Base64Tool.Encode(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(@protected, Formatting.None)));
            string encodedPayload   = Base64Tool.Encode(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Payload, Formatting.None)));

            //Sign Token
            string sigBase = $"{encodedProtected}.{encodedPayload}";

            byte[] sigBytes    = Encoding.ASCII.GetBytes(sigBase);
            byte[] signedBytes = _cryptoProvider.SignData(sigBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            string signature   = Base64Tool.Encode(signedBytes);

            token = new
            {
                @protected = encodedProtected,
                payload    = encodedPayload,
                signature  = signature
            };

            return(token);
        }
        private string GenerateCSR(AcmeAccount account, params string[] domainNames)
        {
            HashAlgorithmName hashName = HashAlgorithmName.SHA256;

            var builder = new SubjectAlternativeNameBuilder();

            foreach (var name in domainNames)
            {
                builder.AddDnsName(name);
            }

            RSA rsa = RSA.Create(4096);
            //rsa.ImportParameters(account.SecurityInfo);

            var dn  = new X500DistinguishedName($"CN={domainNames.First()}");
            var csr = new CertificateRequest(dn, rsa, hashName, RSASignaturePadding.Pkcs1);

            csr.CertificateExtensions.Add(builder.Build());

            return(Base64Tool.Encode(csr.CreateSigningRequest()));
        }
        public static string CreateAuthorizationKey(AcmeAccount account, string challengeToken)
        {
            string jwkThumbprint = string.Empty;

            //Compute the JWK Thumbprint
            var jwk = new
            {
                e   = Base64Tool.Encode(account.SecurityInfo.Exponent),
                kty = "RSA",
                n   = Base64Tool.Encode(account.SecurityInfo.Modulus)
            };

            string sjwk = JsonConvert.SerializeObject(jwk, Formatting.None);

            using (HashAlgorithm sha = SHA256.Create())
            {
                byte[] bjwk = Encoding.UTF8.GetBytes(sjwk);
                jwkThumbprint = Base64Tool.Encode(sha.ComputeHash(bjwk));
            }

            return($"{challengeToken}.{jwkThumbprint}");
        }
Exemple #4
0
        /// <summary>
        /// Changes and updates the account security info for an existing account.
        /// </summary>
        /// <param name="directory">Directory object.</param>
        /// <param name="nonce">Nonce</param>
        /// <param name="account">Must be existing account.</param>
        /// <returns>Return api response with status.</returns>
        /// <remarks>Will update the security info on the passed in account, so you will need to reserialize and update your existing account object to update the security info.</remarks>
        public async Task <AcmeApiResponse> RollOverAccountKeyAsync(AcmeDirectory directory, string nonce, AcmeAccount account)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }
            if (string.IsNullOrEmpty(directory.NewAccount))
            {
                throw new ArgumentException("directory is missing Account url.");
            }
            if (string.IsNullOrEmpty(nonce))
            {
                throw new ArgumentNullException("nonce");
            }
            if (account == null)
            {
                throw new ArgumentNullException("account");
            }

            RSACryptoServiceProvider cryptoProvider = new RSACryptoServiceProvider(2048);
            RSAParameters            rsaPrams       = cryptoProvider.ExportParameters(true);

            JwsContainer <ACCKEY> innerJwsObject = new JwsContainer <ACCKEY>(
                rsaPrams,
                nonce,
                directory.KeyChange,
                new ACCKEY()
            {
                account = account.KID,
                newKey  = new JWK()
                {
                    e   = Base64Tool.Encode(rsaPrams.Exponent),
                    kty = "RSA",
                    n   = Base64Tool.Encode(rsaPrams.Modulus)
                }
            });

            object signedInnerJwsObject = innerJwsObject.SerializeSignedObject();

            JwsContainer <object> outerJwsObject = new JwsContainer <object>(account.SecurityInfo, nonce, directory.KeyChange, account.KID, signedInnerJwsObject);

            string jwsToken = outerJwsObject.SerializeSignedToken();

            var apiResp = await SendPostData(
                url : directory.KeyChange,
                data : jwsToken);

            string apiRespString = await apiResp.Content?.ReadAsStringAsync();

            if (apiResp.StatusCode != HttpStatusCode.OK)
            {
                return(ErrorResponse(apiRespString));
            }

            if (!apiResp.Headers.TryGetValues(ProtoacmeContants.HEADER_NONCE, out IEnumerable <string> nonces))
            {
                return(ErrorResponse <AcmeAccount>("Missing Replay-Nonce Header on RolloverKey Response."));
            }

            account.SecurityInfo = rsaPrams;

            return(new AcmeApiResponse()
            {
                Status = AcmeApiResponseStatus.Success,
                Nonce = nonces.FirstOrDefault()
            });
        }