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__.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:
otp2289.OTPChallengeException – If the challenge is invalid
otp2289.OTPGeneratorException – If generator parameters are wrong
- 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:
otp2289.OTPChallengeException – If the challenge is invalid
otp2289.OTPGeneratorException – If generator parameters are wrong
- 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:
otp2289.OTPChallengeException – If the challenge is invalid
otp2289.OTPGeneratorException – If generator parameters are wrong
- Returns:
The response string
- Return type:
str
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
otp2289.server module¶
A pure Python implementation of the RFC-2289 OTP server
- 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:
- 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
- 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!
- pop_state(key: str) OTPState [source]¶
Removes specified key and returns the corresponding OTPState-object.
- Parameters:
key (str) – The key
- Raises:
KeyError – If key does not exist
otp2289.OTPStoreException – On failure
- Returns:
The state corresponding to the key
- Return type:
- 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:
KeyError – If the key is not present
otp2289.OTPInvalidResponse – If the response does not match this state
- 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!
Module contents¶
A pure Python implementation of RFC-2289
- 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
- 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:
- 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
- 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!
- pop_state(key: str) OTPState [source]¶
Removes specified key and returns the corresponding OTPState-object.
- Parameters:
key (str) – The key
- Raises:
KeyError – If key does not exist
otp2289.OTPStoreException – On failure
- Returns:
The state corresponding to the key
- Return type:
- 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:
KeyError – If the key is not present
otp2289.OTPInvalidResponse – If the response does not match this state
- 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!