Ejemplo n.º 1
0
        /// <summary>
        /// MD5 hashes the specified body stream and compares it with the Content-MD5 string.
        /// </summary>
        /// <param name="contentMd5">The Content-MD5 string to compare the body hash to.</param>
        /// <param name="bodyContent">The body to hash and compare.</param>
        /// <returns><c>true</c> if equal; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentException">The body content stream does not support seeking or reading.</exception>
        public bool IsValidContentMd5(string contentMd5, Stream bodyContent)
        {
            if (bodyContent == null)
            {
                return(string.IsNullOrEmpty(contentMd5));
            }

            if (!bodyContent.CanSeek)
            {
                throw new ArgumentException("The body content stream does not support seeking.", nameof(bodyContent));
            }
            if (!bodyContent.CanRead)
            {
                throw new ArgumentException("The body content stream does not support reading.", nameof(bodyContent));
            }

            if (string.IsNullOrEmpty(contentMd5))
            {
                return(bodyContent.Length == 0);
            }

            string newContentMd5 = HmacSigner.CreateBase64Md5Hash(bodyContent);

            return(contentMd5 == newContentMd5);
        }
Ejemplo n.º 2
0
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true) || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), true))
            {
                return;
            }

            IHmacConfiguration configuration = _configurationManager.Get("Example");
            IHmacSigner        signer        = new HmacSigner(configuration, _keyRepository);
            IHmacValidator     validator     = new HmacValidator(configuration, signer);

            HmacValidationResult result = validator.ValidateHttpRequest(filterContext.HttpContext.Request);

            if (result.ResultCode == HmacValidationResultCode.Ok)
            {
                return;
            }

            HttpResponseBase response = filterContext.HttpContext.Response;

            validator.AddWwwAuthenticateHeader(response, configuration.AuthorizationScheme);
            response.Headers.Add("X-Auth-ErrorCode", result.ResultCode.ToString());
            response.StatusCode = (int)HttpStatusCode.Unauthorized;
            response.Write(result.ErrorMessage);
            response.End();
        }
Ejemplo n.º 3
0
        public void ShouldFailValidationDueToMissingKey()
        {
            // Arrange
            Mock <IHmacKeyRepository> mockKeyRepo = new Mock <IHmacKeyRepository>();

            mockKeyRepo.Setup(r => r.GetHmacKeyForUsername(It.IsAny <string>())).Returns((string)null);
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, mockKeyRepo.Object);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-3);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            HttpRequestBase    request        = CreateRequest(dateString);
            HmacSignatureData  signatureData  = signer.GetSignatureDataFromHttpRequest(request);

            signatureData.Key = "TestKey";
            string signature = signer.CreateSignature(signatureData);

            request.Headers[HmacConstants.AuthorizationHeaderName] = string.Format(
                HmacConstants.AuthorizationHeaderFormat,
                configuration.AuthorizationScheme,
                signature);

            // Act
            HmacValidationResult result = validator.ValidateHttpRequest(request);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ErrorMessage);
            Assert.AreEqual(result.ResultCode, HmacValidationResultCode.KeyMissing);
        }
