python zip and AES encrypt the output using subprocess [duplicate] - python

This question already has answers here:
How to use `subprocess` command with pipes
(7 answers)
Why does subprocess use a list instead of a string with spaces by default?
(2 answers)
Closed 1 year ago.
I'm new to python and I would like to do a zip and having the output encrypted in AES via python using subprocess command.
The standard shell command I use is as below:
zip -9 - test.txt | openssl enc -aes-256-cbc -md sha256 -out test.ENC -pass pass:123456
I tried to use in in python like below:
import subprocess
compress = subprocess.Popen(['zip', '-9', 'test.txt'], stdout=subprocess.PIPE,)
subprocess.Popen(['openssl enc -aes-256-cbc -md=sha256 -pass pass:123456 -out', stdin=compress.stdout], stdin=compress.stdout,)
I'm getting an error:
File "test.py", line 3
subprocess.Popen(['openssl enc -aes-256-cbc -md=sha256 -pass pass:123456 -out test.ENC', stdin=compress.stdout], stdin=compress.stdout,)
Any help please?
Thanks.

Problems:
In my version of openssl, there is no -aes-256-cbc.
'-md=sha256' needs to be '-md', 'sha256'
Did you mean to send the output of openssl to a pipe?
import subprocess
compressor = subprocess.Popen(
['zip', '-9', 'test.txt'], stdout=subprocess.PIPE)
subprocess.Popen(
['openssl', 'enc', '-aes-256-cfb', '-md', 'sha256', '-pass','pass:123456'],
stdin=compressor.stdout)

Related

why is makeblastdb not working with syntax error

import sys
sys.path.append('/home/minhlam/ncbi-blast-2.10.1+/bin/db')
makeblastdb -in human.fa -db mouse.fa -out mousedb -outfmt 5
The error is:
File "parseBlast.py", line 5
makeblastdb -in human.fa -db mouse.fa -out mousedb -outfmt 5
^
SyntaxError: invalid syntax
I've checked multiple pages and other resources and this is just how you write it. Any help would be appreciated.
In general, I want to do a local blast search. I have 2 fasta files, one human.fa and one mouse.fa. I need to format the mouse.fa via makeblastdb and then run the blast. First month with python and need some help.
makeblastdb -in human.fa -db mouse.fa -out mousedb -outfmt 5 is a CLI command (ie a command you type in the terminal / shell / CMD).
It is not a valid Python syntax.
If you do want to execute it from within a Python script, you can use subprocess.Popen:
import sys
import subprocess
sys.path.append('/home/minhlam/ncbi-blast-2.10.1+/bin/db')
p = subprocess.Popen(['makeblastdb', '-in', 'human.fa', '-db', 'mouse.fa', '-out', 'mousedb', '-outfmt', '5'])

How to capture the output of openssl in python

I am trying to run the following openssl command in python:
cmd = "openssl x509 -sha1 -in esx.crt -noout -fingerprint"
tmp = os.popen(cmd)
tmp_sha1 = tmp.readline()
This command is supposed to generate a fingerprint of the certificate. I am trying to capture the output through the file object. But when I read this file object, there's nothing in it. I have executed this command on the command line and it runs fine, generates the fingerprint. Could you tell me how can I get the fingerprint?
You achieve this natively within Python using the OpenSSL module.
from OpenSSL.crypto import load_certificate, FILETYPE_PEM
cert_file_string = open("esx.crt", "rb").read()
cert = load_certificate(FILETYPE_PEM, cert_file_string)
sha1_fingerprint = cert.digest("sha1")
print sha1_fingerprint
You can use two modules to establish what you want: subprocess and os.
Using subprocess you can check for the output for the process using communicate(), which reads data from stdout and stderr until EOF.
>>> import subprocess
>>> p = subprocess.Popen("openssl x509 -sha1 -in 17.cert -noout -fingerprint", stdout=subprocess.PIPE)
>>> out, _ = p.communicate() #return a tuple (stdout, stderr)
>>> out
b'SHA1 Fingerprint=87:68:8B:B0:6A:E2:DF:A3:E2:63:76:97:A9:2B:B4:F4:82:4E:0B:D1\n'
Using os module works fine as well, using both read() and readline() methods: (please note that os.popen() is deprecated)
>>> import os
>>> p = os.popen("openssl x509 -sha1 -in 17.cert -noout -fingerprint")
>>> p.read()
'SHA1 Fingerprint=87:68:8B:B0:6A:E2:DF:A3:E2:63:76:97:A9:2B:B4:F4:82:4E:0B:D1\n'
>>> p = os.popen("openssl x509 -sha1 -in 17.cert -noout -fingerprint")
>>> out = p.readline()
'SHA1 Fingerprint=87:68:8B:B0:6A:E2:DF:A3:E2:63:76:97:A9:2B:B4:F4:82:4E:0B:D1\n'
If you want to write the value to a file, that works as well, which you can verify by opening a file output.txt in your current working directory:
>>> with open('./output.txt', 'w') as f:
... f.write(out)
...
77
The 77 notifies us that 77 bytes were written to the file, which you can verify by opening it in your favourite text editor.

