Martin von Löwis avatar Martin von Löwis committed 1124a6a

Fix bytes vs. str issues for DH key exchange.

Comments (0)

Files changed (1)

openid2rp/__init__.py

 if sys.version_info < (3,):
     def b(s):
         return s
+    # Convert byte to integer
+    b2i = ord
+    def bytes_from_ints(L):
+        return ''.join([chr(i) for i in L])
 else:
     def b(s):
-        return s.encode('ascii')
+        return s.encode('latin-1')
+    def b2i(char):
+        # 3.x: bytes are already sequences of integers
+        return char
+    bytes_from_ints = bytes
 
 def normalize_uri(uri):
     """Normalize an uri according to OpenID section 7.2. Return a pair
     res = cPickle.dumps(l, 2)
     # Pickle result: proto 2, long1 (integer < 256 bytes)
     # number of bytes, little-endian integer, stop
-    assert res[:3] == '\x80\x02\x8a' 
+    assert res[:3] == b('\x80\x02\x8a')
     # btwoc ought to produce the shortest representation in two's
     # complement. Fortunately, pickle already does that.
-    return res[3+ord(res[3]):3:-1]
+    return res[3+b2i(res[3]):3:-1]
 
-def unbtwoc(b):
-    return cPickle.loads('\x80\x02\x8a'+chr(len(b))+b[::-1]+'.')
+def unbtwoc(B):
+    return cPickle.loads(b('\x80\x02\x8a')+bytes_from_ints([len(B)])+B[::-1]+(b'.'))
 
 # Appendix B; DH default prime
 dh_prime = """
 def string_xor(s1, s2):
     res = []
     for c1, c2 in itertools.izip(s1, s2):
-        res.append(chr(ord(c1) ^ ord(c2)))
-    return ''.join(res)
+        res.append(b2i(c1) ^ b2i(c2))
+    return bytes_from_ints(res)
 
 def associate(services, url):
     '''Create an association (OpenID section 8) between RP and OP.
     if 'error' in data:
         raise ValueError, "associate failed: "+data['error']
     if url.startswith('http:'):
-        enc_mac_key = data.get('enc_mac_key')
+        enc_mac_key = b(data.get('enc_mac_key'))
         if not enc_mac_key:
             raise ValueError, "Provider protocol error: not using DH-SHA1"
-        enc_mac_key = base64.b64decode(data['enc_mac_key'])
-        dh_server_public = unbtwoc(base64.b64decode(data['dh_server_public']))
+        enc_mac_key = base64.b64decode(enc_mac_key)
+        dh_server_public = unbtwoc(base64.b64decode(b(data['dh_server_public'])))
         # shared secret: sha1(2^(server_priv*priv) mod prime) xor enc_mac_key
         shared_secret = btwoc(pow(dh_server_public, priv, dh_prime))
         shared_secret = hashlib.sha1(shared_secret).digest()
         if len(shared_secret) != len(enc_mac_key):
             raise ValueError, "incorrect DH key size"
         # Fake mac_key result
-        data['mac_key'] = base64.b64encode(string_xor(enc_mac_key, shared_secret))
+        data['mac_key'] = b(base64.b64encode(string_xor(enc_mac_key, shared_secret)))
     return data
 
 class _AX:
         query.append(value)
     query = b('').join(query)
 
-    mac_key = base64.decodestring(b(session['mac_key']))
+    mac_key = base64.decodestring(session['mac_key'])
     transmitted_sig = base64.decodestring(b(response['openid.sig'][0]))
     computed_sig = hmac.new(mac_key, query, hashlib.sha1).digest()
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.