zoukankan      html  css  js  c++  java
  • openssl_pkcs7_verify的问题之旅

    写在前面

    在做php的pkcs7签名校验的时候,遇到一个校验问题,我的情况是,生成的签名不包含证书信息,而在校验时一定要指定一个文件(对应参数$outfilename),用于存放从签名提取的证书。于是就很迷惑,签名都已经不包含证书了,怎么在没有证书的情况下提取证书,然后就看到一个网站,看起来好像是php的bug问题?

    bug提出地址

    php的openssl_pkcs7_verify源码地址:4077行

    /* {{{ proto bool openssl_pkcs7_verify(string filename, long flags [, string signerscerts [, array cainfo [, string extracerts [, string content]]]])
       Verifys that the data block is intact, the signer is who they say they are, and returns the CERTs of the signers */
    PHP_FUNCTION(openssl_pkcs7_verify)
    {
    	X509_STORE * store = NULL;
    	zval * cainfo = NULL;
    	STACK_OF(X509) *signers= NULL;
    	STACK_OF(X509) *others = NULL;
    	PKCS7 * p7 = NULL;
    	BIO * in = NULL, * datain = NULL, * dataout = NULL;
    	zend_long flags = 0;
    	char * filename;
    	size_t filename_len;
    	char * extracerts = NULL;
    	size_t extracerts_len = 0;
    	char * signersfilename = NULL;
    	size_t signersfilename_len = 0;
    	char * datafilename = NULL;
    	size_t datafilename_len = 0;
    
    	RETVAL_LONG(-1);
    
    	if (zend_parse_parameters(ZEND_NUM_ARGS(), "pl|papp", &filename, &filename_len,
    				&flags, &signersfilename, &signersfilename_len, &cainfo,
    				&extracerts, &extracerts_len, &datafilename, &datafilename_len) == FAILURE) {
    		return;
    	}
    
    	if (extracerts) {
    		others = load_all_certs_from_file(extracerts);
    		if (others == NULL) {
    			goto clean_exit;
    		}
    	}
    
    	flags = flags & ~PKCS7_DETACHED;
    
    	store = setup_verify(cainfo);
    
    	if (!store) {
    		goto clean_exit;
    	}
    	if (php_openssl_open_base_dir_chk(filename)) {
    		goto clean_exit;
    	}
    
    	in = BIO_new_file(filename, (flags & PKCS7_BINARY) ? "rb" : "r");
    	if (in == NULL) {
    		goto clean_exit;
    	}
    	p7 = SMIME_read_PKCS7(in, &datain);
    	if (p7 == NULL) {
    #if DEBUG_SMIME
    		zend_printf("SMIME_read_PKCS7 failed
    ");
    #endif
    		goto clean_exit;
    	}
    
    	if (datafilename) {
    
    		if (php_openssl_open_base_dir_chk(datafilename)) {
    			goto clean_exit;
    		}
    
    		dataout = BIO_new_file(datafilename, "w");
    		if (dataout == NULL) {
    			goto clean_exit;
    		}
    	}
    #if DEBUG_SMIME
    	zend_printf("Calling PKCS7 verify
    ");
    #endif
    
    	if (PKCS7_verify(p7, others, store, datain, dataout, (int)flags)) {
    
    		RETVAL_TRUE;
    
    		if (signersfilename) {
    			BIO *certout;
    
    			if (php_openssl_open_base_dir_chk(signersfilename)) {
    				goto clean_exit;
    			}
    
    			certout = BIO_new_file(signersfilename, "w");
    			if (certout) {
    				int i;
    				signers = PKCS7_get0_signers(p7, NULL, (int)flags);
    
    				for(i = 0; i < sk_X509_num(signers); i++) {
    					PEM_write_bio_X509(certout, sk_X509_value(signers, i));
    				}
    				BIO_free(certout);
    				sk_X509_free(signers);
    			} else {
    				php_error_docref(NULL, E_WARNING, "signature OK, but cannot open %s for writing", signersfilename);
    				RETVAL_LONG(-1);
    			}
    		}
    		goto clean_exit;
    	} else {
    		RETVAL_FALSE;
    	}
    clean_exit:
    	X509_STORE_free(store);
    	BIO_free(datain);
    	BIO_free(in);
    	BIO_free(dataout);
    	PKCS7_free(p7);
    	sk_X509_free(others);
    }
    /* }}} */
    
    

    简单看了下,前面部分基本是读取签名和证书信息,而从(PKCS7_verify(p7, others, store, datain, dataout, (int)flags)这句开始,这部分应该是校验p7签名,在校验通过之后,会判断是否指定了存放证书的文件$outfilename(该证书从签名里提取)。

    在正常签名包含证书的情况下,因为提取的证书存放文件($outfilename)没有默认值,是个必填参数,所以只要指定了就不会出错。

    但是在签名没有包含证书的情况下,应该是无法提取证书的,可是指定证书文件是个必填参数。如果随便指定个文件,会报无法提取证书的错误;如果指定$outfilename为null的话,会有错误信息提示无法写入啥的,报错会有警告,其中一段就包含了signature OK, but cannot open xxxxxxxxxx。

    所以简单总结的话,似乎是php的判断不够严谨导致的问题。

    不够本人对这些了解的不多,如果因为自己错漏导致的理解错误,希望能有人及时指出,非常感谢!

  • 相关阅读:
    php pdo备份还原数据库方法
    php抛出异常
    手机H5支持视频的比特率
    linux 安装imagick方法 php5.4以上都能用
    lnmp一键安装包 成功运行thinkphp的方法
    NAVICAT文件名目录或卷标语法不正确怎么办
    Linux下捕捉键盘事件
    linux 下shell脚本备份文件
    MQTT学习笔记
    windows生成dump文件
  • 原文地址:https://www.cnblogs.com/inkqx/p/14486586.html
Copyright © 2011-2022 走看看