commit 437f816fea14565a34cb9377e665c599d01b4a53 Author: Isis Lovecruft isis@torproject.org Date: Tue Mar 11 20:18:25 2014 +0000
Move HMAC and HMACfunction creators to bridgedb.crypto module.
* MOVE bridgedb.Bridges.get_hmac() → bridgedb.crypto.getHMAC() * MOVE bridgedb.Bridges.get_hmac_fn() → bridgedb.crypto.getHMACFunc() * CHANGE all other modules which use these functions to use the newer ones. --- lib/bridgedb/Bridges.py | 37 ++++++------------------------------- lib/bridgedb/Dist.py | 45 +++++++++++++++++++++------------------------ lib/bridgedb/Main.py | 6 +++--- lib/bridgedb/crypto.py | 27 +++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 58 deletions(-)
diff --git a/lib/bridgedb/Bridges.py b/lib/bridgedb/Bridges.py index cd77911..2293c78 100644 --- a/lib/bridgedb/Bridges.py +++ b/lib/bridgedb/Bridges.py @@ -7,7 +7,6 @@ them in rings.
import binascii import bisect -import hmac import logging import re import hashlib @@ -15,12 +14,12 @@ import socket import time import ipaddr import random -import hashlib
import bridgedb.Storage import bridgedb.Bucket import bridgedb.Util as Util
+from bridgedb.crypto import getHMACFunc from bridgedb.parse import addr from bridgedb.parse import networkstatus
@@ -32,8 +31,6 @@ except ImportError:
HEX_FP_LEN = 40 ID_LEN = 20 - -DIGESTMOD = hashlib.sha1 HEX_DIGEST_LEN = 40 DIGEST_LEN = 20 PORTSPEC_LEN = 16 @@ -87,28 +84,6 @@ def is_valid_fingerprint(fp): toHex = binascii.b2a_hex fromHex = binascii.a2b_hex
-def get_hmac(key, value): - """Return the hmac of **value** using the **key**.""" - h = hmac.new(key, value, digestmod=DIGESTMOD) - return h.digest() - -def get_hmac_fn(key, hex=True): - """Return a function that computes the hmac of its input using the key k. - - :param bool hex: If True, the output of the function will be hex-encoded. - :rtype: callable - :returns: A function which can be uses to generate HMACs. - """ - h = hmac.new(key, digestmod=DIGESTMOD) - def hmac_fn(value): - h_tmp = h.copy() - h_tmp.update(value) - if hex: - return h_tmp.hexdigest() - else: - return h_tmp.digest() - return hmac_fn - def chopString(s, size): """Generator. Given a string and a length, divide the string into pieces of no more than that length. @@ -216,7 +191,7 @@ class Bridge(object): """
if not request: request = 'default' - digest = get_hmac_fn('Order-Or-Addresses')(request) + digest = getHMACFunc('Order-Or-Addresses')(request) pos = long(digest[:8], 16) # lower 8 bytes -> long
# default address type @@ -847,7 +822,7 @@ class BridgeRing(BridgeHolder): """ self.bridges = {} self.bridgesByID = {} - self.hmac = get_hmac_fn(key, hex=False) + self.hmac = getHMACFunc(key, hex=False) self.isSorted = False self.sortedKeys = [] if answerParameters is None: @@ -1045,7 +1020,7 @@ class FixedBridgeSplitter(BridgeHolder): them to several sub-bridgeholders with equal probability. """ def __init__(self, key, rings): - self.hmac = get_hmac_fn(key, hex=True) + self.hmac = getHMACFunc(key, hex=True) self.rings = rings[:] for r in self.rings: assert(isinstance(r, BridgeHolder)) @@ -1123,7 +1098,7 @@ class BridgeSplitter(BridgeHolder): Bridge-to-bridgeholder associations are recorded in a store. """ def __init__(self, key): - self.hmac = get_hmac_fn(key, hex=True) + self.hmac = getHMACFunc(key, hex=True) self.ringsByName = {} self.totalP = 0 self.pValues = [] @@ -1230,7 +1205,7 @@ class FilteredBridgeSplitter(BridgeHolder): """ self.key = key self.filterRings = {} - self.hmac = get_hmac_fn(key, hex=True) + self.hmac = getHMACFunc(key, hex=True) self.bridges = [] self.distributorName = ''
diff --git a/lib/bridgedb/Dist.py b/lib/bridgedb/Dist.py index 6e9c436..9d3b06e 100644 --- a/lib/bridgedb/Dist.py +++ b/lib/bridgedb/Dist.py @@ -15,11 +15,14 @@ import re import time from ipaddr import IPv6Address, IPAddress
+from bridgedb.crypto import getHMAC +from bridgedb.crypto import getHMACFunc from bridgedb.Filters import filterAssignBridgesToRing from bridgedb.Filters import filterBridgesByRules from bridgedb.Filters import filterBridgesByIP4 from bridgedb.Filters import filterBridgesByIP6
+ def uniformMap(ip): """Map an IP to an arbitrary 'area' string, such that any two /24 addresses get the same string. @@ -137,11 +140,11 @@ class IPBasedDistributor(Distributor): for c in ipCategories: self.categories.append(c)
- key2 = bridgedb.Bridges.get_hmac(key, "Assign-Bridges-To-Rings") - key3 = bridgedb.Bridges.get_hmac(key, "Order-Areas-In-Rings") - self.areaOrderHmac = bridgedb.Bridges.get_hmac_fn(key3, hex=False) - key4 = bridgedb.Bridges.get_hmac(key, "Assign-Areas-To-Rings") - self.areaClusterHmac = bridgedb.Bridges.get_hmac_fn(key4, hex=True) + key2 = getHMAC(key, "Assign-Bridges-To-Rings") + key3 = getHMAC(key, "Order-Areas-In-Rings") + self.areaOrderHmac = getHMACFunc(key3, hex=False) + key4 = getHMAC(key, "Assign-Areas-To-Rings") + self.areaClusterHmac = getHMACFunc(key4, hex=True)
# add splitter and cache the default rings # plus leave room for dynamic filters @@ -170,9 +173,8 @@ class IPBasedDistributor(Distributor): if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring-%d" - % n) + key1 = getHMAC(self.splitter.key, + "Order-Bridges-In-Ring-%d" % n) n += 1 ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) ring.setName('{0} Ring'.format(self.name)) @@ -192,9 +194,8 @@ class IPBasedDistributor(Distributor): if filterFn: bridgeFilterRules.append(filterFn) ruleset = frozenset(bridgeFilterRules) - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring-%d" - % clusterNum) + key1 = getHMAC(self.splitter.key, + "Order-Bridges-In-Ring-%d" % clusterNum) ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, @@ -262,9 +263,8 @@ class IPBasedDistributor(Distributor): bridgeFilterRules.append(g) logging.info("category<%s>%s", epoch, Util.logSafely(area)) pos = self.areaOrderHmac("category<%s>%s" % (epoch, area)) - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring-%d" - % n) + key1 = getHMAC(self.splitter.key, + "Order-Bridges-In-Ring-%d" % n) break n += 1
@@ -281,9 +281,8 @@ class IPBasedDistributor(Distributor): clusterNum) bridgeFilterRules.append(g) pos = self.areaOrderHmac("<%s>%s" % (epoch, area)) - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring-%d" - % clusterNum) + key1 = getHMAC(self.splitter.key, + "Order-Bridges-In-Ring-%d" % clusterNum)
# try to find a cached copy ruleset = frozenset(bridgeFilterRules) @@ -425,10 +424,10 @@ class EmailBasedDistributor(Distributor): ## to their canonical forms. def __init__(self, key, domainmap, domainrules, answerParameters=None): - key1 = bridgedb.Bridges.get_hmac(key, "Map-Addresses-To-Ring") - self.emailHmac = bridgedb.Bridges.get_hmac_fn(key1, hex=False) + key1 = getHMAC(key, "Map-Addresses-To-Ring") + self.emailHmac = getHMACFunc(key1, hex=False)
- key2 = bridgedb.Bridges.get_hmac(key, "Order-Bridges-In-Ring") + key2 = getHMAC(key, "Order-Bridges-In-Ring") # XXXX clear the store when the period rolls over! self.domainmap = domainmap self.domainrules = domainrules @@ -506,8 +505,7 @@ class EmailBasedDistributor(Distributor): logging.debug("Cache miss %s" % ruleset)
# add new ring - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring") + key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring") ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) # debug log: cache miss self.splitter.addRing(ring, ruleset, @@ -544,8 +542,7 @@ class EmailBasedDistributor(Distributor): # populate all rings (for dumping assignments and testing) for filterFn in [filterBridgesByIP4, filterBridgesByIP6]: ruleset = frozenset([filterFn]) - key1 = bridgedb.Bridges.get_hmac(self.splitter.key, - "Order-Bridges-In-Ring") + key1 = getHMAC(self.splitter.key, "Order-Bridges-In-Ring") ring = bridgedb.Bridges.BridgeRing(key1, self.answerParameters) self.splitter.addRing(ring, ruleset, filterBridgesByRules([filterFn]), diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py index be8b1b0..e7dc153 100644 --- a/lib/bridgedb/Main.py +++ b/lib/bridgedb/Main.py @@ -410,7 +410,7 @@ def startup(options):
# Create a BridgeSplitter to assign the bridges to the different # distributors. - splitter = Bridges.BridgeSplitter(Bridges.get_hmac(key, "Splitter-Key")) + splitter = Bridges.BridgeSplitter(crypto.getHMAC(key, "Splitter-Key")) logging.debug("Created splitter: %r" % splitter)
# Create ring parameters. @@ -431,7 +431,7 @@ def startup(options): ipDistributor = Dist.IPBasedDistributor( Dist.uniformMap, config.N_IP_CLUSTERS, - Bridges.get_hmac(key, "HTTPS-IP-Dist-Key"), + crypto.getHMAC(key, "HTTPS-IP-Dist-Key"), categories, answerParameters=ringParams) splitter.addRing(ipDistributor, "https", config.HTTPS_SHARE) @@ -442,7 +442,7 @@ def startup(options): if config.EMAIL_DIST and config.EMAIL_SHARE: logging.debug("Setting up Email Distributor...") emailDistributor = Dist.EmailBasedDistributor( - Bridges.get_hmac(key, "Email-Dist-Key"), + crypto.getHMAC(key, "Email-Dist-Key"), config.EMAIL_DOMAIN_MAP.copy(), config.EMAIL_DOMAIN_RULES.copy(), answerParameters=ringParams) diff --git a/lib/bridgedb/crypto.py b/lib/bridgedb/crypto.py index d615489..054ec11 100644 --- a/lib/bridgedb/crypto.py +++ b/lib/bridgedb/crypto.py @@ -29,12 +29,17 @@ from __future__ import absolute_import from __future__ import unicode_literals
+import hashlib +import hmac import logging import os
import OpenSSL.rand
+#: The hash digest to use for HMACs. +DIGESTMOD = hashlib.sha1 + def getKey(filename): """Load the key stored in ``filename``, or create a new key.
@@ -74,3 +79,25 @@ def getKey(filename): key = fh.read() fh.close() return key + +def getHMAC(key, value): + """Return the HMAC of **value** using the **key**.""" + h = hmac.new(key, value, digestmod=DIGESTMOD) + return h.digest() + +def getHMACFunc(key, hex=True): + """Return a function that computes the HMAC of its input using the **key**. + + :param bool hex: If True, the output of the function will be hex-encoded. + :rtype: callable + :returns: A function which can be uses to generate HMACs. + """ + h = hmac.new(key, digestmod=DIGESTMOD) + def hmac_fn(value): + h_tmp = h.copy() + h_tmp.update(value) + if hex: + return h_tmp.hexdigest() + else: + return h_tmp.digest() + return hmac_fn
tor-commits@lists.torproject.org