示例#1
0
def check_password(login, password):
    """Checks provided credentials against database or system user.

    :param str login: login username
    :param str password: cleartext password

    :return: bool
    """
    check_login_attempt(login)
    is_verified = False
    try:
        user = db.session.query(Principal).filter_by(login=login).one()
        if user.is_root:
            is_verified = check_system_login(user.login, password)
        else:
            salt, pass_hash = user.password_hash.split(':')
            computed = KDF.PBKDF2(password,
                                  salt,
                                  dkLen=DK_LEN,
                                  count=HASH_ROUNDS).encode('hex')
            if computed == pass_hash:
                is_verified = True
    except NoResultFound:
        LOG.error("User not found with login: %s", login)
        # simulate a password check anyway
        KDF.PBKDF2(password, 'salt', dkLen=DK_LEN,
                   count=HASH_ROUNDS).encode('hex')
    if not is_verified:
        log_failed_login_attempt(login)
    return is_verified
示例#2
0
 def set_passphrase(self, passphrase):
     """Set a user defined passphrase to override the AES and HMAC keys"""
     self.passphrase = passphrase
     self.aes_key = KDF.PBKDF2(passphrase, dconfig.aes_salt.decode("hex"),
                               32)
     self.mac_key = KDF.PBKDF2(passphrase, dconfig.mac_salt.decode("hex"),
                               64)
示例#3
0
    def decode_url(self, url):
        """Takes a URL, and returns the cryptographic nonce. Use PBKDF2 with our
        nonce and our salts to return the file name, AES key, and MAC key.

        keyword arguments:
        url -- the url after the FQDN provided by the client"""

        self.url = url
        url = url + "=="  # add the padding back

        try:
            self.nonce = base64.urlsafe_b64decode(url.encode("utf-8"))
        except:
            url = "errormessage=="
            self.nonce = base64.urlsafe_b64decode(url.encode("utf-8"))

        self.f_key = KDF.PBKDF2(self.nonce, dconfig.nonce_salt.decode("hex"),
                                16)
        self.aes_key = KDF.PBKDF2(self.nonce, dconfig.aes_salt.decode("hex"),
                                  32)
        self.mac_key = KDF.PBKDF2(self.nonce, dconfig.mac_salt.decode("hex"),
                                  64)
        duress = KDF.PBKDF2(self.nonce, dconfig.duress_salt.decode("hex"), 16)
        self.dkey = base64.urlsafe_b64encode(duress)[:22]
        self.fname = base64.urlsafe_b64encode(self.f_key)[:22]
示例#4
0
def encrypt(filename, password, iv):
    chucksize = 64 * 1024
    out_filename = filename + ".aes"
    iv = iv[:16]

    secure_key = KDF.PBKDF1(password, salt, 16, count=1000)

    encryptor = AES.new(secure_key, AES.MODE_CBC, iv)

    filesize = os.path.getsize(filename)
    progress = progressbar.AnimatedProgressBar(end=filesize, width=50)

    with open(filename, 'rb') as infile:
        with open(out_filename, 'wb') as outfile:
            outfile.write(struct.pack('<Q', filesize))
            outfile.write(iv)

            while True:
                chunk = infile.read(chucksize)
                if len(chunk) == 0:
                    # we are finished
                    break
                elif len(chunk) % 16 != 0:
                    chunk += ' ' * (16 - len(chunk) % 16)

                    # show the progress bar

                outfile.write(encryptor.encrypt(chunk))
                progress + len(chunk)
                progress.show_progress()
            print ""
            print "Done!"
