I am using Python subprocess module but the results are unexpected. I have successfully determined the correct command line strings (using another language) but cannot get a Python equivalent to work.
So I wrote some code in VBA which uses a Windows COM type library to spawn process and capture stdout, stderr. Using this I managed to write my program which generates elliptic curve keys and sign a file etc. An example command line which would run fine would be this
C:\Progra~1\OpenSSL-Win64\bin\openssl.exe ecparam -genkey -name secp384r1 -out n:\ECDSA\2017-11-30T203401\ec_key.pem
I am trying to convert the code to Python so that it runs on a linux box. I am using the same strategy in that I am spawning shells (because i have figured out all the right arguments in the VBA equivalent). I am not using a Python API like pyOpenSSL.
So I am using the subprocess module. I have never used this and am having trouble, initially I couldn't get the thing to work at all. I have managed to get something working but it looks like instead of executing the whole statement and generating a file (in the case given) it is instead dropping me into the OpenSSL prompt. That is to say it is not processing the arguments correctly. Here is my Python code
import os
import subprocess
import sys
class Expando(object):
pass
def RunShellAndWait(sExe, aArgs):
print(sExe + ' ' + ' '.join(aArgs))
# https://stackoverflow.com/questions/4760215/running-shell-command-from-python-and-capturing-the-output#answer-4760517
if (sys.platform[:3]=='win'):
suinfo = subprocess.STARTUPINFO()
suinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
SW_SHOWMAXIMIZED = 3
suinfo.wShowWindow = SW_SHOWMAXIMIZED
try:
result = subprocess.run(args=aArgs,executable=sExe,stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE,startupinfo=suinfo)
except:
print( "something went wrong with subprocess.run \r\nexec " + sExe + ' ' + ' '.join(aArgs))
else:
suinfo = None
retVal=Expando()
retVal.returnCode = result.returncode
retVal.sStdOut = result.stdout.decode('utf-8')
retVal.sStdErr = result.stderr.decode('utf-8')
return retVal
def OpenSSL_GenECDSAKeys(sBatchDir, sEcdsaKeyFile, sEcdsaPublicKeyDerFile,sEcdsaPublicKeyPemFile):
if os.path.isfile(sOPENSSL_BIN)!=True:
print("Cannot find OpenSSL.exe! " + sOPENSSL_BIN)
return false
if os.path.isfile(sEcdsaKeyFile)==True:
os.removefile (sEcdsaKeyFile)
try:
aGenKeyArgs = [' ecparam -genkey -name secp384r1 -out ' + sEcdsaKeyFile]
aGenKeyStatus = RunShellAndWait(sOPENSSL_BIN, aGenKeyArgs)
...
I concude that it is dropping into interactive mode because with stdout capture says "OpenSSL>" which is OpenSLL interactive prompt, i.e. I can just run OpenSSL.exe on its own and I get that prompt. Also the expected file is not generated.
I tried experiment with Popen but it did not like it. I am hoping someone has trodden this path before me and can point out a pitfall.
So the question is how to get OpenSSL to acknowledge and process the given arguments instead of dropping into interactive mode.