Archivi per la categoria python

RFC 4226 implementation in Python

24-03-2011 19:51:06 CET Postato in: nerdate, python | Commenta

Straight from RFC 4226, Appendix C:

import hmac
import hashlib
import struct

# Copyright (C) 2011, Matteo Panella. All rights reserved.
#
# This software is licensed under the same terms as the original
# Java reference code in RFC 4226.
#
# This is a work derived from OATH HOTP Algorithm.
#
# The author makes no representations concerning either
# the merchantability of this software or the suitability of this
# software for any particular purpose.
#
# It is provided "as is" without express or implied warranty
# of any kind and THE AUTHOR EXPRESSLY DISCLAIMS ANY
# WARRANTY OR LIABILITY OF ANY KIND relating to this software.
#
# These notices must be retained in any copies of any part of this
# documentation and/or software.

# Copyright notice for original Java code:
# Copyright (C) 2004, OATH.  All rights reserved.
#
# License to copy and use this software is granted provided that it
# is identified as the "OATH HOTP Algorithm" in all material
# mentioning or referencing this software or this function.
#
# License is also granted to make and use derivative works provided
# that such works are identified as
#  "derived from OATH HOTP algorithm"
# in all material mentioning or referencing the derived work.
#
# OATH (Open AuTHentication) and its members make no
# representations concerning either the merchantability of this
# software or the suitability of this software for any particular
# purpose.
#
# It is provided "as is" without express or implied warranty
# of any kind and OATH AND ITS MEMBERS EXPRESSaLY DISCLAIMS
# ANY WARRANTY OR LIABILITY OF ANY KIND relating to this software.
#
# These notices must be retained in any copies of any part of this
# documentation and/or software.

__all__ = ['hotp']

# Checksum algorithm defined in RFC4226
_doubleDigits = (0, 2, 4, 6, 8, 1, 3, 5, 7, 9)
def _calcChecksum(num, digits):
    doubleDigit = True
    total = 0
    while digits > 0:
        digits -= 1
        digit = num % 10
        num /= 10
        if doubleDigit:
            digit = _doubleDigits[digit]
        total += digit
        doubleDigit = not doubleDigit
    result = total % 10
    if result > 0:
        result = 10 - result
    return result

def hotp(secret, movingFactor, codeDigits=6, addChecksum=False, truncationOffset=None):
    """
    Perform RFC4226 HOTP generation from given secret (shared secret) and movingFactor.

    secret: the shared secret
    movingFactor: a counter, current time or other value that changes on a per-use basis (64 bit integer)
    codeDigits: number of digits in the OTP, not including the checksum (if any)
    addChecksum: True if a checksum digit should be appended to the OTP, False otherwise (default: False)
    truncationOffset: the offset into the MAC output to begin truncation. If this value is out of the
                      range 0 .. 15 or is None, then dynamic truncation will be used.
    Returns a numeric string in base 10 (the OTP).

    Test vectors (RFC4226, Appendix D):
    >>> hotp("12345678901234567890", 0)
    '755224'
    >>> hotp("12345678901234567890", 1)
    '287082'
    >>> hotp("12345678901234567890", 2)
    '359152'
    >>> hotp("12345678901234567890", 3)
    '969429'
    >>> hotp("12345678901234567890", 4)
    '338314'
    >>> hotp("12345678901234567890", 5)
    '254676'
    >>> hotp("12345678901234567890", 6)
    '287922'
    >>> hotp("12345678901234567890", 7)
    '162583'
    >>> hotp("12345678901234567890", 8)
    '399871'
    >>> hotp("12345678901234567890", 9)
    '520489'
    """
    digits = codeDigits + 1 if addChecksum else codeDigits
    movingFactor = struct.pack('!q', movingFactor)
    hs = hmac.new(secret, movingFactor, hashlib.sha1).digest()
    if truncationOffset is None or truncationOffset < 0 or truncationOffset > 15:
        # Perform dynamic truncation (per RFC4226)
        # The offset is taken from the lowest 4 bits of hs[19]
        truncationOffset = ord(hs[19]) & 0xf

    # Starting from the offset, 4 bytes are extracted and converted to an
    # unsigned 32 bit integer (big endian) and then masked with 7fffffff
    bin_code = struct.unpack('!I', hs[truncationOffset:truncationOffset+4])[0] & 0x7fffffff
    # OTP is the value modulo 10^codeDigits
    otp = bin_code % 10**codeDigits
    if addChecksum:
        otp = (otp * 10) + _calcChecksum(otp, codeDigits)
    result = '%d' % (otp,)
    return '0' * (len(result) - digits) + result