示例#5
0
def derive_keys(masterPassoword: str, salt: bytes,
                iterations: int) -> DerivedKeys:
    """
    In OPVault format, the key derivation parameters, except Master Password,
    are all in 'profile'. In iCloud/Dropbox synced format, the profile is stored 
    as `profile.js` as a json object. In MacOS local format, the profile is a
    table in a SQLite database called 'OnePassword.sqlite', usually located at 
    ~/Library/Group Containers/2BUA8C4S2C.com.agilebits/Library/Application Support/1Password/Data.

    Because we don't use 2skd in OpVault, here it is fairly simple.
    The algorithm used here is PBKDF2-HMAC-SHA512, with the plain
    'salt' in profile. See https://support.1password.com/opvault-design/#key-derivation 
    for more information.

    The derived cryptoKey and hmacKey are used to encrypt/decrypt 
    and hmac-authenticate masterKey and overviewKey in profile.

    input:
        masterpassword: the user entered master password string
        salt: the base64 encoded string directly from profile.js. 
            Thus it need to be decoded here
    """
    # encode master password as a utf-8 null terminated string.
    mp = (masterPassoword + '\0').encode('utf-8')
    # decode the salt into bytes

    dk = KDF.PBKDF2(password=mp,
                    salt=salt,
                    dkLen=64,
                    count=iterations,
                    prf=hmac_sha512)

    return DerivedKeys(cryptoKey=dk[0:32], hmacKey=dk[32:])
示例#6
0
 def __init__(self, password):
     ACypher.__init__(self, 'aes')
     if password == '':
         Error_Fatal("Error: The AES key is void. Check your ini file.")
     self.SALT = get_random_bytes(8)
     self.KEY = KDF.PBKDF2(password, self.SALT)
     self.password = password
示例#7
0
 def __derive_key(self):
     """ Generates derived key using stored config """
     return KDF.PBKDF2(
         self.app_uuid + self.config[self.name]['UUID'],
         self.config[self.name]['salt'].encode('utf-8'),
         dkLen=32,  #32 bytes = 256 bits, max AES key length
         count=self.config[self.name]['iterations'])
示例#8
0
 def _pbkdf2(self, password, salt, iterations=10000, key_length=32):
     return KDF.PBKDF2(
         password,
         salt,
         dkLen=key_length,
         count=iterations,
         prf=lambda p, s: hmac.new(p, s, hashlib.sha1).digest())
示例#9
0
def decrypt(filename, password):
    print("Decrypting {0}".format(filename))
    chunksize = 64 * 1024
    nonce = 1
    outFile, outFile_extension = path.splitext(filename)
    with open(filename, "rb") as infile:
        with open(outFile, "wb") as outfile:
            salt = infile.read(16)
            key = KDF.scrypt(password, salt, 32, N, r, p)
            while True:
                tag = infile.read(16)
                rchunk = infile.read(chunksize)
                if len(rchunk) == 0:
                    # print('{} chunks used'.format(nonce))
                    break
                try:
                    cipher = AES.new(key, AES.MODE_GCM, bytes(nonce))
                    outChunk = cipher.decrypt_and_verify(rchunk, tag)
                    outfile.write(outChunk)
                    nonce += 1
                except ValueError:
                    print(Fore.RED + "Integrity verification failed. " +
                          "The password is wrong or the file " +
                          "has been modified without authorization. "
                          )
                    input("Press ENTER and try again.")
                    outfile.close()
                    remove(outFile)
                    sys.exit()
示例#10
0
 def encrypt(self, data):
     salt = get_random_bytes(8)  #random salt to calculate the key
     key = KDF.PBKDF2(self.pwd, salt)  #128bit key derivation function
     iv = get_random_bytes(16)  #initialization vector of the chain blocks
     cipher = AES.new(key, AES.MODE_CFB,
                      iv)  #CFB mode does not need message padding
     return salt + iv + cipher.encrypt(data)
