Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ We welcome direct contributions to the sendgrid-python code base. Thank you!

- Python version 2.7, 3.5, 3.6, 3.7, or 3.8
- [python_http_client](https://github.com/sendgrid/python-http-client)
- [ecdsa_python](https://github.com/starkbank/ecdsa-python)
- [cryptography](https://github.com/pyca/cryptography)
- [pyenv](https://github.com/yyuu/pyenv)
- [tox](https://pypi.python.org/pypi/tox)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pip install sendgrid
## Dependencies

- [Python-HTTP-Client](https://github.com/sendgrid/python-http-client)
- [ECDSA-Python](https://github.com/starkbank/ecdsa-python)
- [Cryptography](https://github.com/pyca/cryptography)


<a name="quick-start"></a>
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Dependencies
------------

- `Python-HTTP-Client`_
- `ECDSA-Python`_
- `Cryptography`_

Quick Start
===========
Expand Down Expand Up @@ -259,7 +259,7 @@ License
.. _Twilio account: https://www.twilio.com/try-twilio?source=sendgrid-python
.. _SENDGRID_API_KEY: https://app.sendgrid.com/settings/api_keys
.. _Python-HTTP-Client: https://github.com/sendgrid/python-http-client
.. _ECDSA-Python: https://github.com/starkbank/ecdsa-python
.. _Cryptography: https://github.com/pyca/cryptography
.. _/mail/send Helper: https://github.com/sendgrid/sendgrid-python/tree/HEAD/sendgrid/helpers/mail
.. _personalization object: https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/personalizations.html
.. _Fluent Interface: https://sendgrid.com/blog/using-python-to-implement-a-fluent-interface-to-any-rest-api/
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Flask==3.1.0
PyYAML>=4.2b1
python-http-client>=3.2.1
six==1.17.0
ecdsa>=0.19.1,<1
cryptography>=45.0.6
more-itertools==5.0.0
21 changes: 11 additions & 10 deletions sendgrid/helpers/eventwebhook/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from ecdsa import VerifyingKey, BadSignatureError
from ecdsa.util import sigdecode_der
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_pem_public_key
import base64
import hashlib
from .eventwebhook_header import EventWebhookHeader

class EventWebhook:
Expand All @@ -20,15 +21,15 @@ def __init__(self, public_key=None):

def convert_public_key_to_ecdsa(self, public_key):
"""
Convert the public key string to a VerifyingKey object.
Convert the public key string to an EllipticCurvePublicKey object.

:param public_key: verification key under Mail Settings
:type public_key string
:return: VerifyingKey object using the ECDSA algorithm
:rtype VerifyingKey
:return: An EllipticCurvePublicKey object using the ECDSA algorithm
:rtype cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey
"""
pem_key = "-----BEGIN PUBLIC KEY-----\n" + public_key + "\n-----END PUBLIC KEY-----"
return VerifyingKey.from_pem(pem_key)
return load_pem_public_key(pem_key.encode("utf-8"))

def verify_signature(self, payload, signature, timestamp, public_key=None):
"""
Expand All @@ -41,15 +42,15 @@ def verify_signature(self, payload, signature, timestamp, public_key=None):
:param timestamp: value obtained from the 'X-Twilio-Email-Event-Webhook-Timestamp' header
:type timestamp: string
:param public_key: elliptic curve public key
:type public_key: VerifyingKey
:type public_key: cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey
:return: true or false if signature is valid
"""
timestamped_payload = (timestamp + payload).encode('utf-8')
decoded_signature = base64.b64decode(signature)

key = public_key or self.public_key
try:
key.verify(decoded_signature, timestamped_payload, hashfunc=hashlib.sha256, sigdecode=sigdecode_der)
key.verify(decoded_signature, timestamped_payload, ec.ECDSA(hashes.SHA256()))
return True
except BadSignatureError:
except InvalidSignature:
return False
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
def getRequires():
deps = [
'python_http_client>=3.2.1',
'ecdsa>=0.19.1,<1',
'cryptography>=45.0.6',
"werkzeug>=0.11.15,<1.0.0 ; python_version < '3.0'",
"werkzeug>=0.15.0,<2.0.0 ; python_version >= '3.0' and python_version < '3.7'",
"werkzeug>=0.15.0,<2.3.0 ; python_version >= '3.0' and python_version < '3.8'", # version 2.3.0 dropped support for Python 3.7
Expand Down