johnsonroad.net

Quidquid latine dictum sit, altum sonatur.

Archive for the ‘Python’ Category

My landlord recently built storage lockers in our basement, and I dug through my junk drawer to find an old combination Master Lock to secure mine. I had forgotten the combination. Not to worry, as it’s not too hard to crack one if you have about 10 minutes to try up to 100 different combinations using this technique:

  1. Set the dial to 0.
  2. Pull up and maintain pressure as if you’re trying to open the lock.
  3. Let up just enough pressure to let the dial turn until it stops.
  4. Wiggle the dial back and forth. It will have one number’s-width of play in it, and it will either move from one whole number to the next or from one number’s half-position to the next number’s half-position. For example, it will move from 3.5 to 4.5. In that case the number we want is 4. Ignore positions where it “straddles” a half number, like if it moves between 3 and 4.
  5. There are 5 of these numbers. Write them down. All of them except one will end with the same digit, e.g.: 2, 12, 22, 27, 32. The one that doesn’t fit this pattern, 27 in this case, is the last number in the combination.

The first 60 seconds of this video demonstrates the technique to find the numbers:

This Python script makes it pretty quick to list the 100 possible combinations once you’ve isolated the last number using the above technique:

masterlock.py:

import sys
last = int(sys.argv[1])
remainder = last % 4
first = [remainder]
while first[-1] < 36:
first.append(first[-1] + 4)
if remainder == 0:
second = [2]
elif remainder == 1:
second = [3]
elif remainder == 2:
second = [0]
elif remainder == 3:
second = [1]
while second[-1] < 36:
second.append(second[-1] + 4)
for f in first:
for s in second:
print f, s, last

Just pass the script the last number in the combination, and it will spit out a list of all 100 possible combinations, like so:

python masterlock.py 7

Of course, this shows that combination Master Locks are really only secure if someone can’t spend 10 minutes messing around with your padlock without getting caught. And it means that if you have ten minutes, and something to write with and on, you can open someone else’s padlock. Don’t be a jerk.

I haven’t confirmed this, but I’ve heard that Master Lock redesigned their locks within the last couple years so that this trick doesn’t work anymore. My padlock was purchased before that.

I know that my padlock really isn’t protecting my stuff very well, but considering that the storage locker “walls” are made of chicken wire, the padlock isn’t the weak part of the system. The lock’s just there as a deterrent to keep my (hopefully) honest neighbors out of my stuff.

  • 2 Comments
  • Filed under: Good Ideas, Python
  • I used PyWin32 on a Django 0.96 instance after struggling and giving up on using python-ldap. This doesn’t query any of the AD user object’s attributes; it just lets them log in to the Django site and creates a Django user object for them.

    Thanks to Benji York for posting the code that talks to Active Directory using PyWin32 to the python mailing list.

    from django.conf import settings
    from django.contrib.auth.models import User, check_password
    from win32security import LogonUser, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT
    import pywintypes
    class ADBackend:
    """
    Authenticates against Active Directory.
    """
    def attempt_ad_login(self, username, password):
    try:
    handle=LogonUser(username, None, password,
    LOGON32_LOGON_NETWORK,
    LOGON32_PROVIDER_DEFAULT)
    # We're not going to use the handle, just seeing if we can get it.
    handle.Close()
    return True
    except pywintypes.error, e:
    # Because of the sheer number of Windows-specific errors that can
    # occur here, we have to assume any of them mean that the
    # credentials were not valid.
    return False
    def authenticate(self, username=None, password=None):
    if self.attempt_ad_login(username, password):
    try:
    user = User.objects.get(username=username)
    except User.DoesNotExist:
    # Create a new user. This password will not be checked during login, so it doesn't matter.
    user = User(username=username, password='dummy password')
    # Comment or uncomment these as appropriate.
    user.is_staff = True
    #user.is_superuser = True
    user.save()
    return user
    else:
    return None
    def get_user(self, user_id):
    try:
    return User.objects.get(pk=user_id)
    except User.DoesNotExist:
    return None

    Save this to a file such as “ADBackend.py” in the same path as your application, then add the following to your settings.py, replacing mysite and myapp to match your Django site and application:

    AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'mysite.myapp.ADBackend.ADBackend'
    )

  • 2 Comments
  • Filed under: Django, Python