otp2289 package

Submodules

otp2289.__main__ module

CLI entry point for the otp2289 package

Examples: python -m otp2289 –initiate-new-sequence -s TesT

python -m otp2289 –generate-otp-response -c “otp-md5 499 TesT “ -f token python -m otp2289 –generate-otp-response -s TesT -i 499 -f token

otp2289.__main__.eprint(*arg, **kwargs)[source]

stdderr print wrapper

otp2289.__main__.generate_otp_range(args: Namespace) str[source]

Generates range of responses based on the parameters sent from the parser

Parameters:

args (argparse.Namespace) – The arguments assigned from argparse

Raises:
Returns:

The responses string

Return type:

str

otp2289.__main__.generate_otp_response(args: Namespace) str[source]

Generates a response based on the parameters sent from the parser

Parameters:

args (argparse.Namespace) – The arguments assigned from argparse

Raises:
Returns:

The response string

Return type:

str

otp2289.__main__.get_password(args: Namespace) str[source]

Extract the provided password using the defined argparse arguments

Parameters:

args (argparse.Namespace) – The arguments assigned from argparse

Raises:

KeyboardInterrupt – If the password prompt is interrupted

Returns:

The extrated password string

Return type:

str

otp2289.__main__.get_rnd_seed() str[source]

Returns a random seed in the format:

2 random letters (capitalize()) + 5 random digits

otp2289.__main__.initiate_new_sequence(args: Namespace) str[source]

Generates a new sequence based on the parameters sent from the parser.

Parameters:

args (argparse.Namespace) – The arguments assigned from argparse

Raises:
Returns:

The response string

Return type:

str

otp2289.__main__.main(args=None)[source]

the main entry point

otp2289.generator module

A pure Python implementation of the RFC-2289 OTP generator

exception otp2289.generator.OTPChallengeException[source]

Bases: Exception

OTPChallengeException class

class otp2289.generator.OTPGenerator(password: bytes, seed: str = '', hash_algo=1)[source]

Bases: object

OTPGenerator class

_generate_otp_bytes(step: int) bytes[source]

Generates the OTP bytes for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

The digest bytes for the given step

Return type:

bytes

static bit_pair_sum(bit_stream: str) int[source]

Split bit_stream in bit-pairs and sum them all together.

Parameters:

bit_stream (str) – The bit-stream object

Returns:

The sum of all bit-pairs in bit_stream

Return type:

int

static bytes_to_tokens(hash_bytes: bytes) str[source]

Returns a 6 words token from bytes as specified by RFC-2289.

Parameters:

hash_bytes (bytes) – The input bytes

Returns:

6 words tokens

Return type:

str

generate_otp_hexdigest(step: int) str[source]

Generates the OTP hexdigest for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

Hexdigest for the given step

Return type:

str

generate_otp_hexdigest_from_challenge(challenge: str) str[source]

Same as generate_otp_hexdigest, but it generates hex. from a challenge.

RFC-2289 states: The challenge MUST be in a standard syntax so that automated generators can recognize the challenge in context and extract these parameters. The syntax of the challenge is: otp-<algorithm identifier> <sequence integer> <seed>

Parameters:

challenge (str) – The challenge string

Returns:

Hexdigest for the given challenge

Return type:

str

generate_otp_words(step: int) str[source]

Generates the OTP six words token for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

Six words (separated by single space) token for the given step

Return type:

str

generate_otp_words_from_challenge(challenge: str) str[source]

Same as generate_otp_words, but it generates words from a challenge.

RFC-2289 states: The challenge MUST be in a standard syntax so that automated generators can recognize the challenge in context and extract these parameters. The syntax of the challenge is: otp-<algorithm identifier> <sequence integer> <seed>

Parameters:

challenge (str) – The challenge string

Returns:

Six words token for the given challenge

Return type:

str

static get_tokens_from_challenge(challenge: str) tuple[source]

Returns tokens (seed, hash_algo and step) from a challenge string.

N.B. The tokens are not validated here.

Parameters:

challenge (str) – The challenge string described in RFC-2289

Raises:

otp2289.OTPChallengeException – If the challenge is invalid

Returns:

(seed, hash_algo, step) tuple.

Return type:

tuple

hexdigest_range(start: int = 499, stop: int = 0)[source]