示例#11
0
    def main_loop():
        pw_hashed = None
        pw = ''
        print('If you forget the password, all shards that are stored on your')
        print('server will be lost forever.')
        while pw == '':
            try:
                pw = getpass.getpass('Enter the password for Natural ' \
                 + 'Message shard encryption: ')
            except KeyboardInterrupt:
                print()  # move to a new output line
                return (None)

        # The salt is set to zero so that I get the same
        # output every time that I run this because I will
        # use the output here as the password later.
        # This routine is based on the one in RNCryptor (with
        # the salt modified):
        print('Please wait while the password is being hashed.')
        print('You will be prompted to verify the results...')
        pw_hashed = KDF.PBKDF2(
            pw,
            b'00',
            dkLen=32,
            count=iterations,
            prf=lambda p, s: hmac.new(p, s, hashlib.sha256).digest())

        return pw_hashed
示例#12
0
    def get_key(self):
        """
        :return:
        """

        key = KDF.PBKDF2(password=self.password, salt=self.salt, count=100000, dkLen=self.lenght_of_key)
        return key
示例#13
0
 def __generate_derived_key(self):
     """
         generate derived key using initial keying material and salt
     """
     return KDF.PBKDF2(self.ikm + self.config[self.name]['UUID'],
                       self.config[self.name]['salt'],
                       dkLen=16,
                       count=self.config[self.name]['iterations'])
示例#14
0
 def aes_decrypt(self, input_byte, encrypt_key):
     pbk_key_instance = KDF.PBKDF2(encrypt_key,
                                   self.__salt,
                                   dkLen=self.__salt_size,
                                   count=self.__iteration_count)
     pbes_key_cipher = AES.new(pbk_key_instance, AES.MODE_CBC, self.__IV)
     desecret_res = pbes_key_cipher.decrypt(input_byte)
     unpad_byte = Padding.unpad(desecret_res, AES.block_size)
     return unpad_byte
示例#15
0
 def __call__(self, archive):
     print("Deciphering")
     nonce = archive[:16]
     salt = archive[16:16 + 8]
     ctr_aes = Counter.new(128,
                           initial_value=int(binascii.hexlify(nonce), 16))
     key = KDF.PBKDF2(self.password, salt)
     cipher = AES.new(key, AES.MODE_CTR, counter=ctr_aes)
     return cipher.decrypt(archive[16 + 8:])
示例#16
0
	def createAccount(self, request):
		""" Create new custom account """
		status = StringMsg()  # return status
		status.data = 'error'  # default to error

		# Verify if user passed reCAPTCHA
		# POST request to Google reCAPTCHA API
		url = 'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s' % (GRECAPTCHA_SECRET, request.recaptcha)
		try:
			result = urlfetch.Fetch(url, method=2)
		except:
			raise endpoints.BadRequestException('urlfetch error: Unable to POST to Google reCAPTCHA')
			return status
		data = json.loads(result.content)
		if not data['success']:
			status.data = 'recaptcha_fail'
			return status

		user_id = 'ca_' + request.email

		# Get profile from datastore -- if profile not found, then profile=None
		profile_key = ndb.Key(Profile, user_id)
		profile = profile_key.get()

		# If profile exists, return status
		if profile:
			status.data = 'user_exists'
			return status

		# Salt and hash the password
		salt = Crypto.Random.new().read(16)
		passkey = KDF.PBKDF2(request.password, salt).encode('hex')

		salt_passkey = salt.encode('hex') + '|' + passkey

		# Generate new session ID
		session_id = Crypto.Random.new().read(16).encode('hex')

		# Create new profile for user
		Profile(
			key = profile_key,
			userId = user_id,
			contactEmail = request.email,
			salt_passkey = salt_passkey,
			session_id = session_id,
			loggedIn = True,
			emailVerified = False,
			notifications = [False, True]
		).put()

		# Generate user access token
		token = self._genToken({'userId': user_id, 'session_id': session_id})

		# If we get here, means we suceeded
		status.data = 'success'
		status.accessToken = token
		return status