Dupefind

21-09-2009 02:12:25 CEST Postato in: nerdate, python | Commenta

Come promesso, ecco gli orrendi sorgenti dell'applicazione che ho usato per generare l'elenco dei codici fiscali duplicati (che non ho pubblicato - rompipalle sì, aspirante suicida ancora no) e il grafico "semianonimo" delle relazioni tra duplicati.

Riporto il contenuto del README per maggiore chiarezza:

*******************************************
* Graduatorie alloggi - Ricerca duplicati *
*******************************************

======= NOTA =======
I PDF contenenti gli elenchi sono stati scaricati da ilCapoluogo.it il
20-09-2009 tra le 15:40 e le 15:49, siete liberi di sostituirli con eventuali
elenchi aggiornati ma NON vi garantisco che questo coso continui a funzionare.
Se li sostituite, aggiornate il Makefile.

======= DISCLAIMER =======
I DATI PRODOTTI DA QUESTO SOFTWARE NON HANNO IL MINIMO VALORE LEGALE.
ZERO. NADA. NISBA.
Toglietevi subito dalla testa di usarlo per fare esposti, denunce o simili.
Ricontrollate SEMPRE *SEMPRE* _*SEMPRE*_ i dati prodotti dal software
confrontandoli manualmente con gli elenchi in PDF.
NON MI ASSUMO NESSUNA RESPONSABILITA` IN CASO DI DANNI A
PERSONE/COSE/ANIMALI/AMMINISTRATORI/COMMISSARI STRAORDINARI DERIVANTI DALL'USO
PROPRIO O IMPROPRIO DI QUESTO SOFTWARE.
Se il software tira fuori il vostro nome/codice fiscale: CAZZI VOSTRI!
Gli elenchi sono pubblici (Albo Pretorio del Comune) e nessuno vi ha accusato di
alcunche', risultate solo come duplicati nelle domande.
Se questo vi comporta noia - ripeto - CAZZI VOSTRI!

======= REQUISITI DI SISTEMA =======
  * Bash (cio` implica un sistema *NIX, non garantisco nulla per cygwin)
  * GNU Make
  * GNU Grep
  * Python >=2.5 ma NON 3.x
  * python-lxml
  * python-yapgvb
  * poppler (poppler-utils su debian/ubuntu)

======= UTILIZZO =======
Digitate 'make'. Tutto qui.
Otterrete due file interessanti:
  * duplicati.txt: l'elenco dei codici fiscali duplicati e relativi
    intestatari delle domande a cui appartengono;
  * duplicati.svg: il diagramma "semianonimo" con i grafi delle relazioni tra
    duplicati.

Se volete deanonimizzare il grafo, modificate duplicati.py.
Se non sapete come farlo, attaccatevi.

 -- 21 Sett. 2009, Matteo Panella

Graduatorie alloggi: un'analisi (molto) artigianale

20-09-2009 23:15:24 CEST Postato in: gente di un certo livello, nerdate, python, real life | Commenta

Di come vanno le cose per le C.A.S.E. e per i MAP - onestamente - non me ne dovrebbe fregare più di tanto, ho il garage agibile e vivrò lì finchè non avrò finito i lavori a casa. Però dopo aver letto le dichiarazioni di Fabio Pelini (PRC-SE), mi sono preso la briga di post-elaborare anche io le graduatorie (con un metodo complicato - prima o poi posterò il software che ho scritto e usato) "per vedere l'effetto che fa".

