OverflowError: int too big to convert with RSA encryption - python

I am doing RSA encryption using exponential, everything appears to be fine until I try to convert it to a bytearray for decryption rst.to_bytes(8, 'big'), it throws an overflow error, how can I rectify this?
from Crypto.PublicKey import RSA
def square_multiply(a,x,n):
res = 1
for i in bin(x)[2:]:
res = res * res % n
if (i == '1'):
res = res * a % n
return res
def encrypt_rsa(m):
key = open('mykey.pem.pub', 'r').read()
rsakey = RSA.import_key(key)
mb = int.from_bytes(m, byteorder='big')
rst = square_multiply(mb, rsakey.e, rsakey.n)
return rst
def decrypt_rsa(me):
key = open(pri_key, 'r').read()
rsakey = RSA.import_key(key)
rst = square_multiply(me, rsakey.d, rsakey.d)
mb = rst.to_bytes(8, 'big')
m = mb.decode("utf-8")
return m
def readFile():
with open('message.txt', 'r') as f:
m = f.read().encode('utf-8')
return m
if __name__=="__main__":
pub_key = 'mykey.pem.pub'
pri_key = 'mykey.pem.priv'
m = readFile()
me = encrypt_rsa(m)
de = decrypt_rsa(me)

Related

How to implement HMAC in python without using the hmac library?

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

RC4 decryption in python hexadecimal inputs

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

Python encryption and decryption

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'

Rsa cipher error

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)

Converting .raw file into Hex

I have a .raw image file, and I'd like to use python3 to read all the data from the file and print a hex dump of this image.
If possible, i'd like it to run in the terminal window.
This is the code I have found and adapted so far:
import sys
src = sys.argv[1]
def hexdump( src, length=16, sep='.' ):
result = [];
# Python3 support
try:
xrange(0,1);
except NameError:
xrange = range;
for i in xrange(0, len(src), length):
subSrc = src[i:i+length];
hexa = '';
isMiddle = False;
for h in xrange(0,len(subSrc)):
if h == length/2:
hexa += ' ';
h = subSrc[h];
if not isinstance(h, int):
h = ord(h);
h = hex(h).replace('0x','');
if len(h) == 1:
h = '0'+h;
hexa += h+' ';
hexa = hexa.strip(' ');
text = '';
for c in subSrc:
if not isinstance(c, int):
c = ord(c);
if 0x20 <= c < 0x7F:
text += chr(c);
else:
text += sep;
result.append(('%08X: %-'+str(length*(2+1)+1)+'s |%s|') % (i, hexa, text));
return '\n'.join(result);
if __name__ == "__main__":
print(hexdump(src, length=16, sep='.'))
I've been using the command in the terminal:
python3 nameoffile.py nameofrawfile.raw
and it just gives me the hex values of the name of the raw file. I'd like it to read the raw file then give be all the data from it in hex.
Thanks.
EDIT: I'd like to use python as once the file is represented in hex values, I'd like to do further processing on it using python.
One-liner:
$ python -c \
"import codecs; print(codecs.encode(open('file.raw', 'rb').read(), 'hex').decode())"
The problem is you pass the name of the file to hexdump() which treats it like data. The following corrects that and applies other relatively minor fixes to your code (and seems to work in my limited testing):
try:
xrange
except NameError: # Python3
xrange = range
def hexdump(filename, length=16, sep='.'):
result = []
with open(filename, 'rb') as file:
src = file.read() # Read whole file into memory
for i in xrange(0, len(src), length):
subSrc = src[i:i+length]
hexa = ''
isMiddle = False;
for h in xrange(0,len(subSrc)):
if h == length/2:
hexa += ' '
h = subSrc[h]
if not isinstance(h, int):
h = ord(h)
h = hex(h).replace('0x','')
if len(h) == 1:
h = '0'+h;
hexa += h+' '
hexa = hexa.strip(' ')
text = ''
for c in subSrc:
if not isinstance(c, int):
c = ord(c)
if 0x20 <= c < 0x7F:
text += chr(c)
else:
text += sep;
result.append(('%08X: %-'+str(length*(2+1)+1)+'s |%s|') %
(i, hexa, text))
return '\n'.join(result)
if __name__ == "__main__":
import sys
filename = sys.argv[1]
print(hexdump(filename, length=16, sep='.'))

Categories

Resources