DSA key format not supported - python

I am trying to do a P2MS script.
For my script, I am saving the keys into a text file with DER format instead of the usual PEM file. Both key and signatures are saved in a text file and hexlify. Below is my code for the P2MS execution.
from Crypto.PublicKey import DSA
from Crypto.Hash import SHA256
from Crypto.Signature import DSS
from binascii import hexlify, unhexlify
import binascii
message = b"helpsmepls"
# Read scriptPubKey and scriptSig from files
with open('scriptPubKey.txt', 'r') as f:
readscriptPubKey = f.read().strip()
with open('scriptSig.txt', 'r') as f:
scriptSig = f.read().strip()
print(type(readscriptPubKey))
tempholder = readscriptPubKey.split()
# Removing the first character and last character
removeend = tempholder[1:-1]
scriptPubKey = []
# Removing front extra headings
for count, x in enumerate(removeend):
w = bytes(removeend[count][1:-1], encoding = 'utf-8')
#print(w)
scriptPubKey.append(w)
# Splitting the Signatures
signatures = scriptSig.split()
hash_obj = SHA256.new(message)
# Going through the pubkeys based on the number of signatures generated
for o, sig in enumerate(signatures):
pub_key = DSA.import_key(bytes.fromhex(scriptPubKey[o].decode("utf-8")))
hash_obj = SHA256.new(message)
verifier = DSS.new(pub_key, 'fips-183-3')
# Verifying if the Public key and signatures match, loop will break if False is encountered
if verifier.verify(hash_obj, sig):
d = True
else:
d = False
break
break
if d == True:
print("The message is authentic.")
else: print("The message is not authentic.")
Unfortunately before my code can reach the verification, it encountered an error.
Full traceback
It seems my DSA key format has an error, but I am not too sure why is it giving me that error.
I have also tried unhexlifying my input from the public key text file, but it also did not work. I have tried to hex decode the input to get the DER format of the input, but my type is still just bytes. I am not so sure how to properly import the key with the appropriate DSA key format from a txt file. I am able to do that with a PEM file but would just like to find out how to execute it with a txt file.
My expected outcome is the DSA key is imported properly and i am able to verify the public key with the signatures.

Related

Verification failure PKCS1_PSS verifier object for Signature signed with RSA 3k and sha384.[Crypto python module]

I am trying to verify the signature file(binary file). I have RSA3k public key and the hash algorithm used is SHA384 Padding shceme used is: PSS. I used Crypto.Signature module in python. I am creating a verifier object in-order to verify the signature -->** PKCS1_PSS.new(key)**.
Below the simple code, verify_signature function takes three parameters public_key_file, message_file and signature_file and returns whether the signature is authentic or not.
Code:
def verify_signature(public_key_file, message_file, signature_file):
# Read the public key from the PEM file
# with open(public_key_file, 'rb') as f:
# key = RSA.importKey(f.read())
# construct key using the modulus file
with open(os.path.join('projectkeys', 'exponent.fws'), 'rb') as f: # open exponent file
data = f.read()
e = int(data.hex(), 16)
with open(public_key_file, 'rb') as f:
data = f.read()
n = int(data.hex(), 16)
key = RSA.construct((n, e))
with open(message_file,'rb') as f2:
message = f2.read()
with open(signature_file,'rb') as f3:
signature = f3.read()
h = SHA384.new(message)
# Verify the signature using the verifier and the hashed message
# mgf = lambda x,y : MGF1(x,y,SHA384.new(message))
verifier = PKCS1_PSS.new(key)
if verifier.verify(h, signature):
return "The signature is authentic."
else:
return "The signature is not authentic."
I tried both ways i. to read the key from the file and ii. constructed key using modulus(n) and exponent(e) values.
This verifier object is verifying correctly if the key is RSA2k and sha256. I tried to explore the mgf(mask generation function) and pass the values appropriately, but I am getting incorrect output.
If anyone has an idea why this code is failing will be really helpful. Or sharing any alternate way of verifying the signature for example using openssl.
Thanks,

Decoding a fetched email header or subject into a readable manner