Ejemplo n.º 4
0
        public void ShouldCreateCanonicalizedUriString()
        {
            // Arrange
            IHmacConfiguration configuration = new HmacConfiguration {
                SignatureEncoding = "UTF-8"
            };
            HmacSigner signer = new HmacSigner(configuration, _keyRepository);

            const string uriString         = "  HTTP://WWW.EXAMPLE.DOMAIN/Test?Key=Value  ";
            const string expectedUriString = "http://www.example.domain:80/Test?Key=Value";

            const string uriString2         = "  httpS://WWW.EXAMPLE.DOMAIN:3000/Test?Key=Value  ";
            const string expectedUriString2 = "https://www.example.domain:3000/Test?Key=Value";

            const string uriString3         = "  TEST://WWW.EXAMPLE.DOMAIN/Test?Key=Value  ";
            const string expectedUriString3 = "test://www.example.domain:-1/Test?Key=Value";

            const string relativeUriString = "/Test?Key=Value";
            Uri          relativeUri       = new Uri(relativeUriString, UriKind.Relative);

            // Act
            string result1 = signer.CreateCanonicalizedUriString(uriString);
            string result2 = signer.CreateCanonicalizedUriString(uriString2);
            string result3 = signer.CreateCanonicalizedUriString(uriString3);
            string result4 = signer.CreateCanonicalizedUriString(relativeUri);

            // Assert
            Assert.AreEqual(expectedUriString, result1);
            Assert.AreEqual(expectedUriString2, result2);
            Assert.AreEqual(expectedUriString3, result3);
            Assert.AreEqual(relativeUriString, result4);
        }
Ejemplo n.º 5
0
        public void ShouldCreateSignature()
        {
            // Arrange
            IHmacConfiguration configuration = CreateConfiguration();
            HmacSigner         signer        = new HmacSigner(configuration, _keyRepository);
            HmacSignatureData  signatureData = new HmacSignatureData
            {
                Key         = _keyRepository.Key,
                HttpMethod  = "POST",
                ContentMd5  = _base64Md5Hash,
                ContentType = ContentType,
                Date        = "Wed, 30 Dec 2015 12:30:45 GMT",
                Username    = _keyRepository.Username,
                RequestUri  = Url,
                Headers     = new NameValueCollection {
                    { "X-Custom-Test-Header-1", "Test1" }, { "X-Custom-Test-Header-2", "Test2" }
                }
            };
            const string expectedSignature = "CSDWHwt5sOWkBKS5mSNWrgJaXREQB6CKywVyB/A4IDQ65h3gzR9/Uutug34ikpcW3JlnVyAL+xbu/eNaq99q/Q==";

            HmacSignatureData signatureData2 = new HmacSignatureData {
                Key = _keyRepository.Key
            };
            const string expectedSignature2 = "QwPLzI1RUBRyYerrolY3+4Mzuw8Z07YfxnpP9va2ckH/I7UvdPBMkcaomWOaC5pZym9x+t/BA/2VTP6pjje1DQ==";

            // Act
            string signature  = signer.CreateSignature(signatureData);
            string signature2 = signer.CreateSignature(signatureData2);

            // Assert
            Assert.IsNotNull(signature);
            Assert.AreEqual(expectedSignature, signature);
            Assert.IsNotNull(signature2);
            Assert.AreEqual(expectedSignature2, signature2);
        }
Ejemplo n.º 6
0
        public void ShouldFailValidationDueToMissingDate()
        {
            // Arrange
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-3);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            HttpRequestBase    request        = CreateRequest(dateString);
            HmacSignatureData  signatureData  = signer.GetSignatureDataFromHttpRequest(request);
            string             signature      = signer.CreateSignature(signatureData);

            request.Headers[HmacConstants.AuthorizationHeaderName] = string.Format(
                HmacConstants.AuthorizationHeaderFormat,
                configuration.AuthorizationScheme,
                signature);

            request.Headers.Remove(HmacConstants.DateHeaderName);

            // Act
            HmacValidationResult result = validator.ValidateHttpRequest(request);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ErrorMessage);
            Assert.AreEqual(result.ResultCode, HmacValidationResultCode.DateMissing);
        }