示例#17
0
 def bf_encrypt(self, input_byte, encrypt_key):
     pbk_key_instance = KDF.PBKDF2(encrypt_key,
                                   self.__salt,
                                   dkLen=self.__salt_size,
                                   count=self.__iteration_count)
     pbes_key_cipher = Blowfish.new(pbk_key_instance, Blowfish.MODE_CBC,
                                    self.__IV[0:8])
     pad_byte = Padding.pad(input_byte, Blowfish.block_size)
     secret_res = pbes_key_cipher.encrypt(pad_byte)
     return secret_res
    def decriptInterKey(self, enc):

        # Generate password derived key to encript AES-32 intermediary key
        password_key = KDF.PBKDF2(self.password, self.salt, 32, 1000, None)

        # Start the initializing vector
        iv = open('data/crypto/iv_password_16.txt', 'rb').read()
        # Create the cipher object and process the input stream
        cipher = AES.AESCipher(password_key, AES.MODE_CBC, iv)
        return self.unpad(cipher.decrypt(enc[len(password_key) / 2:]))
示例#19
0
	def changePassword(self, request):
		""" Change password """
		status = StringMsg()
		status.data = 'error'

		# Get user profile
		user_id = self._getUserId(request.accessToken)
		profile_key = ndb.Key(Profile, user_id)
		profile = profile_key.get()

		# Not sure how this would happen, but it would be an error
		if not profile:
			return status

		# Check if provided old password matches user's current password
		db_salt, db_passkey = profile.salt_passkey.split('|')
		passkey = KDF.PBKDF2(request.oldPw, db_salt.decode('hex')).encode('hex')

		# Passwords don't match, return
		if passkey != db_passkey:
			status.data = 'old_pw_wrong'
			return status

		# If passwords match, salt & hash new password
		new_salt = Crypto.Random.new().read(16)
		new_passkey = KDF.PBKDF2(request.newPw, new_salt).encode('hex')
		new_salt_passkey = new_salt.encode('hex') + '|' + new_passkey
		profile.salt_passkey = new_salt_passkey

		# Also generate new session ID
		session_id = Crypto.Random.new().read(16).encode('hex')
		profile.session_id = session_id

		# Update DB
		profile.put()

		# Send user an email to notify password change
		self._emailPwChange(profile)

		# Return success status
		status.data = 'success'
		return status
def decrypt(pwd, msg):
    """
        Decryption function to decrypt ciphertext and return original message

        :param pwd:     decryption key (first 128 bits to be used if longer than 128)
        :param msg:     string to be decrypted
        :return:        plaintext message
    """
    key = KDF.PBKDF2(pwd[:128], msg[:8])  # pwd[:128] truncates key to max 128
    cipher = AES.new(key, AES.MODE_CFB, msg[8:24])
    return cipher.decrypt(msg[24:])
示例#21
0
    def decode_url(self, url):
        """Takes a URL, and returns the cryptographic nonce. Use PBKDF2 with our
        nonce and our salts to return the file name, AES key, and MAC key.

        keyword arguments:
        url -- the url after the FQDN provided by the client"""

        self.url = url
        url = url + "==" # add the padding back
        self.nonce = base64.urlsafe_b64decode(url.encode("utf-8"))
        self.f_key = KDF.PBKDF2(
            self.nonce, dconfig.nonce_salt.decode("hex"), 16)
        self.aes_key = KDF.PBKDF2(
            self.nonce, dconfig.aes_salt.decode("hex"), 32)
        self.mac_key = KDF.PBKDF2(
            self.nonce, dconfig.mac_salt.decode("hex"), 64)
        self.fname = base64.urlsafe_b64encode(self.f_key)[:22]
        if os.path.exists(self.path('dkey')):
            with open(self.path('dkey'), 'r') as dkey:
                self.dkey = dkey.read()
