|
31 | 31 | from ipaddress import ip_address, ip_network |
32 | 32 | from flask import Flask, request, abort |
33 | 33 |
|
| 34 | +# Python prior to 2.7.7 does not have hmac.compare_digest |
| 35 | +if hexversion >= 0x020707F0: |
| 36 | + def constant_time_compare(val1, val2): |
| 37 | + return hmac.compare_digest(val1, val2) |
| 38 | +else: |
| 39 | + def constant_time_compare(val1, val2): |
| 40 | + if len(val1) != len(val2): |
| 41 | + return False |
| 42 | + result = 0 |
| 43 | + for x, y in zip(val1, val2): |
| 44 | + result |= ord(x) ^ ord(y) |
| 45 | + return result == 0 |
34 | 46 |
|
35 | 47 | application = Flask(__name__) |
36 | 48 |
|
@@ -84,16 +96,8 @@ def index(): |
84 | 96 | # HMAC requires the key to be bytes, but data is string |
85 | 97 | mac = hmac.new(str(secret), msg=request.data, digestmod='sha1') |
86 | 98 |
|
87 | | - # Python prior to 2.7.7 does not have hmac.compare_digest |
88 | | - if hexversion >= 0x020707F0: |
89 | | - if not hmac.compare_digest(str(mac.hexdigest()), str(signature)): |
90 | | - abort(403) |
91 | | - else: |
92 | | - # What compare_digest provides is protection against timing |
93 | | - # attacks; we can live without this protection for a web-based |
94 | | - # application |
95 | | - if not str(mac.hexdigest()) == str(signature): |
96 | | - abort(403) |
| 99 | + if not constant_time_compare(str(mac.hexdigest()), str(signature)): |
| 100 | + abort(403) |
97 | 101 |
|
98 | 102 | # Implement ping |
99 | 103 | event = request.headers.get('X-GitHub-Event', 'ping') |
|
0 commit comments