I get emails with unique subjects, and I want to save them.
I tried this (stage with credentials input is omitted)
import email
import imaplib
suka.select('Inbox')
key = 'FROM'
value = 'TBD'
_, data = suka.search(None, key, value)
mail_id_list = data[0].split()
msgs = []
for num in mail_id_list:
typ, data = suka.fetch(num, '(RFC822)')
msgs.append(data)
for msg in msgs[::-1]:
for response_part in msg:
if type(response_part) is tuple:
my_msg=email.message_from_bytes((response_part[1]))
print ("subj:", my_msg['subject'])
for part in my_msg.walk():
#print(part.get_content_type())
if part.get_content_type() == 'text/plain':
print (part.get_payload())
I do get the subjects, but in a form of "subj: =?utf-8?B?0LfQsNGP0LLQutCwIDIxXzE0MTIyMg==?=". Thus, a decoding is required. The secret seems to be, which variable needs to be decoded?
Also tried the other way:
yek, do = suka.uid('fetch', govno,('RFC822'))
, where govno is the latest email in the inbox. The output is "can't concat int to bytes".
Thus, is there a way to decode the subjects as they appear in the email client? Thank you.
There is a built-in decode_header() method.
Decode a message header value without converting the character set.
The header value is in header.
This function returns a list of (decoded_string, charset) pairs
containing each of the decoded parts of the header. charset is None
for non-encoded parts of the header, otherwise a lower case string
containing the name of the character set specified in the encoded
string.
>>> from email.header import decode_header
>>> decoded_headers = decode_header("=?utf-8?B?0LfQsNGP0LLQutCwIDIxXzE0MTIyMg==?=")
>>> decoded_headers
[(b'\xd0\xb7\xd0\xb0\xd1\x8f\xd0\xb2\xd0\xba\xd0\xb0 21_141222', 'utf-8')]
>>> first = decoded_headers[0]
>>> first[0].decode(first[1])
'заявка 21_141222'
You can decode the actual value returned by decode_header using the charset returned by it.
For follow-up question, here's a helper function to get the header value in case of multiline header value which handlers errors -
from email.header import decode_header
def get_header(header_text, default='utf8'):
try:
headers = decode_header(header_text)
except:
print('Error while decoding header, using the header without decoding')
return header_text
header_sections = []
for text, charset in headers:
try:
# if charset does not exist, try to decode with utf-8
header_section = text.decode(charset or 'utf-8')
except:
# if we fail to decode the text(header is incorrectly encoded)
# Try to do decode, and ignore the decoding errors
header_section = text.decode('utf-8', errors='ignore')
if header_section:
header_sections.append(header_section)
return ' '.join(header_sections)
print(get_header("=?utf-8?B?0LfQsNGP0LLQutCwIDIxXzE0MTIyMg==?="))

How to fix 'str' object has no attribute 'encrypt'?

I'm trying to to encrypt a message using a given public key pubkey that i read off a file. When I try to run my program I get an error message stating that
'str' object has no attribute 'encrypt'.
I have already tried encoding the public key, but I am still getting the same error. Since I need to use these specific public key I cannot generate another random public key.
Following is my code:
from Crypto.PublicKey import RSA
import math
def text_to_int(text):
"""
Converts text into an integer for use in encryption.
input: text - a plaintext message
output: integer - an integer encoding text
"""
integer = 0
for char in text:
if integer > 0:
integer = integer*256
integer = integer + ord(char)
return integer
#Read public key
with open('C:\\Users\\alan9\\Downloads\\Assignement2\\Supporting_Files\\HLand_Key.pub', 'rb') as f:
read_key = f.read()
# use the PUBLIC KEY to encrypt a message:
message = "attack early next week"
message_int = text_to_int(message)
ciphertext = read_key.encrypt(message_int, None)
#Write ciphertext to file
with open('C:\\Users\\alan9\\Downloads\\Assignement2\\Supporting_Files\\cipher.txt', 'w') as f_write:
f_write.write(ciphertext)
I expect the output to return the encrypted message in a text file named cipher using the specified public key.
Any help will be appreciated!!!

Encryption, encoding and Python (AES)

