3 Replies - 1460 Views - Last Post: 25 November 2012 - 01:24 PM Rate Topic: -----

#1 Highest bidder  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 23-November 12

Python Crypto: CTR decryption

Posted 23 November 2012 - 11:06 AM

I have a problem understanding how the CTR works, hope you can help me out. I have wrote a program that encrypts and decrypts (ECB, CBC and OFB) in DES, however while I can encrypt in CTR i cant decrypt it back... Among many of my tries my most often received error is this : "ValueError: 'counter' parameter must be a callable object"

I will post part of the code here because it is to big but you can find the whole thing in the attached file! Also please bear with the bad code since i am a newbie in python and programming in general...

my sources for the CTR so far were: source 1 source 2

But they wont work for the decryption


class Secret(object):
  def __init__(self, secret=None):
    if secret is None: secret = os.urandom(8)
    self.secret = secret
    self.reset()
  def counter(self):
    for i, c in enumerate(self.current):
      self.current[i] = c + 1
      if self.current: break
    return self.current.tostring()
  def reset(self):
    self.current = array.array('B', self.secret)

#[...] get keys, PT, CT and confusing stuff [...]

ctr = secret.counter
des = DES.new(key, DES.MODE_CTR, counter = ctr)
output_txt = des.encrypt(input_txt)




Thanks in advance!

Attached File(s)



Is This A Good Question/Topic? 0
  • +

Replies To: Python Crypto: CTR decryption

#2 Python_4_President  Icon User is offline

  • D.I.C Regular

Reputation: 53
  • View blog
  • Posts: 321
  • Joined: 13-August 11

Re: Python Crypto: CTR decryption

Posted 25 November 2012 - 12:18 AM

Arg, I've banged my head on your code for several hours and was not able to get CTR to decrypt anything successfully. (but I got it to stop crashing, at least)

I think, technically, the problem boils down to your encoding/decoding strings and inconsistent counters.

For example, in the decrypt startup code, you say:

elif function_choice == 2:
	f_c = open("cipher.txt", "r+", 255)
	f_k = open("key.txt", "r+", 255)
	f_iv = open("iv.txt", "r+", 255)
	f_ctr = open("counter.txt", "r+", 255)
	f_p = open("plain.txt", "w+", 255)
	key = f_k.read().encode("hex")
	iv = f_iv.read()
	ctr = f_c.read()
	my_decry_txt = ''
	cipher_txt = ''

        cipher_txt = f_c.read().decode("hex")



Take a look at ctr and cipher_txt.

BIG problem right here.

A.) I think ctr is short for "counter" which means it, in theory, should not contain cipher text.

However, you put the contents of cipher.txt there.

Further, cipher_txt probably should contain some value, but after you file.read() you read all the contents of a file and are now at the end of the file, so further calls to file.read() return nada.

example:

open("test.txt", 'w').write("Hello World!")
newFile = open("test.txt", 'r')
print newFile.tell() #this is the position you're at in the file
fileText = newFile.read()
print newFile.tell() #12, the end
print fileText
fileText = ""
#still at position 12
fileText = newFile.read()
print fileText #nothing, as expected. 



You CAN do file.seek(0) and set it back to the beginning, but, like I said, ctr probably isn't supposed to contain cipher text.

Also, the encode("hex") decode("utf_32_le") thing is probably wishful thinking.


My suggestion: Build up each component one at a time, and get each piece working the way you want before moving to the next. (especially when encoding and decoding things!)
Try and make things as simple for yourself (thus others) as you possibly can. Ask DIC for assistance in simplifying things.

If I'm right, you were so excited to have things work at all, that you decided to keep going and going in spite of the increasing challenge presented by your code base. When you notice that the hill is getting steeper the further up you go, you can rest assured that something is not right in the universe, and you should try and find another path to take.

This post has been edited by Python_4_President: 25 November 2012 - 12:41 AM

Was This Post Helpful? 1
  • +
  • -

#3 Highest bidder  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 19
  • Joined: 23-November 12

Re: Python Crypto: CTR decryption

Posted 25 November 2012 - 04:52 AM

View PostPython_4_President, on 25 November 2012 - 12:18 AM, said:

Arg, I've banged my head on your code for several hours and was not able to get CTR to decrypt anything successfully. (but I got it to stop crashing, at least)


Apart from the CTR did the rest worked fine for you?

Python_4_President said:

Take a look at ctr and cipher_txt.
BIG problem right here.
A.) I think ctr is short for "counter" which means it, in theory, should not contain cipher text.


Haha, you are right i feel a little embarrassed now, but all i wanted is to up load the code as fast as i could to get a solution because i was angry and ready to blow!

Thank you very much for taking notice of my post i had become desperate at some point because it seemed no one could give me solution or even a tip(neither here or on some other forums), anyway... After many hours of reading and searching i managed to find a solution but because no1 seemed to care, i didn't upload it but since you are here now and because you went through a lot of trouble trying to read my code here is what i came up with:

1st) counter needs a starting point each time you call it, (so you have the same start counter for the encry and decry)
i used the IV as starting point so i called the counter like that:
 ctr = Counter.new(64, initial_value=long(iv.encode("hex"), 16)) 

instead of the Secret class

2nd) because of the above you no longer need the counter.txt but IV.txt instead THO if you are gonna use it in a real life scenario iv and thus counter should start from a random point.

3rd) for my program to work the txt files that you are gonna use as input need to have only 1 line and only containing the needed info for example: good example of PT:"pokemon"
bad example of PT:" the plain text is: pokemon"
same for CT, key and IV.
that's is why this:
cipher_txt = f_c.read().decode("hex")

dint worked out for you (i guess) its a huge bug i know...

