<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#
#	Filename pc1char.py
#
#	Purpose:  This program transplant PC1 cipher in C/C++ version into Python
#			  The bugs hidden in deep were fixed, so this python version 
#			  is compatible with versions in C/C++ and java
#			  for more information please contact Alexander Pukall
#
#	Author:  Huey Jiang		huey_jiang@yahoo.com
#
#	Date:	March 13, 2009
#
class PC1:
	def __init__(self):
		self.cle = []
		self.x1a0 = []
		
		for name in ("ax", "bx", "cx", "dx", "si", "tmp", "x1a2", "res", "pki", "inter", "cfc", "cfd", "compte", "pkc"):
			setattr(self, name, 0)
		
	def fin(self):
		del self.cle[0:]
		del self.x1a0[0:]
		
		for i in range(9):
			self.x1a0.insert(i, 0)
		for i in range(16):
			self.cle.insert(i, 0)
			
		for name in ("ax", "bx", "cx", "dx", "si", "tmp", "x1a2", "res", "pki", "inter", "cfc", "cfd", "compte", "pkc"):
			setattr(self, name, 0)
	def code(self):
		self.dx = self.x1a2 + self.pki
		self.ax = self.x1a0[self.pki]
		self.cx = 0x015a
		self.bx = 0x4e35
	
		self.tmp = self.ax
		self.ax = self.si
		self.si = self.tmp
		
		self.tmp = self.ax
		self.ax = self.dx
		self.dx = self.tmp
		
		if self.dx != 0:
			self.ax = (self.ax * self.bx) &amp; 0xffff
			
		self.tmp = self.ax
		self.ax = self.cx
		self.cx = self.tmp
		
		if self.ax != 0:
			self.ax = (self.ax * self.si) &amp; 0xffff
			self.cx = self.ax + self.cx
		
		self.tmp = self.ax
		self.ax = self.si
		self.si = self.tmp
		self.ax = (self.ax * self.bx) &amp; 0xffff
		self.dx = self.cx + self.dx
	
		self.ax = self.ax + 1
		
		self.x1a2 = self.dx
		self.x1a0[self.pki] = self.ax
		
		self.res = (self.ax ^ self.dx) &amp; 0xffff
		self.pki = self.pki + 1
		
	def assemble(self):
		self.x1a0[0] = (self.cle[0] * 256) + self.cle[1]
		
		self.code()
		self.inter = self.res
		
		self.x1a0[1] = self.x1a0[0] ^ ((self.cle[2] * 256) + self.cle[3])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.x1a0[2] = self.x1a0[1] ^ ((self.cle[4] * 256) + self.cle[5])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.x1a0[3] = self.x1a0[2] ^ ((self.cle[6] * 256) + self.cle[7])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.x1a0[4] = self.x1a0[3] ^ ((self.cle[8] * 256) + self.cle[9])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.x1a0[5] = self.x1a0[4] ^ ((self.cle[10] * 256) + self.cle[11])
		self.code()
		self.inter = self.inter ^ self.res
		self.x1a0[6] = self.x1a0[5] ^ ((self.cle[12] * 256) + self.cle[13])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.x1a0[7] = self.x1a0[6] ^ ((self.cle[14] * 256) + self.cle[15])
		self.code()
		self.inter = self.inter ^ self.res
		
		self.pki = 0
	def encrypt(self, plaintext, passwd):
		encrypted = ''
		dummy = []
		
		self.fin()
		for p in passwd:
			dummy.append( ord(p))
	
		# Take care of key first
		paslen = len(passwd)
		keylen = len(self.cle)
		if paslen &gt;= keylen:
			newkey = dummy[:keylen]
		else:
			lefto = self.cle[paslen:]
			newkey = dummy + lefto
	
		self.cle = newkey
		
		# OK, rock starts	
		for c in plaintext:
			self.pkc = ord(c)
			
			self.assemble()
			
			self.cfc = self.inter &gt;&gt; 8
			
			self.cfd = self.inter &amp; 255
			
			for i in range(16):
				self.cle[i] = self.cle[i] ^ self.pkc
			
			self.pkc = self.pkc ^ (self.cfc ^ self.cfd)
			
			d = self.pkc &gt;&gt; 4
			e = self.pkc &amp; 15
			
			dd = 0x61+d;
			ee = 0x61+e;
			
			encrypted = encrypted + chr(dd) + chr(ee)
		return encrypted
	def decrypt(self, ciphertext, passwd):
		decrypted = ''
		dummy = []
		dds = ''
		ees = ''
		
		self.fin()
		for p in passwd:
			dummy.append( ord(p))
	
		# Take care of key first
		paslen = len(passwd)
		keylen = len(self.cle)
		if paslen &gt;= keylen:
			newkey = dummy[:keylen]
		else:
			lefto = self.cle[paslen:]
			newkey = dummy + lefto
	
		self.cle = newkey
		
		cilen = len(ciphertext)
	
		for i in range(0, cilen, 2):
			dds = dds + ciphertext[i]

		for i in range(1, cilen+1, 2):
			ees = ees + ciphertext[i]

		halen = cilen / 2
	
		for i in range(halen):
			dd = ord(dds[i])
		
			d = dd - 0x61
			
			d = d &lt;&lt; 4
		
			ee = ord(ees[i])
			e = ee - 0x61
		
			self.pkc = d + e

			self.assemble()
	
			self.cfc = self.inter &gt;&gt; 8
			self.cfd = self.inter &amp; 255
		
			dec = self.pkc ^ (self.cfc ^ self.cfd)
			
			decrypted = decrypted + chr(dec)	
			for j in range(16):
				self.cle[j] = self.cle[j] ^ dec
			
			
		return decrypted
if __name__ == "__main__":
	p = PC1()
	# you should change key "Remsaalps!123456" 
	ec = p.encrypt("123abc", "Remsaalps!123456")
	print ec
	dc = p.decrypt(ec, "Remsaalps!123456")
	print dc</pre></body></html>