Source code for stoqlib.lib.algorithms

# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4

##
## Copyright (C) 2012 Async Open Source <http://www.async.com.br>
## All rights reserved
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., or visit: http://www.gnu.org/.
##
## Author(s): Stoq Team <stoq-devel@async.com.br>
##


# http://en.wikipedia.org/wiki/Luhn algorithm
# Also known as mod 10
[docs]def luhn(value): if not isinstance(value, basestring): raise TypeError("value must be a string, not %s" % ( value, )) total = 0 try: values = map(int, reversed(value)) except ValueError: return None for i, v in enumerate(values): if not i % 2: v *= 2 if v > 10: v -= 9 total += v return str(10 - total % 10)
# FIXME: These are used for boleto generation code and should # be replaced and/or merged
[docs]def modulo10(num): soma = 0 peso = 2 for i in range(len(num) - 1, -1, -1): parcial = int(num[i]) * peso if parcial > 9: s = "%d" % parcial parcial = int(s[0]) + int(s[1]) soma += parcial if peso == 2: peso = 1 else: peso = 2 resto10 = soma % 10 if resto10 == 0: valor = 0 else: valor = 10 - resto10 return valor
[docs]def modulo11(num, base=9, r=0): soma = 0 fator = 2 for i in range(len(str(num))).__reversed__(): parcial10 = int(num[i]) * fator soma += parcial10 if fator == base: fator = 1 fator += 1 if r == 0: soma = soma * 10 digito = soma % 11 if digito == 10: digito = 0 return digito if r == 1: resto = soma % 11 return resto
# From http://tinyurl.com/lu88m7g
[docs]def calculaDuploDigito(seisPrimeirosCamposConcatenados): def sum11(s, lmin, lmax): soma = 0 peso = lmin for c in reversed(s): soma += peso * int(c) peso += 1 if peso > lmax: peso = lmin return soma primeiroDV = modulo10(seisPrimeirosCamposConcatenados) somaMod11 = sum11( seisPrimeirosCamposConcatenados + str(primeiroDV), 2, 7) restoMod11 = calculeRestoMod11(somaMod11) while restoMod11 == 1: primeiroDV = encontreValorValidoParaPrimeiroDV(primeiroDV) somaMod11 = sum11( seisPrimeirosCamposConcatenados + str(primeiroDV), 2, 7) restoMod11 = calculeRestoMod11(somaMod11) segundoDV = calculeSegundoDV(restoMod11) return str(primeiroDV) + str(segundoDV)
[docs]def calculeSegundoDV(restoMod11): if restoMod11 == 0: return restoMod11 else: return 11 - restoMod11
[docs]def calculePrimeiroDV(restoMod10): if restoMod10 == 0: return 0 else: return 10 - restoMod10
[docs]def calculeRestoMod10(somaMod10): if somaMod10 < 10: return somaMod10 else: return somaMod10 % 10
[docs]def encontreValorValidoParaPrimeiroDV(primeiroDV): if primeiroDV == 9: return 0 else: return primeiroDV + 1
[docs]def calculeRestoMod11(somaMod11): if somaMod11 < 11: return somaMod11 else: return somaMod11 % 11
[docs]class PasswordObfuscator(object): """Password obfuscator Holds a password obfuscated in-memory to avoid any accidental leak. """ _key_mask = [ord(c) for c in '44NLGVlI4q3kHUqBq2RCKU09hVD9USGm'] def __init__(self, password=None): self.hashed_password = None self.password = password @property def password(self): if self.hashed_password is None: return None return self._obfuscate(self.hashed_password).decode('utf-8') @password.setter def password(self, password): if password is None: self.hashed_password = None return if isinstance(password, unicode): password = password.encode('utf-8') self.hashed_password = self._obfuscate(password) def _obfuscate(self, s): # Based on http://stackoverflow.com/a/7489718/6476179 mask = self._key_mask lmask = len(self._key_mask) return ''.join(chr(ord(c) ^ mask[i % lmask]) for i, c in enumerate(s))
if __name__ == '__main__': # pragma nocover assert luhn('810907487') == '5'