4th) Key has to be 4 chars long (since later the program will turn it to hex 8 chars long)

5th) when decrypting plain-text it may end up having one or two null characters at the end. (null for the notepad++ for another word prepossessing program the result my be different.

Anyhow the new code works fine on my machine, (probably for yours too) i will upload for anyone who is interested!
hope you like it! :)/>

important summary:
key -> length = 4, alphanumeric
IV -> length = 8, numeric (used by all except ECB)
PT -> length = whatever you want, alphanumeric
CT -> length = whatever you want, hexadecimal

a small CTR demonstration:
key = coco
IV = 87654321
CT = ae9b747e47851fc902bead28ebeda29c4ae47bef761ac2bb1af4261932cda4e7

after decryption:
PT = Plain text: V for Vendetta!

Attached File(s)


Was This Post Helpful? 1
  • +
  • -

#4 Python_4_President  Icon User is offline

  • D.I.C Regular

Reputation: 53
  • View blog
  • Posts: 321
  • Joined: 13-August 11

Re: Python Crypto: CTR decryption

Posted 25 November 2012 - 01:24 PM

Interesting...
>>> d = DES.new("cocococo", DES.MODE_CTR, counter=lambda:"".join([str(x) for x in range(0,8)]))
>>> d.encrypt("test")
'Nm\x84@'
>>> d.decrypt("Nm\x84@")
'k\x1a\x8f\xe3'
>>> d.decrypt("Nm\x84@")
'test'



This happens consistently. I wonder why the first decrypt produces jibberish but the second is the right answer?


Ahh, clearly I need to have a look at the DES source to figure that one out. I'm guessing two blocks are being used sequentially, and will reset once the second one passes.

I think that because:
>>> d = DES.new("cocococo", DES.MODE_CTR, counter=lambda:"".join([str(x) for x in range(0,8)]))
>>> d.encrypt("test")
'Nm\x84@'
>>> d = DES.new("cocococo", DES.MODE_CTR, counter=lambda:"".join([str(x) for x in range(0,8)]))
>>> d.decrypt("Nm\x84@")
'test'






EDIT: COOL!
from Crypto.Cipher import DES
class crypt(object):
	def __init__(self):
		self.iv = lambda:"".join([str(x) for x in range(0, 8)])
	def CTR(self, message, key, enc = True):
		des = DES.new(key, DES.MODE_CTR, counter=self.iv)
		if enc:
			return des.encrypt(message)
		return des.decrypt(message)



if __name__ == "__main__":
	message = raw_input("Message to Encrypt: ")
	while True:
		password_8_byte = raw_input("Enter 8 bytes for password: ")
		if len(password_8_byte) == 8: break
	print "Before encryption: ", message
	enc_message = crypt().CTR(message, password_8_byte)
	print "After encryption: ", enc_message
	dec_message = crypt().CTR(enc_message, password_8_byte, enc=False)
	print "After decryption: ", dec_message 	




devman@ANDPWN:~$ python mycrypt.py
Message to Encrypt: DIC is the best!
Enter 8 bytes for password: DICthbst
Before encryption:  DIC is the best!
After encryption:  ����e��PӾ��i��
After decryption:  DIC is the best!






EDIT(again) :bigsmile: I like cryptography.
from Crypto.Cipher import DES
import sys, os
class crypt(object):
	def __init__(self, key = None, plain_text = None, cipher_text = None, output_file = None, mode = None):
		if not key or len(key) != 8: raise Exception("Please supply a key of length 8.")
		self.plain_text = self.file_or_text(plain_text) if plain_text else plain_text
		self.cipher_text = self.file_or_text(cipher_text) if cipher_text else cipher_text
		
		message, direction = self.find_direction(self.plain_text, self.cipher_text)
		algorithm = self.find_algorithm(mode)
		self.ofile = output_file
		self.iv = lambda:"".join([str(x) for x in range(0, 8)])
		print "*"*20+"\nMessage:{0}\nKey:{1}\nDirection:{2}\nAlgorithm:{3}\noutput file:{4}\nIV:{5}\n".format(message, key, direction, algorithm, self.ofile, self.iv())+"*"*20
		self.distribute_message(algorithm(key, message, direction))

	def find_algorithm(self, mode):
		if not mode:
			raise Exception("Please supply a mode.")
		if mode.lower() == "ctr":
			return self.CTR
		else:
			return self.not_implemented
			
	def not_implemented(self, **kwargs):
		raise Exception("Not implemented.")

	def find_direction(self, pt, ct):
		if pt and not ct:
			return pt, True
		elif ct and not pt:
			return ct, False
		elif ct and pt:
			raise Exception("Encryption XOR Decryption: plain_text XOR cipher_text [output_file].")
		else:
			raise Exception("I need something to encrypt or decrypt.")


	def file_or_text(self, questionable):
		if os.path.isabs(questionable):
			text = open(questionable, 'r').read() if os.path.isfile(questionable) else None
			if not text: raise Exception("Path to file ({0}) doesn't exist!".format(questionable))
			return text
		#questionable appears to be text
		return questionable

	def distribute_message(self, result):
		if not result: return
		if self.ofile:
			open(self.ofile, 'w').write(result)
		else:
			print "Result: ", result


	def CTR(self, key, message, direction = True):
		des = DES.new(key, DES.MODE_CTR, counter=self.iv)
		if direction:
			return des.encrypt(message)
		return des.decrypt(message)



if __name__ == "__main__":
	crypt(plain_text="Ah, yes. This is much cooler.", key="thisistt", mode="ctr", output_file="/tmp/cipher.txt")
	crypt(cipher_text="/tmp/cipher.txt", key="thisistt", mode="ctr")
		


This post has been edited by Python_4_President: 25 November 2012 - 03:15 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1