【问题标题】:Signing huge file with pyOpenSSL使用 pyOpenSSL 签署大文件
【发布时间】:2017-12-21 20:29:45
【问题描述】:

我需要使用Python 3pyopenssl 模块为大型*.tar.gz 文件(千兆字节数据)创建SSL signatures

以下是我的代码的简化摘录(有效)。有问题的行如下:

bytes_to_sign = sign_file.read()  # PROBLEM if file is LARGE

一次读取整个文件is probably not best idea,但我不知道如何以其他方式进行。

代码如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import OpenSSL
import argparse
import getpass
import logging

DIGEST_METHOD = 'sha256'
SSL_CERT_FORMAT_TYPE = OpenSSL.crypto.FILETYPE_PEM
LOG_FORMAT = '[%(asctime)s][ %(levelname)s ] %(message)s'


def create_args_parser():
    p = argparse.ArgumentParser(description='Simple SSL signature generator.')
    p.add_argument('file', type=argparse.FileType('rb'),
                   metavar='signed_file_path',
                   help='path to the file that will be signed')
    p.add_argument('--ssl-key', type=argparse.FileType(), 
                   metavar='CERT_PATH', required=True,
                   help='path to SSL certificate private key in PEM format')
    p.add_argument('-o', '--out', type=argparse.FileType('wb'),
                   metavar='SIGNATURE_PATH', required=True,
                   help='path where generated signature will be saved')
    return p


def get_priv_key_obj(ssl_key_file):
    """Get password protecting SSL private key and create private key object."""

    priv_key_str = ssl_key_file.read()
    ssl_key_file.close()  # https://stackoverflow.com/a/18863046/1321680
    priv_key = None

    while not priv_key:
        ssl_passwd = getpass.getpass()
        try:
            priv_key = OpenSSL.crypto.load_privatekey(SSL_CERT_FORMAT_TYPE,
                                                      priv_key_str,
                                                      ssl_passwd.encode('ascii'))
        except OpenSSL.crypto.Error:
            logging.warning('Probably wrong password - try again')

    return priv_key


def sign_file(priv_key, sign_file, out_file):
    """Sign given file with SSL private key and save signature in given file."""

    bytes_to_sign = sign_file.read()  # PROBLEM if file is LARGE
    sign = OpenSSL.crypto.sign(priv_key, bytes_to_sign, DIGEST_METHOD)
    sign_file.close()

    out_file.write(sign)
    out_file.close()


def main():
    parser = create_args_parser()
    args = parser.parse_args()
    priv_key = get_priv_key_obj(args.ssl_key)
    sign_file(priv_key, args.file, args.out)


if __name__ == '__main__':
    try:
        logging.basicConfig(format=LOG_FORMAT)
        main()
    except Exception as e:
        logging.exception('Generating SSL certificate has failed. Check if '
                          'SSL cert password is correct. Details: {}'.format(e))

脚本--help:

usage: sign.py [-h] --ssl-key CERT_PATH -o SIGNATURE_PATH signed_file_path

Simple SSL signature generator.

positional arguments:
  signed_file_path      path to the file that will be signed

optional arguments:
  -h, --help            show this help message and exit
  --ssl-key CERT_PATH   path to SSL certificate private key saved in PEM
                        format
  -o SIGNATURE_PATH, --out SIGNATURE_PATH
                        path where generated signature will be saved

有什么方法可以不同时read() 整个文件?


【问题讨论】:

  • 还没有,但我预计我会遇到问题,因为Python's official read() manual states 是: 当 size 省略或为负时,将读取并返回文件的全部内容;如果文件是你机器内存的两倍,那是你的问题。

标签: python python-3.x ssl ssl-certificate pyopenssl


【解决方案1】:

你必须实现你自己的chunked sign函数。
但是收件人呢,它能够验证吗?

阅读:EVP_DigestSignInit
EVP_DigestSignUpdate() 将 d 处的 cnt 个字节的数据散列到签名上下文 ctx 中。
可以在同一个 ctx 上多次调用此函数以包含其他数据。


改编自def sign(pkey, data, digest):

【讨论】:

  • 我没有时间重新实现 pyOpenSSL 库的一部分。我希望这个问题的解决会更容易。事实证明,pyOpenSSL 不够成熟和灵活,无法在复杂的软件中使用。 :-( 来自pyOpenSSL documentation 的引用:pyOpenSSL 是 OpenSSL 库(的子集)的一个相当薄的包装器。对于薄包装器,我们的意思是许多对象方法只不过是在OpenSSL 库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2012-08-22
  • 2022-07-20
  • 1970-01-01
  • 2013-02-05
  • 2014-05-15
相关资源
最近更新 更多