Encryption via multiplication of hex-converted, multiplied ASCII values The idea behind the encryption is that it stores the key within the final encrypted password. When the user inputs a password for the first time, they also have to pick an element from a list of elements, and that determines where in the final, encrypted password the key is stored.

This is crucial for decryption. 

The algorithm proceeds as follows: 


User inputs a password.


The password is split into the individual characters, then stored in a list.

User inputs a key. (The key corresponds to an element in a list in the program, either 1, 2 or 3)
Each character in the list is translated into its ASCII number, and the original list is overwritten.
Each ASCII number is then multiplied by a random number.


The random number is stored as the variable x.

Each multiplied number is then converted into hex.
Random hex values are added to either side of the already encrypted password. 
The element of the list that corresponds to the key (random_key) is replaced by the hex value of x.
The final encrypted password is stored in a file. 


Note: Decryption is possible, but, I'm still working on it. 

import random
import getpass

def joinit(iterable, delimiter):
    it = iter(iterable)
    yield next(it)
    for x in it:
        yield delimiter
        yield x

password = getpass.getpass('Please input a password.\n')
lst = []
key = input('Please pick a list number. Write it down!!')
random_key = [1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4]
for i in range(0, len(password)-1):
    lst.append(ord(password[i]))
print lst
x = random.randint(1,1000)
for i in range(0, len(password)-1):
    lst[i] *= x
for i,z in enumerate(lst):
        lst[i] = hex(z)
print lst
i = 2
lst2 = []

for i in range(0,4):    
    hexhex = random.randint(1000,2000)
    hex(hexhex)
    lst.insert(0,hex(hexhex))
    print hexhex
for i in range(0,4):
    hexhex = random.randint(1000,2000)
    hex(hexhex)
    lst.append(hex(hexhex))
    print hexhex
lst[key] = hex(x)
result = []
for e in lst:
    result.append(e)
    result.append('|')
result.pop()

penultimate = ''.join(str(v) for v in result)
print result
print '\n'*3
print penultimate
file = '/home/vhx/Documents/code/tkinter/encryption/password.txt'
target = open(file, 'w')
target.truncate()
target.write(penultimate)


I designed this encryption method for a login system that encrypts the inputted password before comparing it to the one stored in the file. This way the password is never decrypted, and thus cannot (hopefully) be stolen. 

I have a few questions:


Can the code be made any more efficient? Is there anything in there that can be simplified or removed altogether?
Is the idea itself sound (security wise)?
Has something like this been tried before?
I don't do security.
The information is provided as if this were not a security problem.

First things first. Python's random number generation is pseudo-random.
The source code is really small, and consisted of iirc 4 %.

If we look at the docs for what this may mean on your security.


  Warning: The pseudo-random generators of this module should not be used for security purposes.
  Use os.urandom() or SystemRandom if you require a cryptographically secure pseudo-random number generator.


That instantly destroys all the security of this security program.



Style



PEP8


There should be two blank lines either side of top level functions or classes.
You need white space after commas. [1, 2].
random_key = [1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4]
You should have one space either side of operators. 2 * 2.
The exception to this is so show precedence. 2*2 + 2.
'\n'*3




General style

You should use better variable names. x is not descriptive. lst and lst2 don't 'say' what they do.

When using range 0 is the default value for start. range(0, len(password)-1) == range(len(password)-1).

You should not have all your code in the top level of the program. As a minimum you should wrap it in a if __name__=='__main__':. And then you should have it so that it calls main().



Code



There are two features of the language that you should really like.

1. List comprehensions.

lst = []
for i in range(0, len(password)-1):
    lst.append(ord(password[i]))


Using a list comprehension, you can simplify this.

lst = [
    ord(password[i])
    for i in range(len(password)-1):
]


You can then just slice the string.

lst = [ord(char) for char in password[:-1]]




2. str.join:

result = []
for e in lst:
    result.append(e)
    result.append('|')
result.pop()


This can simply be reduced to

result = '|'.join(str(char) for char in lst)




Conclusion

If we simplify everything, and remove the prints, we get the following:

def get_hexes():
    return [hex(random.randint(1000,2000)) for _ in range(4)]

password = getpass.getpass('Please input a password.\n')
key = input('Please pick a list number. Write it down!!')
x = random.randint(1,1000)

lst = get_hexes() + [hex(ord(char) * x) for char in password[:-1]] + get_hexes()
lst[key] = hex(x)
result = '|'.join(str(char) for char in lst)

path = '/home/vhx/Documents/code/tkinter/encryption/password.txt'
with open(file, 'w') as target:
    target.truncate()
    target.write(result)


From this, we can tell easily, that it's not that secure.
You know that the | and the first and last 4 sections are just red herrings.
This is as they are always just there and we can ignore them.
And there is a lot more noise than needed, 0x.

And, the password will always have a character missing, and can have another missing.

I think the best example of a good password and list number is aa and 5. This is as then my password will be any two letters. All I need to remember is 5.

Also, you can tell when the key is in the first or last 4 sections, this is as the minimum for them are 1000, where the maximum for the key is 1000.



If you want better feedback on your algorithm, go to the cryptography site.