Ejemplo n.º 7
0
        public void ShouldFailToValidateContentMd5()
        {
            // Arrange
            IHmacConfiguration configuration = CreateConfiguration();
            IHmacSigner        signer        = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator     = new HmacValidator(configuration, signer);

            const string incorrectBody = Body + "Modified";

            byte[] incorrectBodyBytes  = Encoding.UTF8.GetBytes(incorrectBody);
            Stream incorrectBodyStream = new MemoryStream(incorrectBodyBytes);

            // Act
            bool stringIsValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, incorrectBody, Encoding.UTF8);
            bool stringIsValidByteArray = validator.IsValidContentMd5(_md5Hash, incorrectBody, Encoding.UTF8);
            bool bytesAreValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, incorrectBodyBytes);
            bool bytesAreValidByteArray = validator.IsValidContentMd5(_md5Hash, incorrectBodyBytes);
            bool streamIsValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, incorrectBodyStream);
            bool streamIsValidByteArray = validator.IsValidContentMd5(_md5Hash, incorrectBodyStream);

            incorrectBodyStream.Dispose();

            // Assert
            Assert.IsFalse(stringIsValidBase64);
            Assert.IsFalse(stringIsValidByteArray);
            Assert.IsFalse(bytesAreValidBase64);
            Assert.IsFalse(bytesAreValidByteArray);
            Assert.IsFalse(streamIsValidBase64);
            Assert.IsFalse(streamIsValidByteArray);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Validates an entire HTTP request message.
        /// </summary>
        /// <param name="request">The HTTP request to validate.</param>
        /// <returns>The result of the validation as a <see cref="HmacValidationResult"/> object.</returns>
        /// <remarks>
        /// The following validation logic is used:
        /// - The Date header must be present if a maximum request age is configured, but cannot be older than the configured value;
        /// - The username header must be present when the user header name has been configured;
        /// - The key must be found for the request;
        /// - The Authorization header must be present, must have the correct authorization scheme and must contain a signature;
        /// - The signature created from the extracted signature data must match the one on the Authorization header.
        ///
        /// In case the request contains a body:
        /// - The Content-MD5 header value must match an MD5 hash of the body, if Content-MD5 validation was enabled in the configuration.
        /// </remarks>
        /// <exception cref="ArgumentNullException">The request is null.</exception>
        /// <exception cref="HmacConfigurationException">One or more of the configuration parameters are invalid.</exception>
        public virtual HmacValidationResult ValidateHttpRequest(HttpRequestMessage request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request), "The request cannot be null.");
            }

            HmacRequestWrapper requestWrapper = new HmacRequestWrapper(request);
            HmacSignatureData  signatureData  = HmacSigner.GetSignatureDataFromHttpRequest(request);

            return(ValidateHttpRequest(requestWrapper, signatureData));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// MD5 hashes the specified body byte array and compares it with the Content-MD5 string.
        /// </summary>
        /// <param name="contentMd5">The Content-MD5 string to compare the body hash to.</param>
        /// <param name="bodyContent">The body to hash and compare.</param>
        /// <returns><c>true</c> if equal; otherwise, <c>false</c>.</returns>
        public bool IsValidContentMd5(string contentMd5, byte[] bodyContent)
        {
            if (string.IsNullOrEmpty(contentMd5))
            {
                return(bodyContent.IsNullOrEmpty());
            }
            if (bodyContent.IsNullOrEmpty())
            {
                return(false);
            }

            string newContentMd5 = HmacSigner.CreateBase64Md5Hash(bodyContent);

            return(contentMd5 == newContentMd5);
        }
Ejemplo n.º 10
0
        public void ShouldSetAuthorizationHeader()
        {
            // Arrange
            const string       signature     = "TEST_SIGNATURE";
            IHmacConfiguration configuration = CreateConfiguration();
            HttpRequestBase    request       = CreateRequest(string.Empty);
            HmacSigner         signer        = new HmacSigner(configuration, _keyRepository);

            // Act
            signer.SetAuthorizationHeader(request, signature);
            string headerValue = request.Headers["Authorization"];

            // Assert
            Assert.IsNotNull(headerValue);
            Assert.AreEqual("HMAC TEST_SIGNATURE", headerValue);
        }
