编程语言
首页 > 编程语言> > Python / POpen / gpg:通过stdin或文件描述符提供密码和加密文本

Python / POpen / gpg:通过stdin或文件描述符提供密码和加密文本

作者:互联网

我正试图通过POpen通过python程序远程控制gpg.
我有一个包含加密数据的文件,我想解密,修改和写回磁盘重新加密.
目前,我将解密的信息存储在临时文件中(当程序结束时我将其粉碎).然后我对该文件执行修改,然后使用一个函数重新加密它,该函数通过stdin管道密码.
代码如下:

def encrypt(source, dest, passphrase, cipher=None):
  """Encrypts the source file.
  @param source Source file, that should be encrypted.
  @param dest Destination file.
  @param passphrase Passphrase to be used.
  @param cipher Cipher to use. If None or empty string gpg's default cipher is
  used.
  """
  phraseecho = Popen(("echo", passphrase), stdout=subprocess.PIPE)

  gpgargs = [
          "gpg",
          "-c",
          "--passphrase-fd", "0", # read passphrase from stdin
          "--output", dest,
          "--batch",
          "--force-mdc"]
  if not cipher is None and len(cipher) > 0:
      gpgargs.extend(("--cipher-algo", cipher))

  gpgargs.append(source)

  encrypter = Popen(
          gpgargs,
          stdin=phraseecho.stdout,
          stdout=subprocess.PIPE,
          stderr=subprocess.PIPE)
  stdout, stderr = encrypter.communicate()
  rc = encrypter.returncode
  if not rc == 0:
      raise RuntimeError(
              "Calling gpg failed with return code %d: %s" % (rc, stderr))

这非常有效,但我相当确定将敏感的,敏感的解密数据存储在临时文件中是一个相当大的安全漏洞.
所以我想以某种方式重写我的加密/解密功能,使它们能够完全在内存中工作,而不会在磁盘上存储敏感数据.
通过stdin管道密码并为解密数据捕获stdout,解密工作直接进行.

另一方面,加密让我很生气,因为我不能将密码和消息传递给`stdin’……至少

encrypter.stdin.write("%s\n%s" % (passphrase, message))

没用.
我的下一个最好的猜测是提供某种内存文件/管道/套接字的文件描述符或者任何–passphrase-fd参数.问题是:我不知道是否存在诸如内存文件之类的东西,或者是否适用套接字,因为我从未使用过它们.

任何人都可以帮助或指出我更好的解决方案吗?
解决方案不一定是可移植的 – 我只使用Linux方法完全没问题.

提前致谢…

编辑:
非常感谢你们,Lars和ryran.两种解决方案完美无缺不幸的是我只接受一个

解决方法:

下面是我在Obnam中用来运行gpg的代码,
也许它对你有所帮助.

def _gpg_pipe(args, data, passphrase):
    '''Pipe things through gpg.

    With the right args, this can be either an encryption or a decryption
    operation.

    For safety, we give the passphrase to gpg via a file descriptor.
    The argument list is modified to include the relevant options for that.

    The data is fed to gpg via a temporary file, readable only by
    the owner, to avoid congested pipes.

    '''

    # Open pipe for passphrase, and write it there. If passphrase is
    # very long (more than 4 KiB by default), this might block. A better
    # implementation would be to have a loop around select(2) to do pipe
    # I/O when it can be done without blocking. Patches most welcome.

    keypipe = os.pipe()
    os.write(keypipe[1], passphrase + '\n')
    os.close(keypipe[1])

    # Actually run gpg.

    argv = ['gpg', '--passphrase-fd', str(keypipe[0]), '-q', '--batch'] + args
    tracing.trace('argv=%s', repr(argv))
    p = subprocess.Popen(argv, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    out, err = p.communicate(data)

    os.close(keypipe[0])

    # Return output data, or deal with errors.
    if p.returncode: # pragma: no cover
        raise obnamlib.Error(err)

    return out


def encrypt_symmetric(cleartext, key):
    '''Encrypt data with symmetric encryption.'''
    return _gpg_pipe(['-c'], cleartext, key)


def decrypt_symmetric(encrypted, key):
    '''Decrypt encrypted data with symmetric encryption.'''
    return _gpg_pipe(['-d'], encrypted, key)

标签:python,pipe,ipc,gnupg
来源: https://codeday.me/bug/20190626/1289637.html