I'm trying to write an encryption/decryption program called P-Cypher in python (python-Cypher, rhymes with decypher). It uses the PyCrypto libraries to encode a file (using AES). Although I know Python, I do not know cryptography - I'm doing this because I thought it would be fun, so don't critique me on security.
This is how the program is supposed to work.
Asks for input file.
Asks whether you want it to encrypt or decrypt. (sets mode)
Asks for output file. Verifies it exists- if it does not, asks if you want it to create one.
Encrypts input file and tells you the key/Prompts you for the key, and decrypts the file with the key (Depending on mode)
Writes to output file.
Everything works except for number 4. (I know step 5 works as step 5 remains pretty much unchanged from the last stable version, v0.03d). On step 4 encoding, one of two things happen depending on which way I code it:
The thing successfully- YAY! encodes the file. However, the key it prints out is in the form of b'U\xxx\xxx\xxx\xxx\xxx' like that. When I enter it in step 4 decoding mode, with or without the b and 's, it doesn't work. So the program cannot decrypt the file, rendering half of my program useless.
I can use .decode(encoding) to turn it into a string. This is the method you see on the code below. However, here is this way's problem- no matter what encoding I use (ascii, ISO, windows-125x, EUR, Big5, utf-8, 16, and 32, etc...) there is always one or more bytes that the encoding cannot encode. And without encoding, there's no decoding, rendering the WHOLE program useless.
So I ask you for help. If you could figure out how to fix problem #1 or #2 (or maybe even both), I would be grateful.
CODE -- Updated
# P-Cypher-Dev
# Made in 2015 by Mateo Guynn
# v0.04d
# Using AES 16/32/64-bit encryption (Google standard)
# DEV VERSION: Possibly unstable, contains better code.
# Changelog:
"""
v0.02d
- Improved Caesar Cipher
- Added binary Cipher converter (fail)
-------------FILE BROKEN------------
"""
"""
v0.03d
- Added ability to create new output files
- Fixed code not quitting on abort
- DEL : binary Cipher converter
---------------STABLE---------------
"""
"""
v0.04d
- DEL : Caesar Cypher
- Added 16/32/64-byte AES encryption
- Binary and text now handled in same manner
-------------FILE BROKEN------------
(encryption works, decryption does not)
"""
"""
v0.05d
- Changed AES encryption to Google's way
- Fixed Key entry
"""
import os
import sys
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Util import randpool
import base64
import codecs
MAX_KEY_SIZE = 26 # Shows the number of available characters (26 in the alphabet)
#NOTES: Binary mode only works if the file is named binary.dat.
def getMode():
while True:
eOrD = input('\nDo you wish to encrypt or decrypt a message? ')
mode = eOrD.lower()
if mode in 'encrypt e decrypt d'.split():
return mode
else:
sys.exit('\nEnter either "encrypt" or "e" or "decrypt" or "d". Capital letters are allowed.\n')
def getMessage():
inputFile = open(input('\nPlease enter the name of the file you want to encrypt/decrypt. You may use relative or full paths. \nPlease, remember the file extension(s)! ')).read()
try:
print ('\nThe contents of the file are: \n%s\n' % inputFile)
return inputFile
except IOError as e:
sys.exit('Unable to open file (the file does not exist or P-Cypher does not have permission to view it).\n Aborting.')
except FileNotFoundError as e:
sys.exit('Unable to open file (the file does not exist or P-Cypher does not have permission to view it).\n Aborting.')
def getCipher(mode, message):
block_size = 16 # For AES, this is the only working value
key_size = 32 # Size of crypto key (possibly changes in getKey())
aesmode = AES.MODE_CBC # More secure mode
if mode[0] == 'e':
key_bytes = randpool.RandomPool(512).get_bytes(key_size)
open('decryption.key', 'wb+').write(key_bytes)
print('\nYour keyfile is: decryption.key\n')
pad = block_size - len(message) % block_size
data = message + pad * chr(pad)
iv_bytes = randpool.RandomPool(512).get_bytes(block_size)
encrypted_bytes = iv_bytes + AES.new(key_bytes,aesmode,iv_bytes).encrypt(data)
encrypted = base64.urlsafe_b64encode(encrypted_bytes)
return encrypted
else:
decryptb = base64.urlsafe_b64decode(message)
decrypted_ivbytes = decryptb[:block_size]
decrypt = decryptb[block_size:]
print('\nAuto-searching for decryption.key...')
try:
key_bytes = base64.urlsafe_b64decode(open('decryption.key', 'rb').read())
except IOError as io:
key_bytes = base64.urlsafe_b64decode(open(input('decryption.key not found. If you have an alternate keyfile, please enter its name now. ')), 'rb').read
except FileNotFoundError as fnf:
key_bytes = base64.urlsafe_b64decode(open(input('decryption.key not found. If you have an alternate keyfile, please enter its name now. '), 'rb').read())
decrypted = AES.new(key_bytes, aesmode, decrypted_ivbytes).decrypt(decryptb)
pad = ord(decrypted[-1])
decrypted = decrypted[:-pad]
return decrypted
def getOutput():
outputFile = input('\nPlease specify an output file. \nDon\'t forget the file extension! ')
outputCheck = input('\nYour message will be encrypted/decrypted into the following output file: %s\n\nIs this okay? (y/n) ' % outputFile).lower()
if outputCheck in 'y yes yeah ok'.split():
try:
return outputFile
except IOError as ioerror:
createNewFile = input('The file you specified does not exist. Shall I create one? (y/n) ')
if createNewFile in 'y_yes_yeah_yes please_ok'.split('_'):
oF = open(outputFile, 'w+')
oF.close()
return outputFile
else:
sys.exit('Aborting...')
elif outputCheck in 'n no'.split():
sys.exit('\nAborting...\n')
else:
sys.exit('\nAborting.\n')
print("\nP-Cypher Alpha starting up...\n\nv0.05 dev\nMateo Guynn\n2015\n")
mode = getMode()
message = getMessage()
try:
open(getOutput(), 'wb+').write(getCipher(mode,message))
except IOError:
sys.exit('Oh noes! Something has gone terribly wrong!')
except FileNotFoundError:
sys.exit('Your input file was not found.')
print('\nDone.')
one solution is to encode it as hex ... this is guaranteed to be ascii characters
import codecs
my_key = "U\x22\x54\x33"
print ("Your Key:", codecs.encode(my_key,"hex"))
...
my_decode_key = codecs.decode(input("enter key:"),"hex")
print( repr(my_decode_key))
print( my_decode_key == my_key )