Ejemplo n.º 11
0
        public void ShouldAddWwwAuthenticateHeader()
        {
            // Arrange
            const string       headerValue   = "HMAC_TEST";
            IHmacConfiguration configuration = CreateConfiguration();
            HttpResponseBase   response      = CreateResponse(string.Empty);
            HmacSigner         signer        = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator     = new HmacValidator(configuration, signer);

            // Act
            validator.AddWwwAuthenticateHeader(response, headerValue);
            string actualHeaderValue = response.Headers["WWW-Authenticate"];

            // Assert
            Assert.IsNotNull(actualHeaderValue);
            Assert.AreEqual(headerValue, actualHeaderValue);
        }
Ejemplo n.º 12
0
        public void ShouldFailToValidateSignature()
        {
            // Arrange
            IHmacConfiguration configuration    = CreateConfiguration();
            IHmacSigner        signer           = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator        = new HmacValidator(configuration, signer);
            const string       signatureString1 = "SIGNATURE_STRING";
            const string       signatureString2 = "SIGNATURE_STRING_DIFFERENT";

            byte[] signatureBytes1 = Encoding.UTF8.GetBytes(signatureString1);
            byte[] signatureBytes2 = Encoding.UTF8.GetBytes(signatureString2);

            // Act
            bool isValidString    = validator.IsValidSignature(signatureString1, signatureString2);
            bool isValidByteArray = validator.IsValidSignature(signatureBytes1, signatureBytes2);

            // Assert
            Assert.IsFalse(isValidString);
            Assert.IsFalse(isValidByteArray);
        }
Ejemplo n.º 13
0
        public void ShouldFailToValidateRequestDate()
        {
            // Arrange
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-6);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            DateTime           dateTime       = dateTimeOffset.UtcDateTime;

            // Act
            bool isValidDateTimeOffset = validator.IsValidRequestDate(dateTimeOffset);
            bool isValidDateString     = validator.IsValidRequestDate(dateString, HmacConstants.DateHeaderFormat);
            bool isValidDateTime       = validator.IsValidRequestDate(dateTime);

            // Assert
            Assert.IsFalse(isValidDateString);
            Assert.IsFalse(isValidDateTime);
            Assert.IsFalse(isValidDateTimeOffset);
        }
Ejemplo n.º 14
0
        public void ShouldFailValidationDueToInvalidAuthorization()
        {
            // Arrange
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-3);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            HttpRequestBase    request        = CreateRequest(dateString);

            request.Headers[HmacConstants.AuthorizationHeaderName] = "blahblah";

            // Act
            HmacValidationResult result = validator.ValidateHttpRequest(request);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ErrorMessage);
            Assert.AreEqual(result.ResultCode, HmacValidationResultCode.AuthorizationInvalid);
        }
Ejemplo n.º 15
0
        public void ShouldCreateBase64Md5Hash()
        {
            // Arrange
            IHmacConfiguration configuration = new HmacConfiguration {
                SignatureEncoding = "UTF-8"
            };
            HmacSigner signer = new HmacSigner(configuration, _keyRepository);

            // Act
            string base64Md5HashFromString = signer.CreateBase64Md5Hash(Body, Encoding.UTF8);
            string base64Md5HashFromBytes  = signer.CreateBase64Md5Hash(_bodyBytes);
            string base64Md5HashFromStream = signer.CreateBase64Md5Hash(_bodyStream);

            // Assert
            Assert.IsNotNull(base64Md5HashFromString);
            Assert.AreEqual(_base64Md5Hash, base64Md5HashFromString);
            Assert.IsNotNull(base64Md5HashFromBytes);
            Assert.AreEqual(_base64Md5Hash, base64Md5HashFromBytes);
            Assert.IsNotNull(base64Md5HashFromStream);
            Assert.AreEqual(_base64Md5Hash, base64Md5HashFromStream);
        }
