1
\$\begingroup\$

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:

  1. User inputs a password.

    1. The password is split into the individual characters, then stored in a list.
  2. User inputs a key. (The key corresponds to an element in a list in the program, either 1, 2 or 3)

  3. Each character in the list is translated into its ASCII number, and the original list is overwritten.

  4. Each ASCII number is then multiplied by a random number.

    1. The random number is stored as the variable x.
  5. Each multiplied number is then converted into hex.

  6. Random hex values are added to either side of the already encrypted password.

  7. The element of the list that corresponds to the key (random_key) is replaced by the hex value of x.

  8. 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:

  1. Can the code be made any more efficient? Is there anything in there that can be simplified or removed altogether?

  2. Is the idea itself sound (security wise)?

  3. Has something like this been tried before?

\$\endgroup\$
  • 2
    \$\begingroup\$ I’m no security expert, but I’m pretty sure the answer to “Is my home-brew security system secure?” is almost always “No, don’t roll your own security”. \$\endgroup\$ – alexwlchan Jul 14 '15 at 5:55
  • \$\begingroup\$ Why ASCII? Why not one of the many other character codings? \$\endgroup\$ – Toby Speight Nov 1 '17 at 13:19
  • \$\begingroup\$ Well , this was almost 3 years ago. I was still learning a lot about programming, and ASCII was something I was more familiar with. I gotta ask though, how did you end up on this question? :P \$\endgroup\$ – Joseph Farah Nov 1 '17 at 17:13
4
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thanks very much! Very descriptive answer. Can you please suggest a place where I can learn more about if __name__=='__main__': ? I have seen that it is useful but the sites I found that explained it were in most cases confusing and in others, downright unhelpful. Also, regarding the random hex values at the beginning and end--the factor that the ASCII values are multiplied by is stored in there. Thanks again! XD \$\endgroup\$ – Joseph Farah Jul 15 '15 at 14:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.