Returns an iterator that providing hexdigests corresponding to steps from start to and including stop.

Parameters:
  • start (int) – The start of the range (default: 499)

  • stop (int) – The last step (default: 0)

Returns:

Iterator

Return type:

generator

static sha1_digest_folding(sha1_digest: bytes) bytes[source]

Implementation of the 160bit -> 64bit folding algorithm for sha1 digest.

Parameters:

sha1_digest (bytes) – The SHA1 digest

Returns:

The byte-string representing the folded sha1-digest

Return type:

bytes

static strxor(byte_str1: bytes, byte_str2: bytes) bytes[source]

Implementation of strxor similar to the one provided by pycrypto.

Parameters:
  • byte_str1 (bytes) – Byte-string 1

  • byte_str2 (bytes) – Byte-string 2

Returns:

The byte-string representing the result of byte_str1^byte_str2

Return type:

bytes

static tokens_to_bytes(tokens_str: str) bytes[source]

Returns bytes from a 6 words token as specified by RFC-2289.

Parameters:

tokens_str (str) – String representing 6 words tokens

Raises:

otp2289.OTPGeneratorException – When the tokens_str is invalid

Returns:

6 words tokens

Return type:

bytes

static validate_hash_algo(hash_algo) str[source]

Validates the provided hash-algorithm.

Parameters:

hash_algo (int or str) – The hash algo, defaults to OTP_ALGO_MD5

Raises:

otp2289.OTPGeneratorException – If hash_algo does not validate

Returns:

The validated hash_algo in str-form

Return type:

str

static validate_seed(seed: str) str[source]

Validates the provided seed as defined by RFC-2289.

Parameters:

seed (str) – The seed received from the challenge, defaults to ‘’

Raises:

otp2289.OTPGeneratorException – If seed does not validate

Returns:

The validated (and very same) seed

Return type:

str

static validate_step(step: int) int[source]

Validates the provided step as defined by RFC-2289.

Parameters:

seed (int) – The step received from the challenge

Raises:

otp2289.OTPGeneratorException – If step does not validate

Returns:

The validated (and very same) step

Return type:

int

words_range(start: int = 499, stop: int = 0)[source]

Returns an iterator that providing the words corresponding to steps from start to and including stop.

Parameters:
  • start (int) – The start of the range (default: 499)

  • stop (int) – The last step (default: 0)

Returns:

Iterator

Return type:

generator

exception otp2289.generator.OTPGeneratorException[source]

Bases: Exception

OTPGeneratorException class

otp2289.server module

A pure Python implementation of the RFC-2289 OTP server

exception otp2289.server.OTPInvalidResponse[source]

Bases: Exception

OTPInvalidResponse class

class otp2289.server.OTPState(ot_hex: str, current_step: int, seed: str, hash_algo=1)[source]

Bases: object

OTPState class

The OTPState class represents a single state on the server side that can: - generate a challenge - validate the corresponding generated response from the generator

property challenge_string: str

challenge_string-property

property current_digest: bytes

current_digest-property

classmethod from_dict(dict_obj: dict)[source]

Returns an OTPState object from the dict-object

Parameters:

dict_obj (dict) – The dict object

Returns:

A new OTPState object

Return type:

otp2289.OTPStore

get_next_state()[source]

Returns the next state for a validated OTPState.

This is a brand new OTPState object with the same hash_algo and seed where step -= 1 and ot_hex = self._new_digest_hex

Returns:

The next OTPState if validated, None otherwise

Return type:

otp2289.OTPState or None

property hash_algo: str

hash_algo-property

property ot_hex: str

ot_hex-property

static response_to_bytes(response: str) bytes[source]

A wrapper that handles/validates the response as specified by RFC-2289.

The method first checks if response is a token and tries to convert it to bytes. If that fails, the method assumes that response is a hex. If neither of those attempts succeeds OTPInvalidResponse is raised. It is up to the caller to run another iteration and compare the result to an existing digest in this state.

Parameters:

response (str) – The response to this state (its challenge)

Raises:

otp2289.OTPInvalidResponse – If the response is corrupt/illegal, but not if it simply does not validate

Returns:

The bytes representation of response (if any)

Return type:

bytes

response_validates(response: str, store_valid_response: str = True) bool[source]

Validates the incoming response as specified by RFC-2289.

