class TOTP(object): def __init__( self, key: bytes, length: int, algorithm: _ALLOWED_HASH_TYPES, time_step: int, backend=None, enforce_key_length: bool = True, ): backend = _get_backend(backend) if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE, ) self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) def generate(self, time: typing.Union[int, float]) -> bytes: counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp: bytes, time: int) -> None: if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri(self, account_name: str, issuer: typing.Optional[str]) -> str: return _generate_uri(self._hotp, "totp", account_name, issuer, [("period", int(self._time_step))])
class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend, enforce_key_length=True): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE) self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri(self, account_name, issuer): return _generate_uri(self._hotp, "totp", account_name, issuer, [ ("period", int(self._time_step)), ])
class TOTP(object): def __init__( self, key: bytes, length: int, algorithm: _ALLOWED_HASH_TYPES, time_step: int, backend: typing.Any = None, enforce_key_length: bool = True, ): self._time_step = time_step self._hotp = HOTP(key, length, algorithm, enforce_key_length=enforce_key_length) def generate(self, time: typing.Union[int, float]) -> bytes: counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp: bytes, time: int) -> None: if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri(self, account_name: str, issuer: typing.Optional[str]) -> str: return _generate_uri( self._hotp, "totp", account_name, issuer, [("period", int(self._time_step))], )
def generate_htop(length=6, salt=0): hotp = HOTP(key, length, SHA1(), backend=default_backend()) hotp_value = hotp.generate(salt) # hotp.verify(hotp_value, 0) return hotp_value.decode()
def test_generate(self, backend, params): secret = params["secret"] counter = int(params["counter"]) hotp_value = params["hotp"] hotp = HOTP(secret, 6, SHA1(), backend) assert hotp.generate(counter) == hotp_value
def test_generate(self, backend, params): secret = params["secret"] counter = int(params["counter"]) hotp_value = params["hotp"] hotp = HOTP(secret, 6, SHA1(), backend) assert hotp.generate(counter) == hotp_value
class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend): self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match")
def send_aic(sessionid, role, bindkey, pubkey): """ Send an AIC to the ags, returns success value sessionid -- Anonymized Session ID for user role -- Role as retrieved from database bindkey -- As generated during login pubkey -- Users stored public key context -- Users login context """ # AIC construct aic = {"sessionid":sessionid, "role":role, "bindkey":bindkey, "pubkey":pubkey} message = json.dumps(aic) logger.info("Genrated AIC: %s", message) # Secure the payload payload = transport_security.construct_message(message, srcprivkey=app_privatekey, destpubkey=ags_publickey) # Calculate the current HOTP token from file with open(ags_secretfile, 'r') as f: agsdict = json.loads(f.read()) counter = agsdict['Counter'] tfapass = agsdict['2FAKey'] hotp = HOTP(bytes(tfapass, 'utf-8'), 6, hashes.SHA1(), backend=default_backend()) tfaval = hotp.generate(counter).decode('utf-8') # Do the reques to the AGS #XXX: Change to https for deployment url = "http://{}:{}/ags/authorized?token={}".format(ags_address, ags_port, tfaval) logger.info("Adding AIC to AGS: %s", url) try: resp = requests.put(url, json=payload) except requests.Timeout: logger.warning("AGS connection timeout") return None except requests.ConnectionError: logger.warning("AGS connection error") return None logger.info("AGS AIC PUT status code: %s", resp.status_code) # A 200 OK response means the request was successful if resp.status_code == 200: # Update the HOTP counter value counter += 1 agsdict['Counter'] = counter with open(ags_secretfile, 'w') as f: f.write(json.dumps(agsdict)) logger.info("AGS HOTP counter was incremented to %s", counter) # Return the validity as returned by the AGS return resp.json()['validity'] else: logger.warning("AGS rejected AIC") return None
def retrieve_keys(db, attribute): """ Retrieve keys from the KS; This involves querying the KS with an authentication token Then decrypting and returning the encrypted payload db -- Databse whose keys to retrieve attribute -- The attribute whose encryption key to retrieve """ # Load the HOTP secret and counter from the secret file of the Key Server with open(ks_secretfile, 'r') as f: ksdict = json.loads(f.read()) counter = ksdict['Counter'] tfapass = ksdict['2FAKey'] # Calculate the HOTP token value hotp = HOTP(bytes(tfapass, 'utf-8'), 6, hashes.SHA1(), backend=default_backend()) tfaval = hotp.generate(counter).decode('utf-8') # Do the request to the key server #XXX: Chnage to https for deployment url = "http://{}:{}/key/{}/{}?token={}".format(ks_address, ks_port, db, attribute, tfaval) logger.info("Trying to access key from KS: %s", url) # Do the request try: resp = requests.get(url) except requests.exceptions.Timeout: logger.warning("KS request timeout") return None except requests.exceptions.ConnectionError: logger.warning("KS connection refused") return None logger.info("KS response code: %s", resp.status_code) if resp.status_code == 200: # Got 200 means KS incremented the counter counter += 1 # Increment our own counter # Save the updated secret ksdict['Counter'] = counter with open(ks_secretfile, 'w') as f: f.write(json.dumps(ksdict)) logger.info("KS HOTP counter was incremented to %s", counter) # Get the transport secure message secured_message = resp.json() key = transport_security.deconstruct_message(secured_message, destprivkey=app_privatekey, srcpubkey=ks_publickey) # Check if decryption was successful if not key: logger.warning("Secured message from KS was not decrypted properly") return None return key else: # KS did not return the key logger.warning("KS replied negatively. Something is wrong.") return None
class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend): if not isinstance(backend, HMACBackend): raise UnsupportedInterface("Backend object does not implement HMACBackend") self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match")
class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE) self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.")
def generate_hotp_code(secret, counter): """ Generate a Google authenticator compatible HOTP code Args: secret: 16 character base32 secret (80 bit key) counter: unique integer value Return: code: 6 digit one time use code """ if isinstance(secret, unicode): secret = secret.encode('utf-8') try: key = base64.b32decode(secret) hotp = HOTP(key, 6, SHA1(), backend=default_backend(), enforce_key_length=False) hotp_value = hotp.generate(counter) return hotp_value except (ValueError, TypeError): pass return None
class TOTP(object): def __init__(self, key, length, algorithm, time_step, backend, enforce_key_length=True): if not isinstance(backend, HMACBackend): raise UnsupportedAlgorithm( "Backend object does not implement HMACBackend.", _Reasons.BACKEND_MISSING_INTERFACE ) self._time_step = time_step self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length) def generate(self, time): counter = int(time / self._time_step) return self._hotp.generate(counter) def verify(self, totp, time): if not constant_time.bytes_eq(self.generate(time), totp): raise InvalidToken("Supplied TOTP value does not match.") def get_provisioning_uri(self, account_name, issuer): return _generate_uri(self._hotp, "totp", account_name, issuer, [("period", int(self._time_step))])
def test_buffer_protocol(self, backend): key = bytearray(b"a long key with lots of entropy goes here") hotp = HOTP(key, 6, SHA1(), backend) assert hotp.generate(10) == b"559978"
def test_buffer_protocol(self, backend): key = bytearray(b"a long key with lots of entropy goes here") hotp = HOTP(key, 6, SHA1(), backend) assert hotp.generate(10) == b"559978"
import collections def count_frequency(arr): return collections.Counter(arr) if __name__ == '__main__': hotp_holder = [] key = os.urandom(20) hotp = HOTP(key, 8, SHA1(), backend=default_backend()) for x in range(100000): hotp_value = hotp.generate(x) hotp_str = hotp_value.decode("utf-8") n = 2 for i in range(0, len(hotp_str), n): hotp_holder.append(hotp_str[i:i + n]) # matplotlib histogram plt.hist(hotp_holder, color='blue', edgecolor='black', bins=100) # seaborn histogram sns.distplot(hotp_holder, hist=True, kde=False, bins=1000, color='blue', hist_kws={'edgecolor': 'black'})
def primitive(): # Initialize the errors variable to empty string. We will have the error messages # in that variable, if any. errors = '' if request.method == "GET": # If the request is GET, render the form template. return render_template("index.html", errors=errors) if 'aesForm' in request.form: # The request is POST with some data, get POST data and validate it. # The form data is available in request.form dictionary. Stripping it to remove # leading and trailing whitespaces aesPlainText = request.form['aesPlainText'].strip() # Check if all the fields are non-empty and raise an error otherwise if not aesPlainText: errors = "Please enter all the fields." if not errors: # If there are no errors, create a dictionary containing all the entered # data and pass it to the template to be displayed a1 = "Symmetric Encryption\n" a2 = "This application will use DES Symmetric Encryption to encrypt and decrypt text\n" plainText = "Text to encrypt: " getInput = aesPlainText backend = default_backend() cfb_Key = os.urandom(16) aes_Key = os.urandom(32) #secretMessage = str.encode(input(plainText)) secretMessage = str.encode(getInput) cipher = Cipher(algorithms.AES(aes_Key), modes.CFB(cfb_Key), backend=backend) encryptor = cipher.encryptor() encryptedText = encryptor.update( secretMessage) + encryptor.finalize() decryptor = cipher.decryptor() decryptedText = decryptor.update( encryptedText) + decryptor.finalize() dataAes = { 'aes_Key': aes_Key, 'cfb_Key': cfb_Key, 'encryptedText': encryptedText, 'decryptedText': decryptedText } # Since the form data is valid, render the success template return render_template("prim/aes.html", dataAes=dataAes) # Render the form template with the error messages return render_template("index.html", errors=errors) if 'desForm' in request.form: # The request is POST with some data, get POST data and validate it. # The form data is available in request.form dictionary. Stripping it to remove desPlainText = request.form['desPlainText'].strip() #desBitKey = request.form['desBitKey'].strip() #desMode = request.form['desMode'].strip() # Check if all the fields are non-empty and raise an error otherwise if not desPlainText: errors = "Please enter all the fields." if not errors: # If there are no errors, create a dictionary containing all the entered # data and pass it to the template to be displayed plaintext = desPlainText mode = "CBC" key = "12345678" #key and plain text desKey = des(key, mode, "\0\0\0\0\0\0\0\0") #print ("Key : %r" % k.getKey()) #print ("Plaintext : %r" % plaintext) #desKey = k # Encrypted message desEnc = desKey.encrypt(plaintext, [], PAD_PKCS5) #print ("Encrypted: %r" % d) desEncMessage = desEnc # Decrypted message desDec = desKey.decrypt(desEncMessage, [], PAD_PKCS5) #print ("Decrypted Plaintext: %r" % d) desDecMessage = desDec dataDes = { 'desPlainText': desPlainText, 'desKey': desKey, 'desEncMessage': desEncMessage, 'desDecMessage': desDecMessage } # Since the form data is valid, render the success template return render_template("prim/des.html", dataDes=dataDes) # Render the form template with the error messages return render_template("index.html", errors=errors) if 'hmacForm' in request.form: # The request is POST with some data, get POST data and validate it. # The form data is available in request.form dictionary. Stripping it to remove hmacPlainText = request.form['hmacPlainText'].strip() # Check if all the fields are non-empty and raise an error otherwise if not hmacPlainText: errors = "Please enter all the fields." if not errors: # If there are no errors, create a dictionary containing all the entered # data and pass it to the template to be displayed shared_key = os.urandom(16) # Create a HMAC object digest = hmac.HMAC(shared_key, hashes.SHA256(), backend=default_backend()) # enter the message has input to be hased in bytes plaintext = str.encode(hmacPlainText) digest.update(plaintext) # Finalized and produce the HMAC that will be attached to the message hash_code = digest.finalize() print("message", hmacPlainText) print("hash_code", hash_code) print("random Key:", shared_key) dataHmac = { 'hmacPlainText': hmacPlainText, 'hash_code': hash_code, 'shared_key': shared_key } # Since the form data is valid, render the success template return render_template("prim/hmac.html", dataHmac=dataHmac) # Render the form template with the error messages return render_template("index.html", errors=errors) if 'diffForm' in request.form: # The request is POST with some data, get POST data and validate it. # The form data is available in request.form dictionary. Stripping it to remove diifPlainText = request.form['diifPlainText'].strip() diffPub1 = request.form['diffPub1'].strip() diffPub2 = request.form['diffPub2'].strip() # Check if all the fields are non-empty and raise an error otherwise if not diifPlainText or not diffPub1 or not diffPub2: errors = "Please enter all the fields." if not errors: # If there are no errors, create a dictionary containing all the entered # data and pass it to the template to be displayed Xa = int(diffPub1) Xb = int(diffPub2) diifPlainText = int(diifPlainText) check_num = 0 prK = 2 a = prK #Compute Public Key for first user Ya = (a**Xa) % diifPlainText #Compute Public Key for second user Yb = (a**Xb) % diifPlainText #Compute shared key Ka = (Yb**Xa) % diifPlainText Kb = (Ya**Xb) % diifPlainText #Shared key should be same value for both users print("primitive_root: prK and prQ") print("1 shared key is", Ka) print("2 shared key is", Kb, "\n") print("1 and 2 secret shared key is", Ka, "\n") print("primitive_root", prK) print("a_pupKey", Ya) print("a_sharedKey", Ka) print("b_pupKey", Yb) print("b_sharedKey:", Kb) dataDiff = { 'prime': diifPlainText, 'primitive_root': prK, 'a_pupKey': Ya, 'a_sharedKey': Ka, 'b_pupKey': Yb, 'b_sharedKey': Kb } # Since the form data is valid, render the success template return render_template("prim/diff.html", dataDiff=dataDiff) # Render the form template with the error messages return render_template("index.html", errors=errors) if '2faForm' in request.form: # The request is POST with some data, get POST data and validate it. # The form data is available in request.form dictionary. Stripping it to remove #diifPlainText = request.form['diifPlainText'].strip() # Check if all the fields are non-empty and raise an error otherwise #if not diifPlainText or not diffPub1 or not diffPub2: #errors = "Please enter all the fields." if not errors: # If there are no errors, create a dictionary containing all the entered # data and pass it to the template to be displayed #Key is a secret key which is being randomly generated bytes key2Fa = os.urandom(20) #HOTP is an HMAC one-time password algorithm. #Length parameter is controls the length of the generated password which must be >=6 and <=8; Is using SHA1() hash function to encrypt hotp = HOTP(key2Fa, 6, SHA1(), backend=default_backend()) #Hotp.generate, generates the random 6 digit token hotp_value = hotp.generate(0) hotp.verify(hotp_value, 0) print("hashed_value: ", hotp_value) print("generated key: ", key2Fa) data2Fa = {'hotp_value': hotp_value, 'key2Fa': key2Fa} # Since the form data is valid, render the success template return render_template("prim/2fa.html", data2Fa=data2Fa) # Render the form template with the error messages return render_template("index.html", errors=errors)