【问题标题】:In Python need to keep openssl alive and keep giving it commands在 Python 中需要保持 openssl 存活并不断给它命令
【发布时间】:2017-12-22 12:08:11
【问题描述】:

我已经尝试使用以下实现提到here 的方法:

from subprocess import PIPE, Popen

process = Popen(['/usr/bin/openssl', 'enc', '-aes-256-cbc', '-a', '-pass', 'pass:asdf'], stdin=PIPE, stdout=PIPE)
process.stdin.write('Hello this is it')
process.stdin.flush()
print(repr(process.stdout.readline()))

但它卡在 readline() 虽然我已经写过并刷新了。我还尝试了提到here 的非阻塞方法,但这也阻塞了 readline()。以下是我后一种方法的代码:

import sys
import time
from subprocess import PIPE, Popen
from threading import Thread
from Queue import Queue, Empty

def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()

def write_to_stdin(process):
    process.stdin.write(b'Hello this is it')

p = Popen(['/usr/bin/openssl', 'enc', '-aes-256-cbc', '-a', '-pass', 'pass:asdf'], stdin=PIPE, stdout=PIPE, bufsize=-1, close_fds=ON_POSIX)
q = Queue()

t2 = Thread(target=write_to_stdin, args=(p,))
t2.daemon = True
t2.start()

t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True  # thread dies with the program
t.start()

try:
    line = q.get(timeout=3) # or q.get(timeout=.1)
except Empty:
    print('no output yet')
else:
    print line

我得到没有输出作为输出。

唯一有效的方法是使用:

process.communicate

但这会关闭进程,我们必须再次重新打开进程。对于要加密的大量消息,这需要花费太多时间,我试图避免包含任何外部包来完成此任务。任何帮助将不胜感激谢谢。

【问题讨论】:

  • 请也标记 Python。
  • 添加了 Python 标签。

标签: python linux python-2.7 openssl aes


【解决方案1】:

process.stdin.flush() 替换为process.stdin.close(),如下所示:

from subprocess import PIPE, Popen

process = Popen(['/usr/bin/openssl', 'enc', '-aes-256-cbc', '-a', '-pass', 'pass:asdf'], stdin=PIPE, stdout=PIPE)
process.stdin.write('Hello this is it')
process.stdin.close()
print(repr(process.stdout.readline()))

readline() 不再阻止。

解释是openssl enc一直等到它的标准输入结束,只有当调用进程关闭管道时才到达。

【讨论】:

  • 知道了,但是我怎样才能在不需要实例化另一个 Popen() 的情况下重新打开 process.stdin。这可能吗 ?因为我需要在不关闭进程的情况下继续沟通。
  • 不,你不能。如果要分别加密几块数据,则需要运行多个 openssl 命令,因此需要运行多个子进程。
  • 好的,非常感谢。现在我将尝试使用 ctype "code.google.com/archive/p/ctypescrypto" 这样就不需要产生 openssl 进程了。
【解决方案2】:

在 linux 中使用ctypescrypto 找到了另一种执行此操作的方法。这不需要任何额外的外部依赖(只需在您的代码中包含所有给定的源文件,因为许可证允许我们这样做)并且在性能方面它应该非常快,因为可用的函数是用 C 编译的。

在 Linux 上为 test.py 我们必须替换:

crypto_dll = os.path.join(r'C:\Python24', 'libeay32.dll')
libcrypto = cdll.LoadLibrary(crypto_dll)

与:

from ctypes.util import find_library

crypto_dll = find_library('crypto')  # In my case its 'libcrypto.so.1.0.0'
libcrypto = cdll.LoadLibrary(crypto_dll)

更改后,以下示例有效:

import cipher
from ctypes import cdll
from base64 import b64encode
from base64 import b64decode

libcrypto = cdll.LoadLibrary('libcrypto.so.1.0.0')
libcrypto.OpenSSL_add_all_digests()
libcrypto.OpenSSL_add_all_ciphers()

# Encryption
c = cipher.CipherType(libcrypto, 'AES-256', 'CBC')
ce = cipher.Cipher(libcrypto, c, '11111111111111111111111111111111', '1111111111111111', encrypt=True)
encrypted_text = b64encode(ce.finish("Four Five Six"))
print encrypted_text


# Decryption
cd = cipher.Cipher(libcrypto, c, '11111111111111111111111111111111', '1111111111111111', encrypt=False)
plain_text = cd.finish(b64decode(encrypted_text))
print plain_text

【讨论】:

    猜你喜欢
    • 2012-03-08
    • 2018-05-10
    • 2014-05-09
    • 1970-01-01
    • 2014-04-19
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多