Ejemplo n.º 16
0
        public async Task PostWorkflowTest_DuplicateKeys_On_KeyData()
        {
            // Arrange
            var client = _Factory.CreateClient();

            await using var inputStream =
                            Assembly.GetExecutingAssembly().GetEmbeddedResourceStream("Resources.payload-duplicate-keys-keydata.json");
            var data      = inputStream.ToArray();
            var signature = HttpUtility.UrlEncode(HmacSigner.Sign(_Key, data));
            var content   = new ByteArrayContent(data);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            // Act
            var result = await client.PostAsync($"v1/postkeys?sig={signature}", content);

            // Assert
            var items = await _DbContext.TemporaryExposureKeys.ToListAsync();

            Assert.AreEqual(0, items.Count);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// MD5 hashes the specified body and compares it with the Content-MD5 string.
        /// </summary>
        /// <param name="contentMd5">The Content-MD5 string to compare the body hash to.</param>
        /// <param name="bodyContent">The body to hash and compare.</param>
        /// <param name="encoding">The encoding to use when converting the body content into bytes.</param>
        /// <returns><c>true</c> if equal; otherwise, <c>false</c>.</returns>
        /// <exception cref="ArgumentNullException">The encoding is null.</exception>
        public bool IsValidContentMd5(string contentMd5, string bodyContent, Encoding encoding)
        {
            if (encoding == null)
            {
                throw new ArgumentNullException(nameof(encoding), "The encoding cannot be null.");
            }

            if (string.IsNullOrEmpty(contentMd5))
            {
                return(string.IsNullOrEmpty(bodyContent));
            }

            if (string.IsNullOrEmpty(bodyContent))
            {
                return(false);
            }

            string newContentMd5 = HmacSigner.CreateBase64Md5Hash(bodyContent, encoding);

            return(contentMd5 == newContentMd5);
        }
Ejemplo n.º 18
0
        public async Task PostWorkflowTest_InvalidSignature()
        {
            // Arrange
            var client = _Factory.CreateClient();

            await using var inputStream =
                            Assembly.GetExecutingAssembly().GetEmbeddedResourceStream("Resources.payload.json");
            var data      = inputStream.ToArray();
            var signature = HttpUtility.UrlEncode(HmacSigner.Sign(new byte[] { 0 }, data));
            var content   = new ByteArrayContent(data);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            // Act
            var result = await client.PostAsync($"v1/postkeys?sig={signature}", content);

            // Assert
            var items = await _DbContext.TemporaryExposureKeys.ToListAsync();

            Assert.Equal(HttpStatusCode.OK, result.StatusCode);
            Assert.Empty(items);
        }
Ejemplo n.º 19
0
        public void ShouldCreateCanonicalizedHeaderString()
        {
            // Arrange
            IHmacConfiguration configuration = new HmacConfiguration {
                SignatureEncoding = "UTF-8", SignatureDataSeparator = "\n"
            };
            HmacSigner          signer  = new HmacSigner(configuration, _keyRepository);
            NameValueCollection headers = new NameValueCollection
            {
                { "  X-Test-Header-1 ", " Value2 " },
                { "  X-Test-Header-1 ", " Value4" },
                { "X-Test-Header-2", "value3" },
                { "  x-test-headeR-1 ", "Value1" }
            };
            const string expectedHeaderString = "x-test-header-1:Value2,Value4,Value1\nx-test-header-2:value3";

            // Act
            string headerString = signer.CreateCanonicalizedHeadersString(headers);

            // Assert
            Assert.IsNotNull(headerString);
            Assert.AreEqual(expectedHeaderString, headerString);
        }
Ejemplo n.º 20
0
        public void ShouldGetSignatureDataFromHttpRequest()
        {
            // Arrange
            IHmacConfiguration configuration = CreateConfiguration();
            string             dateString    = CreateHttpDateString();
            HttpRequestBase    request       = CreateRequest(dateString);
            HmacSigner         signer        = new HmacSigner(configuration, _keyRepository);

            // Act
            HmacSignatureData signatureData = signer.GetSignatureDataFromHttpRequest(request);

            // Assert
            Assert.IsNotNull(signatureData);
            Assert.AreEqual(_keyRepository.Key, signatureData.Key);
            Assert.AreEqual(request.HttpMethod, signatureData.HttpMethod);
            Assert.AreEqual(_base64Md5Hash, signatureData.ContentMd5);
            Assert.AreEqual(ContentType, signatureData.ContentType);
            Assert.AreEqual(dateString, signatureData.Date);
            Assert.AreEqual(_keyRepository.Username, signatureData.Username);
            Assert.AreEqual(Url, signatureData.RequestUri);
            Assert.IsNotNull(signatureData.Headers);
            Assert.IsTrue(signatureData.Headers.Count > 0);
        }
Ejemplo n.º 21
0
        public void ShouldValidateContentMd5()
        {
            // Arrange
            IHmacConfiguration configuration = CreateConfiguration();
            IHmacSigner        signer        = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator     = new HmacValidator(configuration, signer);

            // Act
            bool stringIsValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, Body, Encoding.UTF8);
            bool stringIsValidByteArray = validator.IsValidContentMd5(_md5Hash, Body, Encoding.UTF8);
            bool bytesAreValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, _bodyBytes);
            bool bytesAreValidByteArray = validator.IsValidContentMd5(_md5Hash, _bodyBytes);
            bool streamIsValidBase64    = validator.IsValidContentMd5(_base64Md5Hash, _bodyStream);
            bool streamIsValidByteArray = validator.IsValidContentMd5(_md5Hash, _bodyStream);

            // Assert
            Assert.IsTrue(stringIsValidBase64);
            Assert.IsTrue(stringIsValidByteArray);
            Assert.IsTrue(bytesAreValidBase64);
            Assert.IsTrue(bytesAreValidByteArray);
            Assert.IsTrue(streamIsValidBase64);
            Assert.IsTrue(streamIsValidByteArray);
        }
