Проверка веб-перехватчика подписанного события SendGrid? - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь реализовать проверку по этой ссылке.

https://sendgrid.com/docs/for-developers/tracking-events/getting-started-event-webhook-security-features/#the -signed-event-webhook

Мне не нужна часть OAuth этого, но использовать ключ Publi c и заголовки для проверки данных. Я видел много сообщений, связанных с SendGrid Event Webhook, но ничего не проверял.

Это то, что я пытался, но что-то явно не так. Я действительно не знаю, как перевести код из документации на C#. Я не уверен, где должен быть каждый фрагмент данных из запроса go. Кто-нибудь знает об этом?

public async Task<IHttpActionResult> EventsHook()
{
    IEnumerable<string> signatureFromHeader = Request.Headers.GetValues("X-Twilio-Email-Event-Webhook-Signature");
    byte[] timeStampBytes = Encoding.ASCII.GetBytes(Request.Headers.GetValues("X-Twilio-Email-Event-Webhook-Timestamp").First());
    byte[] body = await Request.Content.ReadAsByteArrayAsync();
    byte[] payloadHash = timeStampBytes.Concat(body).ToArray();
    byte[] signatureByteArray = Convert.FromBase64String(signatureFromHeader.First());
    var publicKey = "{myPublicKey}";
    byte[] publicKeyBytes = Convert.FromBase64String(publicKey);

    var ecdsaParams = new ECParameters
    {
        D = publicKeyBytes
    };

    using (var ecdsa = ECDsa.Create(ecdsaParams))
    {
        if (ecdsa.VerifyData(payloadHash, signatureByteArray, HashAlgorithmName.SHA256))
        {
            return Ok();
        }
        return StatusCode(System.Net.HttpStatusCode.Forbidden);
    }
}

1 Ответ

0 голосов
/ 12 августа 2020

Я только что реализовал это и могу вам с этим помочь:

1 - Я использовал библиотеку starkbank-ecdsa для проверки подписи. 2- Я объявил этот интерфейс

public interface IEmailWebHookRequestValidator
{
    bool IsValidRequest([NotNull] HttpRequest request);
}

3- реализация этого интерфейса такова:

public class SendGridWebHookRequestValidator : IEmailWebHookRequestValidator
{
   private const string SIGNATURE_HEADER = "X-Twilio-Email-Event-Webhook-Signature";
   private const string TIMESTAMP_HEADER = "X-Twilio-Email-Event-Webhook-Timestamp";
    
   private readonly string _sendGridWebHookPublicKey;
    
   public SendGridWebHookRequestValidator(ISettingsProvider settingsProvider)
   {
      _sendGridWebHookPublicKey = settingsProvider.SendGridWebHookPublicKey //"public key that you can get from SendGrid website when you enable Event Webhook's signature";
   }
    
   public bool IsValidRequest([NotNull] HttpRequest request)
   {
      request.Headers.TryGetValue(SIGNATURE_HEADER, out var signatureHeaderValues);
      request.Headers.TryGetValue(TIMESTAMP_HEADER, out var timestampHeaderValues);
    
      var signature = signatureHeaderValues.FirstOrDefault();
      var timestamp = timestampHeaderValues.FirstOrDefault();
    
      if (string.IsNullOrWhiteSpace(signature) || string.IsNullOrWhiteSpace(timestamp))
      {
         return false;
      }
    
      var body = ReadStream(request.Body);
    
      return VerifySignature(_sendGridWebHookPublicKey, body, signature, timestamp);
   }
    

   public bool VerifySignature(string verificationKey, string payload, string signature, string timestamp)
   {
      var publicKey = PublicKey.fromPem(verificationKey);
    
      var timestampedPayload = timestamp + payload;
      var decodedSignature = Signature.fromBase64(signature);
    
      return Ecdsa.verify(timestampedPayload, decodedSignature, publicKey);
   }
    
   public static string ReadStream(Stream stream)
   {
       using var ms = new MemoryStream();
    
       stream.CopyTo(ms);
       return Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
   }
}

ISettingsProvider - это просто интерфейс, который помогает вам получить ключ publi c из настроек.

Приведенный выше код можно легко использовать, когда ваш веб-перехватчик получает httprequest, просто передав его методу IsValidRequest.

...