示例#22
0
    def create_url(self):
        """Create a cryptographic nonce for our URL, and use PBKDF2 with our
        nonce and our salts to generate a file name, AES key, and MAC key.

            - 128-bits for the URL
            - 128-bits for file name
            - 256-bits for AES-256 key
            - 512-bits for HMAC-SHA512 key"""

        self.nonce = os.urandom(16)
        self.f_key = KDF.PBKDF2(self.nonce, dconfig.nonce_salt.decode("hex"),
                                16)
        self.aes_key = KDF.PBKDF2(self.nonce, dconfig.aes_salt.decode("hex"),
                                  32)
        self.mac_key = KDF.PBKDF2(self.nonce, dconfig.mac_salt.decode("hex"),
                                  64)
        self.url = base64.urlsafe_b64encode(self.nonce)[:22]
        self.fname = base64.urlsafe_b64encode(self.f_key)[:22]
        if self.exists():
            return self.create_url()
示例#23
0
def decrypt(masterpassword, cipher_dict):
    key = KDF.PBKDF2(masterpassword,
                     b64decode(cipher_dict['mastersalt'].encode('utf-8')),
                     dkLen=32,
                     count=500000)
    cipher_obj = AES.new(key, AES.MODE_CBC,
                         b64decode(cipher_dict['iv'].encode('utf-8')))
    plaintext = cipher_obj.decrypt(
        b64decode(cipher_dict['ciphertext'].encode('utf-8')))
    plaintext = unpad(plaintext, AES.block_size).decode('utf-8')
    return plaintext
示例#24
0
    def __init__(self,
                 db="dojot_devm",
                 dbhost="postgres",
                 dbuser="******",
                 dbpass=None,
                 dbdriver="postgresql+psycopg2",
                 kafka_host="kafka",
                 kafka_port="9092",
                 broker="http://data-broker",
                 subject="dojot.device-manager.device",
                 device_subject="device-data",
                 status_timeout="5",
                 create_db=True,
                 log_level="INFO"):
        # Postgres configuration data
        self.dbname = os.environ.get('DBNAME', db)
        self.dbhost = os.environ.get('DBHOST', dbhost)
        self.dbuser = os.environ.get('DBUSER', dbuser)
        self.dbpass = os.environ.get('DBPASS', dbpass)
        self.dbdriver = os.environ.get('DBDRIVER', dbdriver)
        self.create_db = os.environ.get('CREATE_DB', create_db)
        # Kafka configuration
        self.kafka_host = os.environ.get('KAFKA_HOST', kafka_host)
        self.kafka_port = os.environ.get('KAFKA_PORT', kafka_port)

        # Log configuration
        self.log_level = os.environ.get('LOG_LEVEL', log_level)

        # Data broker configuration
        # Full baseurl of data-broker
        self.data_broker = os.environ.get('BROKER', broker)

        # Which subject to publish new device information to
        self.subject = os.environ.get('SUBJECT', subject)
        self.device_subject = os.environ.get('DEVICE_SUBJECT', device_subject)
        self.status_timeout = int(
            os.environ.get('STATUS_TIMEOUT', status_timeout))

        # crypto configuration
        if not os.environ.get('DEV_MNGR_CRYPTO_PASS'):
            raise Exception(
                "environment variable 'DEV_MNGR_CRYPTO_PASS' not configured")
        if not os.environ.get('DEV_MNGR_CRYPTO_IV'):
            raise Exception(
                "environment variable 'DEV_MNGR_CRYPTO_IV' not configured")
        if not os.environ.get('DEV_MNGR_CRYPTO_SALT'):
            raise Exception(
                "environment variable 'DEV_MNGR_CRYPTO_SALT' not configured")

        salt = os.environ.get('DEV_MNGR_CRYPTO_SALT')
        salt = salt.encode('ASCII')
        password = os.environ.get('DEV_MNGR_CRYPTO_PASS')
        key = KDF.PBKDF2(password, salt, dkLen=16, count=1000, prf=None)
        self.crypto = {'key': key, 'iv': os.environ.get('DEV_MNGR_CRYPTO_IV')}
