I am trying to execute this code but I am getting this error:
line 37, in \<module\>
encrypt(encryption_key_pair\[0\],encryption_key_pair\[1\],secret_message
line 22, in encrypt
enc_text = num_trans\[ord_num\]
KeyError: 32
\[Finished in 1.1s\]
Here's the part of the code:
from alphabet import transform, num_trans
from key_generator import generate_keys, encryption_key_pair, decryption_key_pair
#enc_key = [5,14]
#dec_key = [11,14]
secret_message = "abc"
encrypted_message = []
decrypted_message = []
def encrypt(e, modulus, message):
global enc_message
for character in message:
#print(character)
#enc_char = ord(character)
enc_char = transform[f'{character}']
#print(enc_char)
ord_num = (enc_char**e)%modulus
#print(ord_num)
#enc_text = chr(ord_num)
enc_text = num_trans[ord_num]
enc_message = encrypted_message.append(enc_text)
def decrypt(d, modulus, message):
global dec_message
for character in message:
decode_char = transform[f'{character}']
deord_char = (decode_char**d)%modulus
#print(deord_char)
dec_text = num_trans[deord_char]
dec_message = decrypted_message.append(dec_text)
encrypt(encryption_key_pair[0],encryption_key_pair[1],secret_message)
decrypt(decryption_key_pair[0],decryption_key_pair[1],encrypted_message)
print(encrypted_message)
print(decrypted_message)
Related
I want to code a short programme. My idea was to code a login window. Then the next window opens and then I should be able to encrypt a text I wrote into a ScrolledText. The whole encryption should be done with the ceasar principal. I combined my code(at the bottom) with this one:
def caesar(text, schluessel):
geheim = ''
for i in text:
number = ord(i) + schluessel #122 = 119+3
if number > 122:
number -= 26
elif number == 32 + schluessel: #whitespace
number = 32
letter = chr(number)
geheim += letter
print(geheim)
I recieved this error message:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "C:/Users/pc/PycharmProjects/test_22_11_22/main.py", line 77, in caesar
for i in encryptiontextentry:
File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1643, in cget
return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str
This is my code:
from tkinter import *
from tkinter.scrolledtext import ScrolledText
class Login:
def __init__(self):
self.user ={'1':'1'}
self.loginwindow = Tk()
self.loginwindow.geometry("500x300")
self.loginwindow.resizable(width= False, height= False)
self.loginlabel = Label(text="Login",font= ("arial",50))
self.loginausgabe = Label(self.loginwindow)
self.loginusernamelabel = Label(self.loginwindow, text="Username",font= ("arial",12))
self.loginusernameentry = Entry(self.loginwindow,font= ("arial",12))
self.loginpasswordlabel = Label(self.loginwindow,text="Password",font= ("arial",12))
self.loginpasswordentry = Entry(self.loginwindow,font= ("arial",12), show="*")
self.loginbtn = Button(self.loginwindow,text="login",width= 38, command=self.login)
self.loginlabel.place(x="140",y="0")
self.loginausgabe.place(x="140",y="140")
self.loginusernamelabel.place(x="140",y ="80")
self.loginusernameentry.place(x="230",y="80")
self.loginpasswordlabel.place(x="140",y ="100")
self.loginpasswordentry.place(x="230",y="100")
self.loginbtn.place(x="140",y="120")
self.loginwindow.mainloop()
def login(self):
loginusernameentry = self.loginusernameentry.get()
if loginusernameentry in self.user.keys():
if self.loginpasswordentry.get() == self.user[loginusernameentry]:
self.loginausgabe.config(text="Welcome!")
self.encryption()
else: self.loginausgabe.config(text="Invalid password!")
else: self.loginausgabe.config(text="Unknown User!")
self.loginusernameentry.config(text="")
self.loginusernameentry.config(text="")
def encryption(self):
self.loginwindow.destroy()
self.encryptionwindow = Tk()
self.encryptionwindow.geometry("1000x600")
self.encryptionwindow.resizable(width= False, height= False)
self.encryptiontextlabel = Label(self.encryptionwindow,text="encryption text",font= ("arial",12))
self.encryptiontextentry = ScrolledText(self.encryptionwindow)
self.decryptiontextlabel = Label(self.encryptionwindow,text="dencryption text",font= ("arial",12))
self.decryptiontextentry = ScrolledText(self.encryptionwindow)
self.encryptionbtn = Button(self.encryptionwindow,text="encrypt",command=self.caesar)
self.caesarkeyencryption = Entry(self.encryptionwindow,width="2")
self.decryptionbtn = Button(self.encryptionwindow,text="decrypt",command=self.caesar)
self.caesarkeydecryption = Entry(self.encryptionwindow,width="2")
self.decryptiontextlabel.place(x="120", y="310")
self.decryptiontextentry.place(x="120", y="330", width="800",height="200")
self.encryptiontextlabel.place(x="120", y="40")
self.encryptiontextentry.place(x="120", y="60", width="800",height="200")
self.encryptionbtn.place(x="120",y="260")
self.caesarkeyencryption.place(x="170",y="264")
self.decryptionbtn.place(x="120",y="530")
self.caesarkeydecryption.place(x="170",y="534")
self.encryptionwindow.mainloop()
** def caesar(self):
caesarkeyencryption = int(self.caesarkeyencryption.get())
encryptiontextentry = self.encryptiontextentry
print(caesarkeyencryption)
encryptiontextresult = ''
for i in encryptiontextentry:
number = ord(i) + caesarkeyencryption
if number > 122:
number -= 26
elif number == 32 + caesarkeyencryption: #whitespace
number = 32
letter = chr(number)
encryptiontextresult += letter
print(encryptiontextresult)
**
l = Login()
I use python to write the program to control the motor, and the error is shown as follows after running:"message": "No value for argument 'speed_a' in function call pylint(no-value-for-parameter)[93,21]' Below is the code I am using:
import serial
import time
#import threading
import struct
from binascii import unhexlify
from crcmod import mkCrcFun
import binascii
import crcmod
def check_code(byte0, byte1, speed_vel, speed_ang):
'计算校验码时需要输入的字节'
read = byte0+byte1+speed_vel+speed_ang #解析校验码要输入的前几位
read=(str(binascii.b2a_hex(read))[2:-1])
print (read)
return (read)
def crc16_modbus(read):
'输出的控制电机指令字节码'
crc16 =crcmod.mkCrcFun(0x18005,rev=True,initCrc=0xFFFF,xorOut=0x0000)
data = read.replace(" ","")
#print (data)
readcrcout=hex(crc16(unhexlify(data))).upper()
str_list = list(readcrcout)
if len(str_list) < 6:
str_list.insert(2, '0'*(6-len(str_list))) # 位数不足补0
crc_data = "".join(str_list)
#print(crc_data)
read = read.strip()+crc_data[4:]+crc_data[2:4]
read = read.encode('UTF-8')
return read
def motor_speed_vel(speed_v,speed_a):
'计算小车线速度speed_v'
DEC1 = speed_v
DEC2 = speed_a
byte2 =(struct.pack("i",DEC1)[-4:-3])#线速度
byte3 =(struct.pack("i",DEC1)[-3:-2])#线速度
speed_vel = byte2 + byte3
byte4 = (struct.pack("i",DEC2)[-4:-3]) #角速度两个字节
byte5 = (struct.pack("i",DEC2)[-3:-2])
speed_ang = byte4+byte5
print (speed_vel,speed_ang)
return (speed_vel,speed_ang)
motor_speed_vel(200,20)
'''
def motor_speed_ang(speed_a):
'角速度的speed_a的byte码'
DEC2 = speed_a
byte4 = (struct.pack("i",DEC2)[-4:-3]) #角速度两个字节
byte5 = (struct.pack("i",DEC2)[-3:-2])
speed_ang = byte4+byte5
print (speed_ang)
return (speed_ang)
motor_speed_ang(20)
#motor_speed_cal(200,20) #设定的 (线速度,角速度)
'''
motor_speed_mode = b'\x01\x2F\x60\x60\x00\x03\x00\x00\x00\x0D'
#motor_status = b'\x43\x50\x00\x51\x00\x68\x95'
motor_start = b'\x01\x44\x21\x00\x31\x00\x00\x01\x00\x01\x75\x34'
motor_stop = b'\x01\x44\x21\x00\x31\x00\x00\x00\x00\x00\xE5\x34' # AB轴失能
class SpeedMotor:
def __init__(self, device,speed_v,speed_a):
# 真实速度
self.rel_speed = 0
# 设置的速度
self.set_speed1 = speed_v
# 设置角速度
self.set_speed2 = speed_a
# 运行状态
self.run = False
# 故障状态
self.fault = None
# 电机电压
self.voltage = 0
# 电机电流
self.current = 0
# 设置串口通讯
self.serial = serial.Serial(device, 115200)
self.serial.timeout = 0
# 设置为速度模式
self.serial.write(motor_speed_mode)
time.sleep(0.1)
# 设置加减速度
# self.serial.write(b'\x0A\x14\x14\x32')
# time.sleep(0.1)
def motor_speed_set(self):
'速度设置'
byte0 = b'\x01'
byte1 = b'\xEA'
speed_vel = motor_speed_vel(self.set_speed1)
speed_ang = motor_speed_vel(self.set_speed2)
read = check_code(byte0, byte1, speed_vel, speed_ang)
speed_code = read
self.serial.write(speed_code)
def motor_start(self):
self.serial.write(motor_start)
self.run = True
def motor_stop(self):
self.run = False
self.serial.write(motor_stop)
m = SpeedMotor('COM5',200,20)
m.motor_start()
#for i in range(100):
# m.set_speed = i
time.sleep(15)
m.motor_stop()`
I don't know if it is because of the problem with my parameter call, or because of the structure of the code, and I am very uncertain about the correctness of the code structure, because I am a beginner.
here is my code:
import time
ed = input('Encrypt (e) or decrypt (d)? ')
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "
charsLen = len(chars)
def numberToStr(num):
s = ""
while num:
s = chars[num % charsLen] + s
num //= charsLen
return(s)
def strToNumber(numStr):
num = 0
for i, c in enumerate(reversed(numStr)):
num += chars.index(c) * (charsLen ** i)
return(num)
def enc():
key = input('What is your key? (Alphanumeric and space) ')
ID = int(input('What is your ID? (0-9, 3+ digits) '))
inp = int(strToNumber(input('What do you want to encrypt? ')))
keyAsNum = int(strToNumber(key))
enc.asint = inp ** 2
enc.asint = enc.asint * ID
enc.asint = enc.asint - keyAsNum
enc.astext = numberToStr(int(enc.asint))
return(enc)
def dec():
key = input('What is your key? (Alphanumeric and space) ')
ID = int(input('What is your ID? (0-9, 3+ digits) '))
inp = int(strToNumber(input('What do you want to decrypt? ')))
keyAsNum = int(strToNumber(key))
message = inp + keyAsNum
message = message // ID
message = math.sqrt(message)
message = numberToStr(message)
return(message)
if ed=='e':
crypt = enc()
print('crypt.asint:\n' + str(crypt.asint) + '\ncrypt.astext:\n' + crypt.astext)
elif ed=='d':
crypt = dec()
print(crypt)
time.sleep(10)
and here is the error:
File "stdin", line 5, in module
File "stdin", line 9, in dec
File "stdin", line 4, in numberToStr
TypeError: string indices must be integers
I cannot figure out why it is throwing this error and cannot find anything on google.
The traceback tells you exactly what is wrong. You are doing
s = chars[num % charsLen] + s
but you don't know for sure that num is an int because, previously, you do:
message = math.sqrt(message)
message = numberToStr(message)
What type does math.sqrt return?
I trying to use a Python script to decrypt a message. I have the cipher text (noted as FLAG in code) and most of the Python code used for encryption. I need to find the original plaintext message. Below I am trying to build a decode function into my Python code but failing (novice to Python). Can any genius help?
Here's the code so far:
import string
import random
from base64 import b64encode, b64decode
FLAG = '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'
enc_ciphers = ['rot13', 'b64e', 'caesar']
dec_ciphers = ['rot13', 'b64d', 'caesard']
def rot13(s):
_rot13 = string.maketrans(
"zyxwvutsrqponZYXWVUTSRQPONmlkjihgfedcbaMLKJIHGFEDCBA",
"mlkjihgfedcbaMLKJIHGFEDCBAzyxwvutsrqponZYXWVUTSRQPON")
return string.translate(s, _rot13)
def b64e(s):
return b64encode(s)
def b64d(s):
return b64decode(s)
def caesar(plaintext, shift=4):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
def caesard(plaintext, shift=-4):
alphabet = string.ascii_lowercase
shifted_alphabet = alphabet[shift:] + alphabet[:shift]
table = string.maketrans(alphabet, shifted_alphabet)
return plaintext.translate(table)
def encode(pt, cnt=50):
tmp = '2{}'.format(b64encode(pt)) #2.format(b64encode(pt))
for cnt in xrange(cnt):
c = random.choice(enc_ciphers) # choose some enc_cipher
i = enc_ciphers.index(c) + 1 # position in the array + 1
_tmp = globals()[c](tmp)
tmp = '{}{}'.format(i, _tmp)
return tmp
def decode(tmp, cnt=50):
for cnt in xrange(cnt):
i = int(tmp[:1])-1
_tmp = tmp[1:]
c = dec_ciphers[i]
tmp = globals()[c](_tmp)
try:
s = b64decode(tmp[1:])
if s.find("flag") != -1:
return s
except:
pass
return b64decode(tmp[1:])
if __name__ == '__main__':
cnt=70
print "Cnt: %d" % cnt
print decode(FLAG, cnt)
Here is the error message:
/usr/bin/python -u "/media/pc/A8560F93560F6204/Python investigation/transfer_csaw2015 fully MODDED2.py"
Cnt: 70
Traceback (most recent call last):
File "/media/pc/A8560F93560F6204/Python investigation/transfer_csaw2015 fully MODDED2.py", line 64, in <module>
print decode(FLAG, cnt)
File "/media/pc/A8560F93560F6204/Python investigation/transfer_csaw2015 fully MODDED2.py", line 47, in decode
i = int(tmp[:1])-1
ValueError: invalid literal for int() with base 10: 'W'
I wrote the following code in python 3.4
import sys
DEFAULT_BLOCK_SIZE = 128
BYTE_SIZE = 256
def main():
filename = 'encrypted_file.txt'
mode = 'encrypt'
if mode == 'encrypt':
message = '''"Journalists belong in the gutter because that is where the ruling classes throw their guilty secrets." -Gerald Priestland "TheFounding Fathers gave the free press the protection it must have to bare the secrets of government and inform the people." -Hugo Black'''
pubKeyFilename = 'vineeth_pubkey.txt'
print('Encrypting and writing to %s...' % (filename))
encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message)
print('Encrypted text:')
print(encryptedText)
elif mode == 'decrypt':
privKeyFilename = 'vineeth_privkey.txt'
print('Reading from %s and decrypting...' % (filename))
decryptedText = readFromFileAndDecrypt(filename, privKeyFilename)
print('Decrypted text:')
print(decryptedText)
def getBlocksFromText(message, blockSize=DEFAULT_BLOCK_SIZE):
messageBytes = message.encode('ascii')
blockInts = []
for blockStart in range(0, len(messageBytes), blockSize):
blockInt = 0
for i in range(blockStart, min(blockStart + blockSize, len(messageBytes))):
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
blockInts.append(blockInt)
return blockInts
def getTextFromBlocks(blockInts, messageLength,blockSize=DEFAULT_BLOCK_SIZE):
message = []
for blockInt in blockInts:
blockMessage = []
for i in range(blockSize- 1, -1, -1):
if len(message) + i < messageLength:
asciiNumber = blockInt // (BYTE_SIZE ** i)
blockInt = blockInt % (BYTE_SIZE ** i)
blockMessage.insert(0, chr(asciiNumber))
message.extend(blockMessage)
return ''.join(message)
def encryptMessage(message, key, blockSize=DEFAULT_BLOCK_SIZE):
encryptedBlocks = []
n, e = key
for block in getBlocksFromText(message, blockSize):
encryptedBlocks.append(pow(block, e, n))
return encryptedBlocks
def decryptMessage(encryptedBlocks, messageLength, key, blockSize=DEFAULT_BLOCK_SIZE):
decryptedBlocks = []
n, d = key
for block in encryptedBlocks:
decryptedBlocks.append(pow(block, d, n))
return getTextFromBlocks(decryptedBlocks, messageLength, blockSize)
def readKeyFile(keyFilename):
fo = open(keyFilename)
content = fo.read()
fo.close()
keySize, n, EorD = content.split(',')
return (int(keySize), int(n), int(EorD))
def encryptAndWriteToFile(messageFilename, keyFilename, message, blockSize=DEFAULT_BLOCK_SIZE):
keySize, n, e = readKeyFile(keyFilename)
if keySize < blockSize * 8:
print'ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or less than the key size. Either increase the block size or use different keys.' % (blockSize * 8, keySize)
sys.exit()
encryptedBlocks = encryptMessage(message, (n, e), blockSize)
for i in range(len(encryptedBlocks)):
encryptedBlocks[i] = str(encryptedBlocks[i])
encryptedContent = ','.join(encryptedBlocks)
encryptedContent = '%s_%s_%s' % (len(message), blockSize, encryptedContent)
fo = open(messageFilename, 'w')
fo.write(encryptedContent)
fo.close()
return encryptedContent
def readFromFileAndDecrypt(messageFilename, keyFilename):
keySize, n, d = readKeyFile(keyFilename)
fo = open(messageFilename)
content = fo.read()
messageLength, blockSize, encryptedMessage = content.split('_')
messageLength = int(messageLength)
blockSize = int(blockSize)
if keySize < blockSize * 8:
print 'ERROR: Block size is %s bits and key size is %s bits. The RSA cipher requires the block size to be equal to or less than the keysize. Did you specify the correct key file and encrypted file?' % (blockSize * 8, keySize)
encryptedBlocks = []
for block in encryptedMessage.split(','):
encryptedBlocks.append(int(block))
return decryptMessage(encryptedBlocks, messageLength, (n, d), blockSize)
if __name__ == '__main__':
main()
It generates the following error when used in python 2.7
Traceback (most recent call last):
File "E:\Python27\My programs\rsa.py", line 94, in <module>
main()
File "E:\Python27\My programs\rsa.py", line 11, in main
encryptedText = encryptAndWriteToFile(filename, pubKeyFilename, message)
File "E:\Python27\My programs\rsa.py", line 69, in encryptAndWriteToFile
encryptedBlocks = encryptMessage(message, (n, e), blockSize)
File "E:\Python27\My programs\rsa.py", line 46, in encryptMessage
for block in getBlocksFromText(message, blockSize):
File "E:\Python27\My programs\rsa.py", line 27, in getBlocksFromText
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
Could anyone help in troubleshooting this code so that it works in python 2.7?
Thanks!
P.S It worked in python 3.4.
Look at the error
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
It is derived from
File "E:\Python27\My programs\rsa.py", line 27, in getBlocksFromText
blockInt += messageBytes[i] * (BYTE_SIZE ** (i % blockSize))
You are trying to and operation on a int and a string. You need to convert either of them to the same type
numbers = 12345
letters = 'abcde'
num_letters = '12345'
# this works:
str(numbers)
int(num_letters)
# this doesn't work:
int(letters)