Parameters:
  • response (str) – The response to this state (its challenge)

  • store_valid_response (bool) – Should a valid response be stored

Raises:

otp2289.OTPInvalidResponse – If the response does not match this state

Returns:

Returns True if response validates, False otherwise

Return type:

bool

property seed: str

seed-property

property step: int

step-property

to_dict() dict[source]

Returns a dict representation of the object.

This could be the base for a JSON serialization.

Returns:

The dict representation of the object

Return type:

dict

static validate_hex(ot_hex: str) bytes[source]

Validates the provided hexidigest.

Parameters:

ot_hex (str) – The one-time hex to validate

Raises:

otp2289.OTPStateException – If hex does not validate

Returns:

The validated hex (without leading 0x) converted to bytes

Return type:

bytes

property validated: bool

validated-property

exception otp2289.server.OTPStateException[source]

Bases: Exception

OTPStateException class

class otp2289.server.OTPStore(data=None)[source]

Bases: object

OTPStore class

A helper / container class that stores OTPState objects in a 2 layered dict structure represented by [domain][key].

The class could serve as a base class when implementing store backends.

_add_data(dict_obj: dict) dict[source]

Adds data from a dict object (dict_obj).

This method should probably be either overloaded or wrapped in a child class.

dict_obj has the following format: {

‘key’: {

‘ot_hex’: val1, ‘current_step’: val2, ‘seed’: val3, ‘hash_algo’: val4

}, …, …,

}

Parameters:

dict_obj (dict) – The dict-object

add_state(key: str, state: OTPState)[source]

Adds an OTPState object with a given key.

Parameters:
  • key (str) – The key under which to add the state

  • state (otp2289.OTPState) – The OTPState object

Raises:

otp2289.OTPStoreException – On failure

property data: dict

data-property

Exposes the entire raw-data structure (dict). Use the high level methods when possible!

get(key, default=None)[source]

A wrapper for dict.get

items()[source]

A wrapper for dict.items

pop_state(key: str) OTPState[source]

Removes specified key and returns the corresponding OTPState-object.

Parameters:

key (str) – The key

Raises:
Returns:

The state corresponding to the key

Return type:

otp2289.OTPState

response_validates(key: str, response: str, store_valid_response: bool = True) bool[source]

A method that wraps around OTPState.response_validates and OTPState.get_next_state.

The response is validated against the OTPState object that corresponds to key (if any). If store_valid_response is True, the state is replaced by the next state on successful validation.

Parameters:
  • key (str) – The key

  • response (str) – The response to this state (its challenge)

  • store_valid_response (bool) – Should a valid response be stored

Raises:
Returns:

Returns True if response validates, False otherwise

Return type:

bool

property states: dict

states-property

Exposes the entire states structure (dict). Use the high level methods when possible!

to_dict() dict[source]

Returns a dict representation of the object.

This could be the base for a JSON serialization.

Returns:

The dict representation of the object

Return type:

dict

exception otp2289.server.OTPStoreException[source]

Bases: Exception

OTPStoreException class

Module contents

A pure Python implementation of RFC-2289

exception otp2289.OTPChallengeException[source]

Bases: Exception

OTPChallengeException class

class otp2289.OTPGenerator(password: bytes, seed: str = '', hash_algo=1)[source]

Bases: object

OTPGenerator class

_generate_otp_bytes(step: int) bytes[source]

Generates the OTP bytes for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

The digest bytes for the given step

Return type:

bytes

static bit_pair_sum(bit_stream: str) int[source]

Split bit_stream in bit-pairs and sum them all together.

Parameters:

bit_stream (str) – The bit-stream object

Returns:

The sum of all bit-pairs in bit_stream

Return type:

int

static bytes_to_tokens(hash_bytes: bytes) str[source]

Returns a 6 words token from bytes as specified by RFC-2289.

Parameters:

hash_bytes (bytes) – The input bytes

Returns:

6 words tokens

Return type:

str

generate_otp_hexdigest(step: int) str[source]

Generates the OTP hexdigest for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

Hexdigest for the given step

Return type:

str

generate_otp_hexdigest_from_challenge(challenge: str) str[source]

Same as generate_otp_hexdigest, but it generates hex. from a challenge.