Ejemplo n.º 22
0
        public async Task PostWorkflowTest(string file, int keyCount, int mm, int dd)
        {
            _fakeTimeProvider.Value = new DateTime(2020, mm, dd, 0, 0, 0, DateTimeKind.Utc);

            // Arrange
            var client = _factory.CreateClient();

            await using var inputStream = Assembly.GetExecutingAssembly().GetEmbeddedResourceStream(file);
            var data = inputStream.ToArray();

            var args = new StandardJsonSerializer().Deserialize <PostTeksArgs>(Encoding.UTF8.GetString(data));

            await WriteBucket(Convert.FromBase64String(args.BucketId));

            var tekDates = args.Keys
                           .OrderBy(x => x.RollingStartNumber)
                           .Select(x => new { x, Date = x.RollingStartNumber.FromRollingStartNumber() });

            foreach (var i in tekDates)
            {
                Trace.WriteLine($"RSN:{i.x.RollingStartNumber} Date:{i.Date:yyyy-MM-dd}.");
            }

            var signature = HttpUtility.UrlEncode(HmacSigner.Sign(new byte[32], data));
            var content   = new ByteArrayContent(data);

            content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            // Act
            var result = await client.PostAsync($"v1/postkeys?sig={signature}", content);

            // Assert
            var items = await _workflowDbProvider.CreateNew().TemporaryExposureKeys.ToListAsync();

            Assert.Equal(HttpStatusCode.OK, result.StatusCode);
            Assert.Equal(keyCount, items.Count);
        }
