{ "metadata": { "name": "", "signature": "sha256:1d9252a691e4540d14fe065c0882321c174303755e599065246b2436fef55866" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "From [wikipedia](http://en.wikipedia.org/wiki/Luhn_algorithm):\n", "\n", ">It is not intended to be a cryptographically secure hash function; it was designed to protect against accidental errors, not malicious attacks. Most credit cards and many government identification numbers use the algorithm as a simple method of distinguishing valid numbers from mistyped or otherwise incorrect numbers." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def luhn_checksum(card_number):\n", " def digits_of(n):\n", " return [int(d) for d in str(n)]\n", " digits = digits_of(card_number)\n", " odd_digits = digits[-1::-2]\n", " even_digits = digits[-2::-2]\n", " checksum = 0\n", " checksum += sum(odd_digits)\n", " for d in even_digits:\n", " checksum += sum(digits_of(d*2))\n", " return checksum % 10" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "def is_luhn_valid(card_number):\n", " return luhn_checksum(card_number) == 0" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "code", "collapsed": false, "input": [ "def calculate_luhn(partial_card_number):\n", " check_digit = luhn_checksum(int(partial_card_number) * 10)\n", " return check_digit if check_digit == 0 else 10 - check_digit" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the random module, we can write a function that returns Luhn-valid numbers with a given amount of digits." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import random" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 4 }, { "cell_type": "code", "collapsed": false, "input": [ "def generate_card_number(number_of_digits):\n", " partial_card_number = int(\"\".join([str(random.randrange(10)) for i in range(number_of_digits - 1)]))\n", " checksum = calculate_luhn(partial_card_number)\n", " return int(str(partial_card_number) + str(checksum))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can try out that function on the previous `is_luhn_valid` method:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "generate_card_number(16)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "6979197319948772" ] } ], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "is_luhn_valid(4083102477600833 )" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "text": [ "True" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can also make a number of random tests of this sort." ] }, { "cell_type": "code", "collapsed": false, "input": [ "[is_luhn_valid(generate_card_number(16)) for i in range(10000)] == [True]*10000" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 8, "text": [ "True" ] } ], "prompt_number": 8 } ], "metadata": {} } ] }