Hey, I have been working on this for a while, and I can remebr my brother stepped me through this very same alogorithm.
Basicly, it just adds the ascii values of both the characters from the key, and the phrase.
I can encrypt it with this:
def encrypt(key, string):
encoded = ''
for i in range(len(string)):
key_c = ord(key[i % len(key)])
string_c = ord(string[i % len(string)])
encoded += chr((key_c + string_c) % 127)
return encoded
But I can't seem to remember what we did as far as decrypting. Its difficult to revers a mod :P
Any ideas?
That's simple, let's see how it works. First of all, the encrypted message is obtained by subtracting the key.
enc = msg + key (mod 127)
How can we obtain the original message? That's easy, subtract the key in both sides
enc - key = msg + key - key (mod 127)
And here we get:
enc - key = msg (mod 127)
For more details, please refer to Modular arithmetic, I think it should belong one of group/field/ring. I'm not an expert in math, for further reading, you should check out Number theory. Here is the refined code:
def encrypt(key, msg):
encryped = []
for i, c in enumerate(msg):
key_c = ord(key[i % len(key)])
msg_c = ord(c)
encryped.append(chr((msg_c + key_c) % 127))
return ''.join(encryped)
def decrypt(key, encryped):
msg = []
for i, c in enumerate(encryped):
key_c = ord(key[i % len(key)])
enc_c = ord(c)
msg.append(chr((enc_c - key_c) % 127))
return ''.join(msg)
if __name__ == '__main__':
key = 'This_is_my_awsome_secret_key'
msg = 'Hello world'
encrypted = encrypt(key, msg)
decrypted = decrypt(key, encrypted)
print 'Message:', repr(msg)
print 'Key:', repr(key)
print 'Encrypted:', repr(encrypted)
print 'Decrypted:', repr(decrypted)
Output
Message: 'Hello world'
Key: 'This_is_my_awsome_secret_key'
Encrypted: '\x1dNV`O\nkO`fD'
Decrypted: 'Hello world'
Decryption is the same, except with minus instead of plus.
But you do not need to inverse the mod, just the + key_c, right? So just add 128, subtract key_c, and do modulo 127 again to keep in range. (instead of the last line, all the other lines are the same as with encrypting.
Related
I am trying to decrypt an AES CBC string for the number of times it was decrypted.
I was successful in decrypting the first time.
from Crypto.Cipher import AES
k = '57067125438768260656188878670043'
key = bytes(k, 'ascii')
i = '5706712543876826'
iv = bytes(i, 'ascii')
dec = AES.new(key, AES.MODE_CBC, iv)
n = 2
cipher = 'dd3364461dbca39ddb5eb32e9f11b81f000acac9ce8b91369f8bf7e4a88787785a8cc498c85ea20370e68f0e7014e92a2b5aedd4c670ec172d7adb45dfa5a770b582e8ed255bb857d94afdfd6e579525f24890070f984b8862133eda9cbb118ba7880db125c32dea7e7c54bc77abfc02'
def unpad(s):
return s[:-ord(s[len(s)-1:])]
def decrypt(cipherId):
cipher = bytes.fromhex(cipherId)
id = dec.decrypt(cipher)
node_dec = unpad(id.decode('utf-8'))
print (node_dec)
return node_dec
that is the first stage of encryption, but I don't know how to set a loop to run the function again based on n. this cipher for example was encrypted twice, it might be three or four or more.
I created another function to decrypt the output of the decrypt function because the output gives a different codec.
def decrypt_again(cipherId):
cipher = bytes.fromhex(cipherId)
id = dec.decrypt(cipher)
node_dec = unpad(id.decode('ISO-8859-1'))
print (node_dec)
return node_dec
so I tried writing this loop
x = decrypt(cipher)
for i in range (n):
y = decrypt_again(x)
but it only works for n = 1, if n is more than 1, it just keeps repeating y instead of parsing it again.
how can I go about it, please?
also if I re-run the function twice something happens to the string, I get ó³*Ä'»g)X»#¾ú84-8089-be57330fcd45 instead of this a214868d-f40b-4184-8089-be57330fcd45, there seem to be a break in the codec
any reason why this is so?
every time it sets y to decrypt_again(x), x is still the same so you should add a line that sets x to y so it remembers the result of the previous iteration
x = decrypt(cipher)
for i in range (n):
y = decrypt_again(x)
x = y
so guys I was able to solve the issue. here is the correct code that works top-notch.
from Crypto.Cipher import AES
k = '57067125438768260656188878670043'
key = bytes(k, 'ascii')
i = '5706712543876826'
iv = bytes(i, 'ascii')
n = 4
cipher = 'afc6f435d3bb68234bba2d39840d4c61cd0d45810940cf796ebf4078e1c0b2368caf618dd6c915fa3f9e0245372cc0dd9992d71aa3ac9e811a579a1d39fa9e26b0d1728d290f4bfa54931917afb45c49a815937498923e241a3eded50dff67ff18d9c1259404f1bdbafef7df5aba0c0b2aacc18079b6bb64058a7976246c0231b2178312c9a008dfa3bd954eef12c73d0b3adac8aa2f4733fe09767dc08741997a6243642d7a5fc627eede9fbeea9f9d931f90daa1cc6a760e352a36d55f22ea1a8bb4bd993d96f4cd006ad9de128d7ea9cd74b875ac2c55e62905b67eb354b5bac48961940fbdc1c0dc58ebc3b7356cb95c11505c8d9bbecc8670d7327ed5fcffd3577ed7d87adf628c5b44cb92c1e33f66715d2d429d3a62dc88a80fc3a3b4a720e9680b4ff444d4e87057a7fbe66afba6bffd96b641bfb03c0802528e30768c5695db92d0dd4f4db3d5301c17ed37accbe3c89d2c70d4fbb3e40d30164b640154fa9ecd5565b11af24f40fe91fbca3966ce1632a3dbbd6c1af432b2100a9f7136834fc00609170b6cf66a3861bf9aa1902292152ba6efdefeacc4d4d37e20896a42243f3ec2f4ae463cfa455e92d4df33688cb127ade64dbad056b1614fe2f2a32b0b2536a23f4b019511df378778c374413629e7afe83a047fe6745de19397193e7082f8ab27b4b41695f43abd9c'
def unpad(s):
return s[:-ord(s[len(s)-1:])]
def decrypt(cipherId):
dec = AES.new(key, AES.MODE_CBC, iv)
cipher = bytes.fromhex(cipherId)
id = dec.decrypt(cipher)
node_dec = unpad(id.decode('ISO-8859-1'))
return node_dec
if __name__ == '__main__':
x = decrypt(cipher)
result = ""
for i in range(n - 1):
y = decrypt(x)
x = y
result = x
print(result)
key = "password"
def cipher(text): #my example cipher method
encoded_chars = []
for i in range(len(text)):
key_c = key[i % len(key)]
encoded_c = chr(ord(text[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = ''.join(encoded_chars)
return (encoded_string)
def decipher(text):
dec = []
text = base64.urlsafe_b64encode(b"'{text}'").decode()
print('text')
for i in range(len(text)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(text[i]) - ord(key_c)) % 256)
dec.append(text)
return str(dec_c)
enter code here
print(decipher("test"))
After encrypting it successfully with vigenere cipher I get something like this: b'\xc2\xbd\xc2\xb8\xc3\x83\xc3\x80'
I would like to decrypt this string with the code above and turn it into back to the text "password" however when I try to decrypt my text it leaves me with another encoded string. Can someone explain what I am doing wrong with my decryption?
It's not clear what you are trying to do with the base64 library. Also, you are mixing up come variables in your decrypt method:
dec.append(text) # text is the passed in argument.
# Why append it to the result
return str(dec_c) # this is the last element in the loop
# why return this rather than the list you made above?
Neither of the above things make much sense. Maybe something like this will get it going in the right direction:
key = "password"
def cipher(text): #my example cipher method
encoded_chars = []
for i in range(len(text)):
key_c = key[i % len(key)]
encoded_c = chr(ord(text[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = ''.join(encoded_chars)
return (encoded_string)
def decipher(text):
dec = []
for i in range(len(text)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(text[i]) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
plain = "some text to encrypt"
encrypted = cipher(plain)
print("encrypted: ", encrypted)
decrypted = decipher(encrypted)
print("decrypted: ", decrypted)
Prints:
encrypted: ãÐàØã×ÜäçâÔàÇâÚãç
decrypted: some text to encrypt
I want to implement the hmac algorithm with SHA-1 by the definition from RFC 2104. The code is running but the results aren't the same as the test-vectors from RFC. I'm not sure if I'm loading the values correctly(String to Hex, or String to Bytes?).
As template I've used the pseudo-code from wikipedia
I'm not sure about the terms 'blocksize' and 'output size'. In the code from wikipedia the outputsize is one of the input values but never used.
This is my code so far:
First I'm setting up a hash-function, then I'm converting my input-strings (key and message) into hex values. Next step is to to look if key hast go get hashed or filled with zeros. Next I'm xor-ing the single chars from the key with those values (I don't know where they come from, but they're in every example without any comment). Last but not least I'm combining an inner string(I_key_pad + message) and hash it which results in an outer strings that im combining with the outer pad and hash it again.
import hashlib
from functools import reduce
def hmac(key, message, hashfunc):
hasher = hashlib.sha1
blocksize = 40
message = toHex(message) #is this right?
key = toHex(key)
#alternative: loading values as bytes
#message = bytes(message, 'utf-8')
#key = bytes(key, 'utf-8')
if len(key) > blocksize:
key = hasher(key)
else:
#key = key.ljust(blocksize, '0') #filling from right to left
#key = key.ljust(blocksize, b'\0') #same as above but for bytes
key = pad(key, blocksize) #filling from left to right
val1 = 0x5c
val2 = 0x36
i = 0
o_key_pad = ""
i_key_pad = ""
while i < blocksize:
o_key_pad += str(ord(key[i]) ^ val1)
i_key_pad += str(ord(key[i]) ^ val2)
i += 1
tmp_string = str(i_key_pad) + str(message)
tmp_string = tmp_string.encode()
inner_hash = hasher(tmp_string).hexdigest()
fullstring = str(o_key_pad) + inner_hash
fullstring = fullstring.encode()
fullstring = hasher(fullstring).hexdigest()
print(fullstring)
def pad(key, blocksize):
key = str(key)
while len(key) < blocksize:
key = '0' + key
key = key
return key
def toHex(s):
lst = []
for ch in s:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)
def main():
while (1):
key = input("key = ")
message = input("message = ")
hash = input("hash (0: SHA-256, 1: SHA-1) = ")
hmac(key, message, hash)
if __name__ == "__main__":
main()
I'm not understanding all the steps in your code, but here's a short example showing HMAC-SHA1 using only hashlib.sha1, with a helper function xor.
import hashlib
def xor(x, y):
return bytes(x[i] ^ y[i] for i in range(min(len(x), len(y))))
def hmac_sha1(key_K, data):
if len(key_K) > 64:
raise ValueError('The key must be <= 64 bytes in length')
padded_K = key_K + b'\x00' * (64 - len(key_K))
ipad = b'\x36' * 64
opad = b'\x5c' * 64
h_inner = hashlib.sha1(xor(padded_K, ipad))
h_inner.update(data)
h_outer = hashlib.sha1(xor(padded_K, opad))
h_outer.update(h_inner.digest())
return h_outer.digest()
def do_tests():
# test 1
k = b'\x0b' * 20
data = b"Hi There"
result = hmac_sha1(k, data)
print(result.hex())
# add tests as desired
I have a program that successfully encrypts a piece of plain text information and outputs the encrypted data as hexadecimal. i can decrypt this data on http://www.fyneworks.com/encryption/rc4-encryption/index.asp by putting in the hex data i received from my program and the key i used (in plain text)
the next step i am trying to accomplish is to have two inputs where i can input an encrypted message in hex and the encryption key (also in hex).
i'm having trouble getting the decryption part of my program to work...
If i enter the key as password and the ciphertext as 8c905b7c294a94c30422d81d552e which successfully decrypts on the website above... it doesn't work.
anyone have any ideas how i can get decryption working in RC4 with hexadecimal inputs?
# Global variables
state = [None] * 256
p = q = None
def setKey(key):
##RC4 Key Scheduling Algorithm (KSA)
global p, q, state
state = [n for n in range(256)]
p = q = j = 0
for i in range(256):
if len(key) > 0:
j = (j + state[i] + key[i % len(key)]) % 256
else:
j = (j + state[i]) % 256
state[i], state[j] = state[j], state[i]
def byteGenerator():
##RC4 Pseudo-Random Generation Algorithm (PRGA)
global p, q, state
p = (p + 1) % 256
q = (q + state[p]) % 256
state[p], state[q] = state[q], state[p]
return state[(state[p] + state[q]) % 256]
def encrypt(key,inputString):
##Encrypt input string returning a byte list
setKey(string_to_list(key))
return [ord(p) ^ byteGenerator() for p in inputString]
def decrypt(inputByteList):
##Decrypt input byte list returning a string
return "".join([chr(c ^ byteGenerator()) for c in inputByteList])
def intToList(inputNumber):
##Convert a number into a byte list
inputString = "{:02x}".format(inputNumber)
return [int(inputString[i:i + 2], 16) for i in range(0, len(inputString), 2)]
def string_to_list(inputString):
##Convert a string into a byte list
return [ord(c) for c in inputString]
key = raw_input("Enter Key: ")
ciphertext = raw_input("enter ciphertext: ")
print decrypt(intToList(ciphertext))
Here is general idea of how encryption / decryption can be done using reference implementation of RC4 for python:
def KSA(key):
keylength = len(key)
S = range(256)
j = 0
for i in range(256):
j = (j + S[i] + key[i % keylength]) % 256
S[i], S[j] = S[j], S[i] # swap
return S
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # swap
K = S[(S[i] + S[j]) % 256]
yield K
def RC4(key):
S = KSA(key)
return PRGA(S)
if __name__ == '__main__':
# ciphertext should be 9D5AB375EC
key = 'secret'
plaintext = 'plain'
def convert_key(s):
return [ord(c) for c in s]
key = convert_key(key)
keystream = RC4(key)
ciphertext = ''.join([("%02X" % (ord(c) ^ keystream.next())) for c in plaintext])
print ciphertext
keystream = RC4(key)
def convert_ct(s):
import binascii
return [ord(ch) for ch in binascii.unhexlify(s)]
ciphertext = convert_ct(ciphertext)
plaintext = ''.join([chr(c ^ keystream.next()) for c in ciphertext])
print plaintext
With your code base it can be done like so:
import binascii
# Global variables
state = [None] * 256
p = q = None
def setKey(key):
##RC4 Key Scheduling Algorithm (KSA)
global p, q, state
state = [n for n in range(256)]
p = q = j = 0
for i in range(256):
if len(key) > 0:
j = (j + state[i] + key[i % len(key)]) % 256
else:
j = (j + state[i]) % 256
state[i], state[j] = state[j], state[i]
def byteGenerator():
##RC4 Pseudo-Random Generation Algorithm (PRGA)
global p, q, state
p = (p + 1) % 256
q = (q + state[p]) % 256
state[p], state[q] = state[q], state[p]
return state[(state[p] + state[q]) % 256]
def encrypt(key, plaintext):
##Encrypt input string returning a byte list
pt = string_to_list(plaintext)
ct = rc4(key, pt)
return list_to_string(ct, hex=True)
def decrypt(key, ciphertext):
##Decrypt input byte list returning a string
ct = string_to_list(ciphertext, hex=True)
pt = rc4(key, ct)
return list_to_string(pt, hex=False)
def string_to_list(input_srt, hex=False):
##Convert a string into an int list
if hex:
res = [ord(ch) for ch in binascii.unhexlify(input_srt)]
else:
res = [ord(ch) for ch in input_srt]
return res
def list_to_string(lst, hex=True):
##Convert an int list into a string
if hex:
res = ''.join(["%0.2X" % el for el in lst])
else:
res = ''.join([chr(el) for el in lst])
return res
def rc4(key, ints):
"""Xor list of ints with output generated by RC4. Output list of ints"""
setKey(string_to_list(key))
return [x ^ byteGenerator() for x in ints]
# key = raw_input("Enter Key: ")
# ciphertext = raw_input("enter ciphertext: ")
key = 'secret'
plaintext = 'plain'
ciphertext = encrypt(key, plaintext)
print ciphertext
print decrypt(key, ciphertext)
Decryption and encryption are basically the same procedures
I am trying to make a python program that will take in plain text and encrypt it using a key. It is written with python 2.7.4
This is my code so far
def encrypter(intext, shift, modder):
plain = list(intext)
out = ''
j = 0
key = list(shift)
for i in plain:
if mod > 0:
x = chr((ord(i) + ord(key[(j % (len(plain) - 1)) % len(key)]) - 48) % 58 + 48)
if mod < 0:
x = chr(((ord(i) - ord(key[(j % (len(plain) - 1)) % len(key)]) - 48) % 58 + 48))
out += x
j += 1
return out
sel = raw_input("Encrypt (e)/ Decrypt (d)")
if sel == 'e':
mod = 1
elif sel == 'd':
mod = -1
else:
mod = 0
print('Enter a proper value!')
if mod != 0:
print(encrypter(raw_input('Enter the text:'), raw_input('Enter the key-phrase:'), mod)
When I encrypt something I get this:
C:\Users\aesha_000\py\Scripts\python.exe "D:/Programming/Computing GCSE/Resources/functiontest3.py"
Encrypt (e)/ Decrypt (d)e
Enter the text:alex
Enter the key-phrase:pass
]Yd:
Process finished with exit code 0
But the problem is when I then Decrypt it again I get the wrong output:
C:\Users\aesha_000\py\Scripts\python.exe "D:/Programming/Computing GCSE/Resources/functiontest3.py"
Encrypt (e)/ Decrypt (d)d
Enter the text:]Yd:
Enter the key-phrase:pass
a2e>
Process finished with exit code 0
Does anyone know the answer to this or am I just being stupid?
You should remove % 58 + 48.
I'm assuming you're using it for having printable ascii chars, but you should not. You're loosing information.
If you want to display "not printable ascii chard", use base64.