示例#25
0
def encrypt(masterpassword, plaintext):
    mastersalt = os.urandom(32)
    key = KDF.PBKDF2(masterpassword, mastersalt, dkLen=32, count=500000)
    cipher_obj = AES.new(key, AES.MODE_CBC)
    ciphertext = cipher_obj.encrypt(
        pad(plaintext.encode('utf-8'), AES.block_size))
    iv = cipher_obj.iv
    return {
        'ciphertext': b64encode(ciphertext).decode('utf-8'),
        'iv': b64encode(iv).decode('utf-8'),
        'mastersalt': b64encode(mastersalt).decode('utf-8')
    }
def encrypt(pwd, data):
    """
    Encryption function that encrypts a string using EAS encryption with 128 bit key

    :param pwd:     encryption key (first 128 bits to be used if longer than 128)
    :param data:    string to be encrypted
    :return:        ciphertext
    """
    salt = get_random_bytes(8)
    key = KDF.PBKDF2(pwd[:128], salt)  # pwd[:128] truncates key to max 128
    iv = get_random_bytes(16)
    cipher = AES.new(key, AES.MODE_CFB, iv)
    return salt + iv + cipher.encrypt(data)
示例#27
0
def generate_password_hash(raw_password):
    """Generates a password for a user.

    The value will be stored in the database as a concatenation
    of a random salt and generated hash, separated by a full colon.

    :return: string
    """
    rand = Random.new()
    salt = rand.read(64).encode('hex')
    pass_hash = KDF.PBKDF2(raw_password, salt, dkLen=DK_LEN,
                           count=HASH_ROUNDS).encode('hex')
    return '%s:%s' % (salt, pass_hash)
示例#28
0
	def login(self, request):
		""" Check username/password to login """
		status = StringMsg()  # return status
		status.data = 'error'  # default to error

		# Verify if user passed reCAPTCHA
		# POST request to Google reCAPTCHA API
		url = 'https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s' % (GRECAPTCHA_SECRET, request.recaptcha)
		try:
			result = urlfetch.Fetch(url, method=2)
		except:
			raise endpoints.BadRequestException('urlfetch error: Unable to POST to Google reCAPTCHA')
			return status
		data = json.loads(result.content)
		if not data['success']:
			status.data = 'recaptcha_fail'
			return status

		user_id = 'ca_' + request.email

		# Get profile from datastore -- if profile not found, then profile=None
		profile_key = ndb.Key(Profile, user_id)
		profile = profile_key.get()

		# If profile does not exist, return False
		if not profile:
			return status

		# Parse salt and passkey from DB, compare it to provided version
		db_salt, db_passkey = profile.salt_passkey.split('|')
		passkey = KDF.PBKDF2(request.password, db_salt.decode('hex')).encode('hex')

		# Passwords don't match, return False
		if passkey != db_passkey:
			return status

		# Generate new session ID
		session_id = Crypto.Random.new().read(16).encode('hex')
		profile.session_id = session_id

		# Update user's status to logged-in
		profile.loggedIn = True
		profile.put()

		# Generate user access token
		token = self._genToken({'userId': user_id, 'session_id': session_id})

		# If we get here, means we suceeded
		status.data = 'success'
		status.accessToken = token
		return status
示例#29
0
 def generate_dk(self, token):
     """Generate a defined key for a given token in hex
     >>> c = Credentials()
     >>> c.salt = 'abc'
     >>> c.iterations = 4
     >>> dk = c.generate_dk("password")
     >>> len(dk)
     64
     """
     return KDF.PBKDF2(token,
                       self.salt,
                       dkLen=self.DK_LEN,
                       count=self.iterations +
                       self.ITER_OFFSET).encode('hex')
示例#30
0
    def makeKey(password, salt):
        """
        Makes a key using the inputed password and salt

        Args:
            :param password: Password to hash
            :param salt: Salt used for hash

        Returns:
            bytes: The hashed password.
        """
        return KDF.PBKDF2(
            password, salt, dkLen=32, count=5000, hmac_hash_module=Hash.SHA256
        )