You can do it by using two of the built-in functions on the standard Python library. The first one is the function ord( ), which takes a unicode string character as single input parameter and converts it to its corresponding unicode code (an integer). Two simple examples of the usage of this function are provided:
>>> ord('a')
97
>>> ord('b')
98
Then, you also have the inverse function of ord(): chr( ). And as you can imagine it works all the way around: it has a unicode code as an input (integer) and gets the corresponding unicode character (string):
>>> chr(97)
'a'
>>> chr(98)
'b'
Then you can do a simple encription by adding or substracting by some arbitrary integer... in this case, the number 2:
NOTE: Watch out in not utting very big values or you'll get an error id you reach a negative nber, for example.
def encrypt(message):
newS=''
for car in message:
newS=newS+chr(ord(car)+2)
return newS
print(encrypt('hello world'))
And getting as a result:
jgnnq"yqtnf
Now you can copy and past the same function and generate the decrypt function. In this case, it requires, obviously, to substract by 2:
def decrypt(message):
newS=''
for car in message:
newS=newS+chr(ord(car)-2)
return newS
print(decrypt('jgnnq"yqtnf'))
And the result will be the original message again:
'hello world'
This would be a great way to encrypt messages to non programmers. However, anyone with a little of programming knowledge could write a program that varied the integer we used until they found we have just added (2) to the unicode characters to encrypt the code...
In order to avoid that, I would propose two more complex alternatives.
1. The first one is the simplest: it consists in applying a different sum value to the chr function depending on the position of the character (for example, adding 2 to each unicode code when it occupies an even position in the string and substracting 3 when sits on an odd position).
2. The second one will generate the maximum security. It will consist on adding or substracting every unicode code for a number that will be randomly generated for each character. It will require to store an array of values to decript back the message. Make sure, then, this array of values is not available to third parties.
There it goes a possible solution for 1.:
def encryptHard(message):
newS=''
for i in range(len(message)):
if i%2==0:
newS=newS+chr(ord(message[i])+2)
else:
newS=newS+chr(ord(message[i])-3)
return newS
print(encryptHard('hello world'))
And the result would be:
jbniqyltif
With the information hereby privided the decrypting script is obvious, so I won't bother you with coping, pasing and changing two values.
Finally, let's go into an in-depth-analysis of the second more complex alternative. With this one we can say that the encription will be almost indefitable. The idea is to vary the value we add or substract to each unicode code by a random number comprized between 0 and 255 (this is the range of numbers the chr( ) function admits, so do not try to play with other numbers o you will definitely get an error).
In this case, my proposal also randomizes the operation (sum or subtract), and avoids that the final number be a 0 (i.e. we would get an original character). Finally, its also returns a list with the numers it has been subtracted to, something you will need in order to decrypt the message back.
The chances that you get the same encrypted message if you call two times this function using the same message of length n are somewhat near to 255^n... So don't worry (I say somewhat, as the algorithm created would actually generate more repeated values on the low-end or high-end range of values, for example, in case the most frequent characters were not centered in this distrubution unicode caracrer set (from 0 to 255), which is the case. However, the program, though not perfect, works flawlessly and protects the information.
import random as r
def encryptSuperHard(message):
newS=''
l_trans=[]
for car in message:
code=ord(car)
add_subtract=r.choice([True,False])
if add_subtract:
transpose=r.randint(0,code-1)
newS=newS+chr(code-transpose)
l_trans=l_trans+[-transpose]
else:
transpose=r.randint(code+1,255)
newS=newS+chr(code+transpose)
l_trans=l_trans+[transpose]
return newS, l_trans
print(encryptSuperHard('hello world'))
In this case, this random encrypting script I've made has returned this two value tuple, where the first value is the encrypted message and the second one is the value that has "transposed" every character in order of apearance.
('A0ŤłY\x10řG;,à', [-39, -53, 248, 214, -22, -16, 226, -40, -55, -64, 124])
Decrypting, in this case would need to take the encrypred message and the list and proceed as follows:
def decryptSuperHard(encriptedS,l):
newS=''
for i in range(len(l)):
newS=newS+chr(ord(encriptedS[i])-l[i])
return newS
print(decryptSuperHard('A0ŤłY\x10řG;,à', [-39,-53,248,214,-22,-16,226,-40,-55,-64,124]))
And the results goes back to:
hello world
print(deccryptSuperHard('A0ŤłY\x10řG;,à', [-39, -53, 248, 214, -22, -16, 226, -40, -55, -64, 124])
pycrypto
for the encryption itself and perhapsbase64
to get a string representation of the result. – Choate