Why is my OpenSSL-generated signature different than the signature from PyCryptodome?

I'm trying to validate a signature from OpenSSL's rsautl command with PyCryptodome. The Bash command I use to sign the data (data is "38b..da1" string) is:
echo 38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1 | openssl rsautl -inkey another_guys_priv_key.pem -sign | base64
I have converted this command into a Python script so I can compare things in Python:
from subprocess import Popen, PIPE
from shlex import split
# Use openssl to sign the data ("38b2..0da1") with another_guys private key
p1 = Popen(split('echo 38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'), stdout=PIPE)
p2 = Popen(split('openssl rsautl -inkey another_guys_priv_key.pem -sign'), stdin=p1.stdout, stdout=PIPE)
output, _ = p2.communicate()
Then I use PyCryptodome to sign the same data and compare the signatures:
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
# Use PyCrypto to sign the data with another_guys private key
key = RSA.importKey(open('another_guys_priv_key.pem').read())
signer = PKCS1_v1_5.new(key)
h = SHA256.new()
h.update('38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'.encode('utf-8'))
signature = signer.sign(h)
# Compare signature with OpenSSL signature
output == signature # False
and the results aren't the same.
So I was thinking that maybe OpenSSL automatically converts hexadecimal data into bytes and signs that, so I tried it with Python:
from binascii import unhexlify
# Use PyCryptodome to sign the hex-decoded data with another_guys private key
hh = SHA256.new()
hh.update(unhexlify('38b2be8850bbf6e52bee4d4c5889df436285479f5472efe856787d7068a50da1'))
hex_signature = signer.sign(hh)
# Compare signature with OpenSSL signature
output == hex_signature # False
but those results aren't the same either.
I'm obviously doing something wrong, but I'm not familiar enough with the Python crypto libraries to figure out what it is. What am I doing wrong?
The echo command (or shell built-in) adds a new line to the output by default, so signatures never match. Try disabling it.
$ echo -n foo | wc -c # hint - this counts number of bytes
3
$ echo foo | wc -c
4
But personally, I would just pass the string as standard input to the second process directly.

Call a shell command in python

I need to execute a shell command in python and need to store the result to a variable. How can I perform this.
I need to execute openssl rsautl -encrypt -inkey key and get the result to a variable.
---edit---
How can I execute
perl -e 'print "hello world"' | openssl rsautl -encrypt -inkey key
in python and get the output..
You can use subprocess.check_output
from subprocess import check_output
out = check_output(["openssl", "rsautl", "-encrypt", "-inkey", "key"])
The output will be stored in out.
A Simple way to execute a shell command is os.popen:
import os
cmdOutput1 = os.popen("openssl rsautl -encrypt -inkey key").readlines()
cmdOutput2 = os.popen("perl -e 'print \"hello world\"' | openssl rsautl -encrypt -inkey key").readlines()
All it takes is the command you want to run in the form of one String. It will return you an open file object. By using .readlines() this open file object will be converted to a list, where an Item in the List will correspond to a single line of Output from your command.

Using subprocess with openssl in a python script

I have thoroughly confused myself with Python subprocess syntax!
I would like to decrypt a string using openssl from within a Python script.
Here is the bash script snippet that works:
readable_code=$(echo "$encrypted_code"| openssl enc -aes-128-cbc -a -d -salt -pass pass:$key)
So in a python script - I understand that to run this same bash command I should use subprocess.
I need to Pipe the echo to the openssl command and as well pass in the encrypted_code and key variables dynamically(its in a loop).
Anyone out there know the correct syntax for this ?
Below's snippet should give the background to what i'm trying to do.
thank-you
import subprocess
key = "my-secret-key"
file = list_of_ips #format ip:long-encrypted-code
with open(file_read) as f:
#read in all connecion requests
content=f.readlines()
#create list that will hold all ips whose decrypted codes have passed test
elements = []
for ip_code in content:
#grab the ip address before the colon
ip = ip_code.split(':', 1)[0]
#grab the encrypted code after the colon
code = ip_code.split(':',1)[1]
#here is where I want to run the bash command and assign to a python variable
decrypted_code = subprocess....using code and key variables
...on it goes....
To emulate the shell command:
$ readable_code=$(echo "$encrypted_code"| openssl enc -aes-128-cbc -a -d -salt -pass "pass:$key")
using subprocess module in Python:
from subprocess import Popen, PIPE
cmd = 'openssl enc -aes-128-cbc -a -d -salt -pass'.split()
p = Popen(cmd + ['pass:' + key], stdin=PIPE, stdout=PIPE)
readable_code = p.communicate(encrypted_code)[0]
I highly recommend you to use Plumbum Python library to write shell scripts.
Particularly it has a convenient way to do piping and redirection.
I don't really understood what exact task you trying to solve, but your code could look approximately like this:
from plubum.cmd import openssl
with open('file') as f:
for ip_code in f:
(openssl['whatever', 'params'] << ip_code)()

Categories

Resources