Generating a Temporary url in Python

I've been trying to generate a temporary url in python, the url will some data that i need to make sure isn't changed so i'll add a hash in the end but i keep ending with a bString no matter what i try, can anyone point out what i'm doing wrong?
Here's a sample of my code
oh and i know that maybe changing the algorithms/encoding might solve the problem but i can't find a suitable one, can any downvoter explain why he downvoted
import hashlib
import datetime
from Crypto.Cipher import AES
def checkTemp(tempLink):
encrypter = AES.new('1234567890123456', AES.MODE_CBC, 'this is an iv456')
decryption = encrypter.decrypt(tempLink)
length = len(decryption)
hash_code = decryption[length-32:length]
data= decryption[:length-32].strip()
hasher = hashlib.sha256()
hasher.update(data)
hashCode = hasher.digest()
if(hash_code==hashCode):
array = data.decode().split(",",5)
print("expiry date is :"+ str(array[5]))
return array[0],array[1],array[2],array[3],array[4]
else:
return "","","","",""
def createTemp(inviter,email,role,pj_name,cmp_name):
delim = ','
data = inviter+delim+email+delim+role+delim+pj_name+delim+cmp_name+delim+str(datetime.datetime.now().time())
data = data.encode(encoding='utf_8', errors='strict')
hasher = hashlib.sha256()
hasher.update(data)
hashCode = hasher.digest()
encrypter = AES.new('1234567890123456', AES.MODE_CBC, 'this is an iv456')
# to make the link a multiple of 16 by adding for AES with the addition of spaces
newData = data+b' '*(len(data)%16)
result = encrypter.encrypt(newData+hashCode)
return result
#print(str(link).split(",",5))
link = createTemp("name","email#homail.com","Designer","Project Name","My Company")
print(link)
inviter,email,role,project,company = checkTemp(link)
The problem was not being able to putout a normal string because the encryption will result in characters that are almost impossible to encode, so the solution is to use binascii to encode the bStrings for us and decode them
import binascii
then we encode the resulting usable string for the link
hexedLink = binascii.hexlify(link).decode()
and we unhexify it before using it in the method
inviter,email,role,project,company = checkTemp(binascii.unhexlify(hexedLink))

Categories