Intanto cominciamo subito con un paio di perle d'annata: il signor D'AL√≤ (sì, avete letto bene: "D'AL-RADICEQUADRATA-MINOREUGUALE") e un certo signor "MARTINELLI" privo di nome e con un codice fiscale che non ha nulla a che vedere con quel cognome.

Ma questo non è niente: il risultato di questa analisi artigianale è che su 23073 codici fiscali OTTANTASEI sono duplicati!

Ebbene sì, c'è gente che compare in più nuclei familiari, oppure ha presentato una domanda ma si trova nel nucleo familiare di un'altra domanda o addirittura ha presentato due domande. Il caso più eclatante è di due intestatari di una domanda, entrambi beneficiari di un alloggio presso le C.A.S.E.: uno figura nel nucleo familiare dell'altro e viceversa!

Non ci credete? Ho preparato un diagramma in SVG che illustra in forma di grafi i "duplicati" e le relazioni che intercorrono tra loro.

I rettangoli rappresentano gli intestatari delle domande, le ellissi le persone che figurano solo come componenti di nuclei, gli archi uscenti da un nodo indicano l'appartenenza al nucleo familiare di una domanda ed i colori indicano la graduatoria in cui è presente l'intestatario:

  1. Rosso → beneficiario C.A.S.E.
  2. Blu → beneficiario MAP
  3. Ciano → in attesa di collocazione
  4. Verde → non beneficiario

Nel caso di domande multiple, il colore indica la domanda con assegnazione "maggiore" (secondo l'ordine dell'elenco precedente). I rettangoli isolati non sono errori (domanda doppia), né i doppi archi tra due nodi (vuol dire essenzialmente che l'intestatario ha presentato due domande). Per scrupolo (leggasi: per evitare legnate), ho ritenuto opportuno sostituire i codici fiscali con una stringa semicasuale univoca.

Nel caso non abbiate un browser in grado di visualizzare SVG (aggiornatelo), è disponibile una versione ridotta in png.

"Buona" visione!

FNV-0 in Python

16-06-2008 23:09:48 CEST Postato in: nerdate, python | Commenta

Piccolo code snippet per estimatori del pitone.

def fnv_hash(data):
   """
    Returns a 32bit FNV-0 hash of the given string.

    >>> fnv_hash('3dcb910fb26bafb97e4a9660493afd9704536743')
    -1588890617L
    >>> fnv_hash('deb114355f8b912c4f7c7f0aceac7adceaa5db10')
    317390073L
    """
   h = long(0)
   for i in xrange(len(data)):
      h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)
      h ^= ord(data[i])
   # Everything after the 32th bit is meaningless
   h &= 0xffffffffL
   # Perform sign extension
   if h & 0x80000000L:
       h = -(~(h - 1) & 0xffffffffL)
   return h

I compagni di merende che masticano C avranno sicuramente storto il naso vedendo sia l'AND che l'estensione di segno fatta in quel modo becero, quindi precisiamo:

  • Python promuove automaticamente gli interi alla storage class superiore (ANCHE oltre i 64 bit) per evitare l'overflow, quindi solo i 32 bit inferiori contengono valori sensati;
  • per quanto appena esposto, l'estensione di segno non può essere effettuata con un banale OR (che promuoverebbe l'intero per conservare il segno!) ma è necessario fare ricorso alla definizione scolastica di complemento a 2.

The pasta theory of design

11-06-2008 15:50:58 CEST Postato in: nerdate, python | Commenta
  • Spaghetti: each piece of code interacts with every other piece of code [can be implemented with GOTO, functions, objects]
  • Lasagna: code has carefully designed layers. Each layer is, in theory independent. However low-level layers usually cannot be used easily, and high-level layers depend on low-level layers.
  • Ravioli: each part of the code is useful by itself. There is a thin layer of interfaces between various parts [the sauce]. Each part can be used elsewhere.
  • ...but sometimes, the user just wants to order Ravioli, so one coarse-grain easily definable layer of abstraction on top of it all can be useful.

(from Twisted Matrix documentation)