Martin von Löwis avatar Martin von Löwis committed 4f46ce5

Drop M2Crypto dependency.

Comments (0)

Files changed (2)

 
 # This library implements OpenID Authentication 2.0,
 # in the role of a relying party
-# It has the following assumptions and limitations:
-# - service discovery requires YADIS (HTML discovery not implemented)
-# - only provider-directed mode (identifier_select) is supported
-# - direct requests require https
-# - as a signature algorithm, HMAC-SHA1 is requested
 
 import urlparse, urllib, httplib, BeautifulSoup, time
-import cStringIO, base64, hmac, sha, datetime, re, binascii, struct
-import itertools
+import cStringIO, base64, hmac, sha, datetime, re, random
+import itertools, cPickle
 
 try:
     from xml.etree import ElementTree
             return True
     return False
 
-# OpenSSL MPI integer representation
-def bin2mpi(bin):
-    if ord(bin[0]) >= 128:
-        # avoid interpretation as a negative number
-        bin = "\x00" + bin
-    return struct.pack(">i", len(bin))+bin
-def mpi2bin(mpi):
-    assert len(mpi)-4 == struct.unpack(">i", mpi[:4])[0]
-    return mpi[4:]
+# 4.1.3: Binary two's complement
+def btwoc(l):
+    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' 
+    # btwoc ought to produce the shortest representation in two's
+    # complement. Fortunately, pickle already does that.
+    return res[3+ord(res[3]):3:-1]
+
+def unbtwoc(b):
+    return cPickle.loads('\x80\x02\x8a'+chr(len(b))+b[::-1]+'.')
 
 # Appendix B; DH default prime
 dh_prime = """
 7D45C2E7E52DC81C7A171876E5CEA74B1448BFDFAF18828EFD2519F14E45E382
 6634AF1949E5B535CC829A483B8A76223E5D490A257F05BDFF16F2FB22C583AB
 """
-dh_prime = binascii.unhexlify("".join(dh_prime.split()))
-# OpenSSL MPI representation: dh_prime, 2
-dh = DH.set_params(bin2mpi(dh_prime), '\x00\x00\x00\x01\x02')
-dh.gen_key()
-dh_public_base64 = base64.b64encode(mpi2bin(dh.pub))
+dh_prime = long("".join(dh_prime.split()), 16)
 
 def string_xor(s1, s2):
     res = []
         'openid.assoc_type':"HMAC-SHA1",
         'openid.session_type':"no-encryption",
         }
-    if url.startswith('http:'):
+    if 1 or url.startswith('http:'):
         # Use DH exchange
         data['openid.session_type'] = "DH-SHA1"
+        # Private key: random number between 1 and dh_prime-1
+        priv = random.randrange(1, dh_prime-1)
+        # Public key: 2^priv mod prime
+        pubkey = pow(2L, priv, dh_prime)
+        dh_public_base64 = base64.b64encode(btwoc(pubkey))
         # No need to send key and generator
         data['openid.dh_consumer_public'] = dh_public_base64
     if is_compat_1x(services):
     data = parse_response(res.read())
     if 'error' in data:
         raise ValueError, "associate failed: "+data['error']
-    if url.startswith('http:'):
+    if 1 or url.startswith('http:'):
         enc_mac_key = base64.b64decode(data['enc_mac_key'])
-        dh_server_public = base64.b64decode(data['dh_server_public'])
-        # compute_key does not return an MPI
-        shared_secret = dh.compute_key(bin2mpi(dh_server_public))
-        if ord(shared_secret[0]) >= 128:
-            # btwoc: add leading zero if number would otherwise be negative
-            shared_secret = '\x00' + shared_secret
+        dh_server_public = unbtwoc(base64.b64decode(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 = sha.new(shared_secret).digest()
         if len(shared_secret) != len(enc_mac_key):
             raise ValueError, "incorrect DH key size"
 providers = (
     ('Google', 'http://www.google.com/favicon.ico', 'https://www.google.com/accounts/o8/id'),
     ('Yahoo', 'http://www.yahoo.com/favicon.ico', 'http://yahoo.com/'),
-    # Verisigns service URL is not https
-    #('Verisign', 'https://pip.verisignlabs.com/favicon.ico', 'https://pip.verisignlabs.com')
+    ('Verisign', 'http://pip.verisignlabs.com/favicon.ico', 'http://pip.verisignlabs.com'),
     ('myOpenID', 'https://www.myopenid.com/favicon.ico', 'https://www.myopenid.com/'),
     ('Launchpad', 'https://login.launchpad.net/favicon.ico', 'https://login.launchpad.net/')
     )
 setup(name='openid2rp',
       version='1.0',
       description='OpenID 2.0 Relying Party Support Library',
-      author='Martin v. Löwis',
+      author='Martin v. Loewis',
       author_email='martin@v.loewis.de',
       long_description=open('README').read(),
       py_modules=['openid2rp'],
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.