RFC-2289 states: The challenge MUST be in a standard syntax so that automated generators can recognize the challenge in context and extract these parameters. The syntax of the challenge is: otp-<algorithm identifier> <sequence integer> <seed>

Parameters:

challenge (str) – The challenge string

Returns:

Hexdigest for the given challenge

Return type:

str

generate_otp_words(step: int) str[source]

Generates the OTP six words token for the given step.

Parameters:

step (int) – The step to generate OTP for

Returns:

Six words (separated by single space) token for the given step

Return type:

str

generate_otp_words_from_challenge(challenge: str) str[source]

Same as generate_otp_words, but it generates words from a challenge.

RFC-2289 states: The challenge MUST be in a standard syntax so that automated generators can recognize the challenge in context and extract these parameters. The syntax of the challenge is: otp-<algorithm identifier> <sequence integer> <seed>

Parameters:

challenge (str) – The challenge string

Returns:

Six words token for the given challenge

Return type:

str

static get_tokens_from_challenge(challenge: str) tuple[source]

Returns tokens (seed, hash_algo and step) from a challenge string.

N.B. The tokens are not validated here.

Parameters:

challenge (str) – The challenge string described in RFC-2289

Raises:

otp2289.OTPChallengeException – If the challenge is invalid

Returns:

(seed, hash_algo, step) tuple.

Return type:

tuple

hexdigest_range(start: int = 499, stop: int = 0)[source]

Returns an iterator that providing hexdigests corresponding to steps from start to and including stop.

Parameters:
  • start (int) – The start of the range (default: 499)

  • stop (int) – The last step (default: 0)

Returns:

Iterator

Return type:

generator

static sha1_digest_folding(sha1_digest: bytes) bytes[source]

Implementation of the 160bit -> 64bit folding algorithm for sha1 digest.

Parameters:

sha1_digest (bytes) – The SHA1 digest

Returns:

The byte-string representing the folded sha1-digest

Return type:

bytes

static strxor(byte_str1: bytes, byte_str2: bytes) bytes[source]

Implementation of strxor similar to the one provided by pycrypto.

Parameters:
  • byte_str1 (bytes) – Byte-string 1

  • byte_str2 (bytes) – Byte-string 2

Returns:

The byte-string representing the result of byte_str1^byte_str2

Return type:

bytes

static tokens_to_bytes(tokens_str: str) bytes[source]

Returns bytes from a 6 words token as specified by RFC-2289.

Parameters:

tokens_str (str) – String representing 6 words tokens

Raises:

otp2289.OTPGeneratorException – When the tokens_str is invalid

Returns:

6 words tokens

Return type:

bytes

static validate_hash_algo(hash_algo) str[source]

Validates the provided hash-algorithm.

Parameters:

hash_algo (int or str) – The hash algo, defaults to OTP_ALGO_MD5

Raises:

otp2289.OTPGeneratorException – If hash_algo does not validate

Returns:

The validated hash_algo in str-form

Return type:

str

static validate_seed(seed: str) str[source]

Validates the provided seed as defined by RFC-2289.

Parameters:

seed (str) – The seed received from the challenge, defaults to ‘’

Raises:

otp2289.OTPGeneratorException – If seed does not validate

Returns:

The validated (and very same) seed

Return type:

str

static validate_step(step: int) int[source]

Validates the provided step as defined by RFC-2289.

Parameters:

seed (int) – The step received from the challenge

Raises:

otp2289.OTPGeneratorException – If step does not validate

Returns:

The validated (and very same) step

Return type:

int

words_range(start: int = 499, stop: int = 0)[source]

Returns an iterator that providing the words corresponding to steps from start to and including stop.

Parameters:
  • start (int) – The start of the range (default: 499)

  • stop (int) – The last step (default: 0)

Returns:

Iterator

Return type:

generator

exception otp2289.OTPGeneratorException[source]

Bases: Exception

OTPGeneratorException class

exception otp2289.OTPInvalidResponse[source]

Bases: Exception

OTPInvalidResponse class

class otp2289.OTPState(ot_hex: str, current_step: int, seed: str, hash_algo=1)[source]

Bases: object

OTPState class

The OTPState class represents a single state on the server side that can: - generate a challenge - validate the corresponding generated response from the generator

property challenge_string: str

challenge_string-property

property current_digest: bytes

current_digest-property

