diff --git a/IPython/kernel/zmq/session.py b/IPython/kernel/zmq/session.py index 3d16169..1ebdf16 100644 --- a/IPython/kernel/zmq/session.py +++ b/IPython/kernel/zmq/session.py @@ -27,12 +27,20 @@ except: cPickle = None import pickle +try: + # We are using compare_digest to limit the surface of timing attacks + from hmac import compare_digest +except ImportError: + # Python < 2.7.7: When digests don't match no feedback is provided, + # limiting the surface of attack + def compare_digest(a,b): return a == b + import zmq from zmq.utils import jsonapi from zmq.eventloop.ioloop import IOLoop from zmq.eventloop.zmqstream import ZMQStream -from IPython.core.release import kernel_protocol_version, kernel_protocol_version_info +from IPython.core.release import kernel_protocol_version from IPython.config.configurable import Configurable, LoggingConfigurable from IPython.utils import io from IPython.utils.importstring import import_item @@ -216,7 +224,7 @@ class Session(Configurable): dict-based IPython message spec. The Session will handle serialization/deserialization, security, and metadata. - Sessions support configurable serialiization via packer/unpacker traits, + Sessions support configurable serialization via packer/unpacker traits, and signing with HMAC digests via the key/keyfile traits. Parameters @@ -524,7 +532,7 @@ class Session(Configurable): Parameters ---------- msg : dict or Message - The nexted message dict as returned by the self.msg method. + The next message dict as returned by the self.msg method. Returns ------- @@ -818,7 +826,7 @@ class Session(Configurable): raise ValueError("Duplicate Signature: %r" % signature) self._add_digest(signature) check = self.sign(msg_list[1:5]) - if not signature == check: + if not compare_digest(signature, check): raise ValueError("Invalid Signature: %r" % signature) if not len(msg_list) >= minlen: raise TypeError("malformed message, must have at least %i elements"%minlen)