简体   繁体   English

用pyOpenSSL签名大文件

[英]Signing huge file with pyOpenSSL

I need to create SSL signatures for large *.tar.gz files (gigabytes of data) using Python 3 and pyopenssl module. 我需要使用Python 3pyopenssl模块为大型*.tar.gz文件(千兆字节的数据)创建SSL签名

Below is simplified excerpt of my code (that works). 下面是我的代码的简化摘录(有效)。 The problematic line is the following one: 问题行如下:

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

Reading whole file at once is probably not best idea but I don't know how to do it in other way. 一次读取整个文件可能不是最好的主意,但我不知道如何以其他方式进行。

Here is the code: 这是代码:

#!/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))

Script --help : 脚本--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

Is there any way to not read() the whole file at once? 有没有办法不一次read()整个文件?


You have to implement your own chunked sign Function. 您必须实现自己的chunked sign功能。
But what about the Recipient, will it be able to verify? 但是收件人可以验证吗?

Read about: EVP_DigestSignInit 阅读有关: EVP_DigestSignInit
EVP_DigestSignUpdate() hashes cnt bytes of data at d into the signature context ctx. EVP_DigestSignUpdate()将d处的cnt字节数据散列到签名上下文ctx中。
This function can be called several times on the same ctx to include additional data. 可以在同一ctx上多次调用此函数以包含其他数据。


Adapt from def sign(pkey, data, digest): 改用def符号(pkey,数据,摘要):

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM