mirror of
https://github.com/bringout/oca-ocb-security.git
synced 2026-04-24 17:02:07 +02:00
Initial commit: Security packages
This commit is contained in:
commit
bb469e4763
1399 changed files with 278378 additions and 0 deletions
56
odoo-bringout-oca-ocb-auth_totp/auth_totp/models/totp.py
Normal file
56
odoo-bringout-oca-ocb-auth_totp/auth_totp/models/totp.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import hmac
|
||||
import struct
|
||||
import time
|
||||
|
||||
# 160 bits, as recommended by HOTP RFC 4226, section 4, R6.
|
||||
# Google Auth uses 80 bits by default but supports 160.
|
||||
TOTP_SECRET_SIZE = 160
|
||||
|
||||
# The algorithm (and key URI format) allows customising these parameters but
|
||||
# google authenticator doesn't support it
|
||||
# https://github.com/google/google-authenticator/wiki/Key-Uri-Format
|
||||
ALGORITHM = 'sha1'
|
||||
DIGITS = 6
|
||||
TIMESTEP = 30
|
||||
|
||||
class TOTP:
|
||||
def __init__(self, key):
|
||||
self._key = key
|
||||
|
||||
def match(self, code, t=None, window=TIMESTEP, timestep=TIMESTEP):
|
||||
"""
|
||||
:param code: authenticator code to check against this key
|
||||
:param int t: current timestamp (seconds)
|
||||
:param int window: fuzz window to account for slow fingers, network
|
||||
latency, desynchronised clocks, ..., every code
|
||||
valid between t-window an t+window is considered
|
||||
valid
|
||||
"""
|
||||
if t is None:
|
||||
t = time.time()
|
||||
|
||||
low = int((t - window) / timestep)
|
||||
high = int((t + window) / timestep) + 1
|
||||
|
||||
return next((
|
||||
counter for counter in range(low, high)
|
||||
if hotp(self._key, counter) == code
|
||||
), None)
|
||||
|
||||
def hotp(secret, counter):
|
||||
# C is the 64b counter encoded in big-endian
|
||||
C = struct.pack(">Q", counter)
|
||||
mac = hmac.new(secret, msg=C, digestmod=ALGORITHM).digest()
|
||||
# the data offset is the last nibble of the hash
|
||||
offset = mac[-1] & 0xF
|
||||
# code is the 4 bytes at the offset interpreted as a 31b big-endian uint
|
||||
# (31b to avoid sign concerns). This effectively limits digits to 9 and
|
||||
# hard-limits it to 10: each digit is normally worth 3.32 bits but the
|
||||
# 10th is only worth 1.1 (9 digits encode 29.9 bits).
|
||||
code = struct.unpack_from('>I', mac, offset)[0] & 0x7FFFFFFF
|
||||
r = code % (10 ** DIGITS)
|
||||
# NOTE: use text / bytes instead of int?
|
||||
return r
|
||||
Loading…
Add table
Add a link
Reference in a new issue