Ejemplo n.º 23
0
        public void ShouldCreateMd5Hash()
        {
            // Arrange
            IHmacConfiguration configuration = new HmacConfiguration {
                SignatureEncoding = "UTF-8"
            };
            HmacSigner signer = new HmacSigner(configuration, _keyRepository);

            // Act
            byte[] md5HashFromString = signer.CreateMd5Hash(Body, Encoding.UTF8);
            byte[] md5HashFromBytes  = signer.CreateMd5Hash(_bodyBytes);
            byte[] md5HashFromStrean = signer.CreateMd5Hash(_bodyStream);

            // Assert
            Assert.IsNotNull(md5HashFromString);
            Assert.AreEqual(_md5Hash.Length, md5HashFromString.Length);
            Assert.IsTrue(_md5Hash.SequenceEqual(md5HashFromString));
            Assert.IsNotNull(md5HashFromBytes);
            Assert.AreEqual(_md5Hash.Length, md5HashFromBytes.Length);
            Assert.IsTrue(_md5Hash.SequenceEqual(md5HashFromBytes));
            Assert.IsNotNull(md5HashFromStrean);
            Assert.AreEqual(_md5Hash.Length, md5HashFromStrean.Length);
            Assert.IsTrue(_md5Hash.SequenceEqual(md5HashFromStrean));
        }
Ejemplo n.º 24
0
        private HmacValidationResult ValidateHttpRequest(HmacRequestWrapper request, HmacSignatureData signatureData)
        {
            if (string.IsNullOrEmpty(HmacConfiguration.AuthorizationScheme))
            {
                throw new HmacConfigurationException("The AuthorizationScheme cannot be null or empty.");
            }

            // Note: the Content-MD5 and Content-Type headers are only required if the request contains a body

            // If configured, the request date is validated to prevent replay attacks
            if (HmacConfiguration.MaxRequestAge.HasValue)
            {
                if (!request.Date.HasValue)
                {
                    return(new HmacValidationResult(HmacValidationResultCode.DateMissing, "The request date was not found."));
                }
                if (!IsValidRequestDate(request.Date.Value))
                {
                    return(new HmacValidationResult(HmacValidationResultCode.DateInvalid, "The request date is invalid."));
                }
            }

            // The username is always required when the header has been configured
            if (!string.IsNullOrEmpty(HmacConfiguration.UserHeaderName) && string.IsNullOrEmpty(signatureData.Username))
            {
                return(new HmacValidationResult(HmacValidationResultCode.UsernameMissing, "The username is required but was not found."));
            }

            // The key must be found
            if (string.IsNullOrEmpty(signatureData.Key))
            {
                return(new HmacValidationResult(HmacValidationResultCode.KeyMissing, "The key was not found."));
            }

            // If configured, an MD5 hash of the body is generated and compared with the Content-MD5 header value to check if the body hasn't been altered
            if (HmacConfiguration.ValidateContentMd5 && !IsValidContentMd5(signatureData.ContentMd5, request.Content))
            {
                if (string.IsNullOrEmpty(signatureData.ContentMd5))
                {
                    return(new HmacValidationResult(HmacValidationResultCode.BodyHashMissing, "The MD5 body hash was not found."));
                }
                return(new HmacValidationResult(HmacValidationResultCode.BodyHashMismatch, "The body content differs."));
            }

            // The Authorization header is always required and should contain the scheme and signature

            IList <string> authorizations = request.Headers.GetValues(HmacConstants.AuthorizationHeaderName);
            string         authorization;

            if (authorizations == null || string.IsNullOrEmpty(authorization = authorizations.FirstOrDefault()))
            {
                return(new HmacValidationResult(HmacValidationResultCode.AuthorizationMissing, "The signature was not found."));
            }

            string[] authorizationParts = authorization.Split(' ');

            if (authorizationParts.Length < 2 || authorizationParts[0] != HmacConfiguration.AuthorizationScheme)
            {
                return(new HmacValidationResult(HmacValidationResultCode.AuthorizationInvalid, "The signature was not correctly specified."));
            }

            // Finally, the signature from the Authorization header should match the newly created signature

            string signature = authorizationParts[1];

            string newSignature = HmacSigner.CreateSignature(signatureData);

            if (!IsValidSignature(signature, newSignature))
            {
                return(new HmacValidationResult(HmacValidationResultCode.SignatureMismatch, "The signature does not match."));
            }

            return(HmacValidationResult.Ok);
        }