/// <summary> /// Validate Message Bird Request /// </summary> /// <param name="content">Request Content</param> /// <param name="request">HTTP Request</param> /// <param name="messageBirdSigningKey">Message Bird Signing Key</param> /// <returns>True if there request is valid, false if there aren't.</returns> public static bool ValidateMessageBirdRequest(string content, HttpRequest request, string messageBirdSigningKey) { if (string.IsNullOrWhiteSpace(messageBirdSigningKey)) { throw new ArgumentNullException(nameof(messageBirdSigningKey)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (string.IsNullOrWhiteSpace(content)) { throw new ArgumentNullException(nameof(content)); } var messageBirdRequest = new MessageBirdRequest( request.Headers?["Messagebird-Request-Timestamp"], request.QueryString.Value?.Equals("?", StringComparison.CurrentCulture) != null ? string.Empty : request.QueryString.Value, GetBytes(content)); var messageBirdRequestSigner = new MessageBirdRequestSigner(GetBytes(messageBirdSigningKey)); string expectedSignature = request.Headers?["Messagebird-Signature"]; return(messageBirdRequestSigner.IsMatch(expectedSignature, messageBirdRequest)); }
/// <summary> /// Computes the signature for the provided request and determines whether /// it matches the expected signature(from the raw MessageBird-Signature header) /// </summary> /// <param name="encodedSignature">expectedSignature Signature from the MessageBird-Signature /// header in its original base64 encoded state</param> /// <param name="request">Request containing the values from the incoming web-hook.</param> /// <returns>True if the computed signature matches the expected signature</returns> public bool IsMatch(string encodedSignature, MessageBirdRequest request) { using (var base64Transform = new FromBase64Transform()) { var signatureBytes = Encoding.ASCII.GetBytes(encodedSignature); var decodedSignature = base64Transform.TransformFinalBlock(signatureBytes, 0, signatureBytes.Length); return(IsMatch(decodedSignature, request)); } }
/// <summary> /// Computes the signature for the provided request and determines whether it matches the expected signature /// </summary> /// <param name="expectedSignature">Decoded (with base64) signature from the MessageBird-Signature header</param> /// <param name="request">Request containing the values from the incoming web-hook</param> /// <returns>True if the computed signature matches the expected signature</returns> public bool IsMatch(byte[] expectedSignature, MessageBirdRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var actualSignature = ComputeSignature(request); return(expectedSignature.SequenceEqual(actualSignature)); }
/// <summary> /// Computes the signature for a request instance. /// </summary> /// <param name="request">Request to compute signature for</param> /// <returns>HMAC-SHA2556 signature for the provided request</returns> private IEnumerable <byte> ComputeSignature(MessageBirdRequest request) { var timestampAndQuery = request.Timestamp + '\n' + request.SortedQueryParameters() + '\n'; var timestampAndQueryBytes = Encoding.UTF8.GetBytes(timestampAndQuery); using (var sha256 = SHA256.Create()) { var bodyHashBytes = sha256.ComputeHash(request.Data); var signPayload = new byte[timestampAndQueryBytes.Length + bodyHashBytes.Length]; Array.Copy(timestampAndQueryBytes, signPayload, timestampAndQueryBytes.Length); Array.Copy(bodyHashBytes, 0, signPayload, timestampAndQueryBytes.Length, bodyHashBytes.Length); using (var hmacSha256 = new HMACSHA256(_signingKey)) { return(hmacSha256.ComputeHash(signPayload, 0, signPayload.Length)); } } }