classmethod from_dict(dict_obj: dict)[source]

Returns an OTPState object from the dict-object

Parameters:

dict_obj (dict) – The dict object

Returns:

A new OTPState object

Return type:

otp2289.OTPStore

get_next_state()[source]

Returns the next state for a validated OTPState.

This is a brand new OTPState object with the same hash_algo and seed where step -= 1 and ot_hex = self._new_digest_hex

Returns:

The next OTPState if validated, None otherwise

Return type:

otp2289.OTPState or None

property hash_algo: str

hash_algo-property

property ot_hex: str

ot_hex-property

static response_to_bytes(response: str) bytes[source]

A wrapper that handles/validates the response as specified by RFC-2289.

The method first checks if response is a token and tries to convert it to bytes. If that fails, the method assumes that response is a hex. If neither of those attempts succeeds OTPInvalidResponse is raised. It is up to the caller to run another iteration and compare the result to an existing digest in this state.

Parameters:

response (str) – The response to this state (its challenge)

Raises:

otp2289.OTPInvalidResponse – If the response is corrupt/illegal, but not if it simply does not validate

Returns:

The bytes representation of response (if any)

Return type:

bytes

response_validates(response: str, store_valid_response: str = True) bool[source]

Validates the incoming response as specified by RFC-2289.

Parameters:
  • response (str) – The response to this state (its challenge)

  • store_valid_response (bool) – Should a valid response be stored

Raises:

otp2289.OTPInvalidResponse – If the response does not match this state

Returns:

Returns True if response validates, False otherwise

Return type:

bool

property seed: str

seed-property

property step: int

step-property

to_dict() dict[source]

Returns a dict representation of the object.

This could be the base for a JSON serialization.

Returns:

The dict representation of the object

Return type:

dict

static validate_hex(ot_hex: str) bytes[source]

Validates the provided hexidigest.

Parameters:

ot_hex (str) – The one-time hex to validate

Raises:

otp2289.OTPStateException – If hex does not validate

Returns:

The validated hex (without leading 0x) converted to bytes

Return type:

bytes

property validated: bool

validated-property

exception otp2289.OTPStateException[source]

Bases: Exception

OTPStateException class

class otp2289.OTPStore(data=None)[source]

Bases: object

OTPStore class

A helper / container class that stores OTPState objects in a 2 layered dict structure represented by [domain][key].

The class could serve as a base class when implementing store backends.

_add_data(dict_obj: dict) dict[source]

Adds data from a dict object (dict_obj).

This method should probably be either overloaded or wrapped in a child class.

dict_obj has the following format: {

‘key’: {

‘ot_hex’: val1, ‘current_step’: val2, ‘seed’: val3, ‘hash_algo’: val4

}, …, …,

}

Parameters:

dict_obj (dict) – The dict-object

add_state(key: str, state: OTPState)[source]

Adds an OTPState object with a given key.

Parameters:
  • key (str) – The key under which to add the state

  • state (otp2289.OTPState) – The OTPState object

Raises:

otp2289.OTPStoreException – On failure

property data: dict

data-property

Exposes the entire raw-data structure (dict). Use the high level methods when possible!

get(key, default=None)[source]

A wrapper for dict.get

items()[source]

A wrapper for dict.items

pop_state(key: str) OTPState[source]

Removes specified key and returns the corresponding OTPState-object.

Parameters:

key (str) – The key

Raises:
Returns:

The state corresponding to the key

Return type:

otp2289.OTPState

response_validates(key: str, response: str, store_valid_response: bool = True) bool[source]

A method that wraps around OTPState.response_validates and OTPState.get_next_state.

The response is validated against the OTPState object that corresponds to key (if any). If store_valid_response is True, the state is replaced by the next state on successful validation.

Parameters:
  • key (str) – The key

  • response (str) – The response to this state (its challenge)

  • store_valid_response (bool) – Should a valid response be stored

Raises:
Returns:

Returns True if response validates, False otherwise

Return type:

bool

property states: dict

states-property

Exposes the entire states structure (dict). Use the high level methods when possible!

to_dict() dict[source]

Returns a dict representation of the object.

This could be the base for a JSON serialization.

Returns:

The dict representation of the object

Return type:

dict

exception otp2289.OTPStoreException[source]

Bases: Exception

OTPStoreException class