常见问题(FAQ) MISC 各种各样的问题 1、OpenSSL的当前版本是哪个? 2、文档在哪里? 3、我如何联系OpenSSL开发人员? 4、我从哪里得到OpenSSL的预编译版本? 5、为什么不用'autoconf'和'libtool'? 6、'engine'版本是什么? 7、我如何检测OpenSSL发行的真实性? LEGAL 法律问题 1、我用OpenSSL需要专利授权吗? 2、我能不能在GPL软件中使用OpenSSL? USER 用OpenSSL应用程序的问题 1、为什么我得到"PRNG not seeded"的错误消息? 2、为什么我得到"unable to write 'random state'"的错误消息? 3、我如何建立证书或者证书请求? 4、为什么我不能建立证书请求? 5、为什么因为证书验证错误而失败? 6、为什么在我用OpenSSL连接服务器时只能用弱加密? 7、我如何建立DSA证书? 8、为什么我不能用DSA证书建立一个SSL连接? 9、我如何在私钥上删除短语? 10、为什么我在SSL客户认证不能用OpenSSL证书? 11、为什么我的浏览器给我一个关于缺少匹配主机的警告? 12、我如何安装一个CA证书到我的浏览器? 13、为什么OpenSSL x509 DN输出不符合RFC2253? 14、"128位证书"是什么? 我能够用OpenSSL建立一个吗? BUILD 安装和测试OpenSSL的问题 1、为什么连接器发出undefined symbols错误? 2、为什么OpenSSL因为"bc: command not found"测试失败? 3、为什么OpenSSL因为"bc: 1 no implemented"测试失败? 4、为什么OpenSSL因为"bc: stack empty"测试失败? 5、为什么OpenSSL在Alpha Tru64 UNIX上编译失败? 6、为什么OpenSSL因为"ar: command not found"编译失败? 7、为什么OpenSSL在Win32平台用VC++编译失败? 8、OpenSSL在Redhat上有什么特殊? 9、为什么OpenSSL在MacOS X上编译失败? 10、为什么OpenSSL测试套件在MacOS X上失败? 11、为什么OpenSSL测试套件在BN_sqr测试失败[在64位平台]? 12、为什么OpenBSD-i386在des-586.s上因为'unimplemented segment type'建立失败? 13、为什么OpenSSL测试套件在x86 CPU上sha512t中失败? 14、为什么编译器编译sha512.c失败? PROG OpenSSL程序设计问题 1、OpenSSL是线程安全的吗? 2、我在Windows上编译了一个程序,它崩溃了: 为什么? 3、我如何用ASN1函数读或者写一个DER编码缓冲? 4、OpenSSL用DER,但是我需要BER格式:OpenSSL支持BER吗? 5、我尝试用,我得到错误,为什么? 6、我调用,它失败了,为什么? 7、我仅仅从错误输出中得到一串数字,它们意味着什么? 8、为什么我得到未知算法的错误? 9、为什么OpenSSH配置脚本不能检测OpenSSL? 10、我能不能以非阻塞IO用OpenSSL的SSL库? 11、为什么我的服务器程序没有接收一个客户端证书? 12、为什么因为一个未定义标记NID_uniqueIdentifier编译失败? 13、我认为我检测到一个内存泄漏, 这是BUG吗? [MISC] 1、OpenSSL的当前版本是哪个? 当前的版本在http://www.openssl.org上有效。OpenSSL 0.9.8在2005年七月5日发布。 除了当前的稳定发布版本之外,你也能够访问ftp://ftp.openssl.org/snapshot/下的开发版本的每日快照, 或者通过匿名CVS访问。 2、文档在哪里? OpenSSL是一个库,为安全WEB服务器这样的程序提供加密功能。你应该读你想用的程序的文档。 INSTALL文件解释如何安装这个库。 OpenSSL包括命令行工具,能够用来执行不同的加密功能。它在OpenSSL手册页中描述。 给开发人员的文档当前正在编写中。少量的手册页已经有效了; 介绍libcrypto和libssl的文档在crypto手册和ssl手册中。 libcrypto的部分信息还没有文档,你可以读Ariel Glenn的SSLeay 0.9文档, 在http://www.columbia.edu/~ariel/ssleay/.大部分在OpenSSL中是有用的。 证书扩展和PKCS#12的文档在doc/openssl.txt中。 原始的SSLeay文档包含在doc/ssleay.txt中,在没有其它资源帮助情况下,这是很有用的, 但是请注意荒废的版本SSLeay0.6.6。 3、我如何联系OpenSSL开发人员? README文件描述如何提交错误报告和补丁到OpenSSL。OpenSSL邮件列表在http://www.openssl.org上有效. 4、我从哪里得到OpenSSL的预编译版本? 你能够在http://www.openssl.org/related/binaries.html找到二进制发布。 某些用OpenSSL的程序用二进制形式发布。当你用这样的程序时,你不需要自己安装OpenSSL; 应用程序将包含需要的部分(DLLs)。 如果你想在Windows系统编译OpenSSL,但是没有C变压器,读INSTALL.W32中的"Mingw32"部分, 获得如何获取和安装免费GNU C变压器的信息。 一系列Linux和*BSD发布中包含了OpenSSL。 5、为什么不用'autoconf'和'libtool'? autoconf将可以在将来的OpenSSL版本中使用。如果它少一些以UNIX为中心,它可能更容易使用。 6、'engine'版本是什么? OpenSSL版本0.9.6扩展接口到外部加密硬件。这在一个特殊的发行'0.9.6-engine'中实现。 在版本0.9.7,这个改变被整合到开发线,所以不再需要特殊的发行了。 7、我如何检测OpenSSL发行的真实性? 我们为每个TAR包提供MD5摘要和ASC签名。用MD5检测来自镜像站点的TAR包命名为: md5sum TARBALL | awk '{print $1;}' | cmp - TARBALL.md5 你能够用pgp或者gpg检测真实性,你需要OpenSSL社团公钥来签名它(从密钥服务器下载, 密钥列表在http://www.openssl.org/about/).然后仅仅做: pgp TARBALL.asc [LEGAL] 1、我用OpenSSL需要专利授权吗? 如果你想用OpenSSL,README文件中patents部分可能应用到你。对于知识产权信息,请联系律师。 OpenSSL社团不提供法律顾问。 你能够配置OpenSSL不用IDEA,MDC2和RC5,用: ./config no-idea no-mdc2 no-rc5 2、我能不能在GPL软件中使用OpenSSL? 在许多系统中,包括主要的Linux和BSD发布,是的(GPL不限制你使用操作系统发布的库)。 在其它系统,这个情形是很模糊的。如果你用OpenSSL使用操作系统没有包括OpenSSL的软件, 有些GPL软件版权持有者控告你违反了他们的版权。 如果你用OpenSSL开发开源软件,你可以选择GPL之外的授权,或者明白的申明 "This program is released under the GPL with the additional exemption that compiling, linking, and/or using OpenSSL is allowed." 如果你用其它开发人员开发的GPL软件, 你可以联系版权持有者允许通过OpenSSL使用他们的软件。 [USER] 1、为什么我得到"PRNG not seeded"的错误消息? 加解密软件需要一个不可预知的数据源来正确的工作。许多开源操作系统提供一个"随机数设备" (/dev/urandom or /dev/radnom)作为这个用途。所有OpenSSL版本默认尝试用/dev/urandom;从版本0.9.7开始, 如果/dev/urandom无效的话,OpenSSL也尝试/dev/random。 在其它操作系统,程序在生成密钥执行公钥加密之前,必须用适当的数据调用RAND_add()或者RAND_seed()函数。 (这些函数初始化伪随机数产生器,PRNG.).某些错误的程序没有这样做。在版本0.9.5,如果随机数生成器没有128位随机种子, OpenSSL函数需要随机的报告一个错误。如果发生了这个错误,而没有在你使用的程序文档中讨论,请联系程序作者; 这应该从不能正确工作。OpenSSL0.9.5和后续版本通过拒绝执行不安全加密来反应这个错误。 如果你用Solaris 8,你能够通过安装补丁112438(Sparc)或者112439(x86)加入/dev/urandom和/dev/random设备, 这可以通过PatchFinder在http://sunsolve.sun.com找到(Solaris 9默认包含这些设备).对于早期版本的Solaris支持/dev/random, 参考Sun的站点http://sunsolve.sun.com/pub-cgi/retrieve.pl?doc=fsrdb/27606&zone_32=SUNWski(SUNWski包是有效在补丁105710). 在没有/dev/urandom和/dev/random的系统中,最好的办法是用平均信息量聚集程序(EGD);参考RAND_egd()手册页。 版本0.9.7开始,OpenSSL自动的在/var/run/egd-pol, /dev/egd-pool, /dev/egd-pool和/etc/entropy中查询EGD Socket。 openssl命令行工具的许多组件自动尝试从文件生成随机数。默认的种子文件按下面的方式决定:如果环境变量RANDFILE被设置, 那么它的名称是种子文件。否则如果环境变量HOME被设置,那么种子文件是$HOME/.rnd。如果RANDFILE和HOME都没有设置, 版本低于0.9.6将用在当前目录的文件.rnd,0.9.6a用非默认的种子文件。OpenSSL0.9.6b和后面行为类似0.9.6a,但是在Windows平台, 如果没有设置HOME环境变量,将用默认的"C"\"。 如果默认的种子文件不存在,或者太短,将发生"PRNG not seeded"错误消息。 openssl命令行工具工具将回写新的状态到默认种子文件(如果需要就建立它),除非没有足够的种子。 指向$RANDFILE到平均信息量聚集程序socket不工作。用openssl的命令行选项'-rand'替代。 $RANDFILE环境变量和$HOME/.rnd仅仅是用在openssl命令行工具。用OpenSSL库的程序提供他们自己的配置选项来指定特殊的平均信息源, 请参考程序自带的文档。 2、为什么我得到"unable to write 'random state'"的错误消息? 有时openssl命令行工具不用"PRNG not seeded"错误消息中断,而是抱怨"unable to write 'random state'"。 这个消息说明默认种子文件(参考前面的答案).一个可能的原因是没有默认的文件名,因为RANDFILE和HOME都没有设置。 (版本低于0.9.6的用当前目录的".rnd",但是在0.9.6a中改变了) 3、我如何建立证书或者证书请求? 找到CA.pl手册页,这提供一个简单的'req', 'verify', 'ca'和'pkcs12'工具的包装。 4、为什么我不能建立证书请求? 一般你将得到下列错误: unable to find 'distinguished_name' in config problems making Certificate Request 这是因为它不能找到配置文件,参考req文件DIAGNOSTICS部分得到更多信息。 5、为什么因为证书验证错误而失败? 这个问题通常通过日志消息指出,说明象"unable to get local issuer certificate"或者"self signed certificate"这些事情。 当一个证书被验证,它的跟证书对OpenSSL必须是“信任的”,这意味着CA证书必须放置在某个目录或者文件,相关的程序配置去读它。 OpenSSL程序"验证"行为在类似的方法,并且发出类似的错误:查看verify手册。 6、为什么在我用OpenSSL连接服务器时只能用弱加密? 这确实是的,因为你用老的"export grade"浏览器,只支持弱加密。更新你的浏览器去支持128位加密。 7、我如何建立DSA证书? 查看CA.pl手册。 8、为什么我不能用DSA证书建立一个SSL连接? 9、我如何在私钥上删除短语? 10、为什么我在SSL客户认证不能用OpenSSL证书? 11、为什么我的浏览器给我一个关于缺少匹配主机的警告? 12、我如何安装一个CA证书到我的浏览器? 13、为什么OpenSSL x509 DN输出不符合RFC2253? 14、"128位证书"是什么? 我能够用OpenSSL建立一个吗? [BUILD] 1、为什么连接器发出undefined symbols错误? 可能编译被中断了,并且make没有通知缺少某些东西,运行"make clean; make". 如果你用./configure而不是./config,确保你选择了正确的目标。文件格式在不同的OS之间可能有些不同(例如, sparcv8/sparcv9, 或者a.out/elf). 在你得到下面标记错误的情况下,用config选项"no-asm",在INSTALL中描述: BF_cbc_encrypt, BF_decrypt, BF_encrypt, CAST_cbc_encrypt, CAST_decrypt, CAST_encrypt, RC4, RC5_32_cbc_encrypt, RC5_32_decrypt, RC5_32_encrypt, bn_add_words, bn_div_words, bn_mul_add_words, bn_mul_comba4, bn_mul_comba8, bn_mul_words, bn_sqr_comba4, bn_sqr_comba8, bn_sqr_words, bn_sub_words, des_decrypt3, des_ede3_cbc_encrypt, des_encrypt, des_encrypt2, des_encrypt3, des_ncbc_encrypt, md5_block_asm_host_order, sha1_block_asm_data_order 如果上面的帮助没有用,你可以尝试用当前的快照。如果还是有问题,请提交一个错误报告。 2、为什么OpenSSL因为"bc: command not found"测试失败? 你没有安装"bc" - UNIX计算器。如果你想运行测试,从ftp://ftp.gnu.org或者你的OS发布商哪里获取GNU bc。 3、为什么OpenSSL因为"bc: 1 no implemented"测试失败? 在一些SCO安装或者版本中,bc有个BUG,当你运行测试套件是触发(用make test).返回的消息是:"bc: command not found". 最好的方法是寻找另外的bc实现进行编译安装。GNU bc(参考http://www.gnu.org/software/software.html下载)能够安全的使用。 4、为什么OpenSSL因为"bc: stack empty"测试失败? 在一些DG/ux版本中,bc只有太小的栈用来计算,openssl的bntest抛出这个错误。这在你运行测试套件时触发(make test)。 返回的消息是:"bc: stack empty"。 最好的方法是寻找另外的bc实现进行编译安装。GNU bc(参考http://www.gnu.org/software/software.html下载)能够安全的使用。 5、为什么OpenSSL在Alpha Tru64 UNIX上编译失败? 在一些运行Tru Unix和Compaq C的Alpha安装中,编译crypto/sha/sha_dgst.c出现错误: 'Fatal: Insufficient virtual memory to continue compilation.'。这可能是一个编译器BUG。 吃掉这么多内存来编译某些东西(可能是一个表)会发生什么呢。这个问题在优化代码中没有的,... 解决这个问题有三个方法: 1、设置你当前数据段大小软限制更高。经验表明在AlphaServer DS10上大约241000KB看起来足够。你用命令'ulimit -Sd nnnnnn'完成, 'nnnnnn'是一个数字。 2、如果你因为硬限制低于你的需求,并且你不能改变,你能够用-O0优化级别编译全部OpenSSL,这对于想得到最好OpenSSL的人不是一个好主意, 一个更复杂的解决方案是下列的: ----- snip:start ----- make DIRS=crypto SDIRS=sha "`grep '^CFLAG=' Makefile.ssl | \ sed -e 's/ -O[0-9] / -O0 /'`" rm `ls crypto/*.o crypto/sha/*.o | grep -v 'sha_dgst\.o'` make ----- snip:end ----- 这将只用-O0编译sha_dgst.c,剩余的优化级别是配置过程选择,当上面的完成之后,进行测试,和安装。 3、重新用no-sha0选项配置工具包来去除SHA0,这不应该使用,并且不能用在SSL/TLS协议中。 6、为什么OpenSSL因为"ar: command not found"编译失败? 在Solaris 2上经常返回这个错误,因为SUN隐藏'ar'和其它开发命令到非$PATH的目录中。 这些目录是'/usr/ccs/bin'.最快的解决方法是按下面的做: ----- snip:start ----- PATH=${PATH}:/usr/ccs/bin; export PATH ----- snip:end ----- 然后重新编译。你应该做的事情是确保'/usr/ccs/bin'永久的在你的$PATH,例如通过你的.profile(再次,假设你用一个sh兼容的shell). 7、为什么OpenSSL在Win32平台用VC++编译失败? 有时候,你可能从VC++命令行(cl)得到报告 9、为什么OpenSSL在MacOS X上编译失败? 10、为什么OpenSSL测试套件在MacOS X上失败? 11、为什么OpenSSL测试套件在BN_sqr测试失败[在64位平台]? 12、为什么OpenBSD-i386在des-586.s上因为'unimplemented segment type'建立失败? 13、为什么OpenSSL测试套件在x86 CPU上sha512t中失败? 14、为什么编译器编译sha512.c失败? [PROG] 1、OpenSSL是线程安全的吗? YES(是有限的:一个SSL连接不能用在多个线程中)。在Windows和许多UNIX系统中,OpenSSL自动的用多线程作为标准库。 如果你的平台不是这些,请参考INSTALL文件。 2、我在Windows上编译了一个程序,它崩溃了: 为什么? 这通常是因为你忽视了INSTALL.W32中的注释。你的程序必须连接openssl库连接的Win32 C运行时库。默认的版本是 /MD - "Multithreaded DLL". 如果你用VC++ IDE,在许多情况下,你的新项目选择默认的"Debug Singlethreaded"-/ML,这和/MD是不可以交换的, 你的程序将崩溃,典型的在你第一次调用BIO读写相关操作时。 在win32中,对于六个可能的连接配置,你的程序必须连接正确的OpenSSL。如果你用MS VC++(Studio),这能够按下面 的改变: 1、从project菜单选择setting... 2、选择C++标签。 3、从"Category"下拉列表框选择"Code Generation"。 4、从"Use run-time library"下拉列表框中选择正确的库(参考下表),为你的DEBUG和RELEASE版本执行这个步骤 (在左上的设置面板在两个之间改变) Single Threaded /ML - MS VC++经常用这个作为新项目发行版本的默认设置 Debug Single Threaded /MLd - MS VC++经常用这个作为新项目调试版本的默认设置 Multithreaded /MT Debug Multithreaded /MTd Multithreaded DLL /MD - OpenSSL默认用这个 Debug Multithreaded DLL /MDd 注意Debug和Release库是不可相互交换的,如果你用/MD编译OpenSSL,你的程序必须用/MD,而不能用/MDd。 在0.9.8中,上面的限制对与.DLLs被排除.OpenSSL的.DLLs用一些特殊额运行时选项编译[我们推荐默认的/MD], 能够用在程序编译时用不同的选项甚至编译器,但是这是一个catch!代替重新编译OpenSSL,你将用前面的版本, 你不得不用你选择的编译器和选项编译一小段代码。小段代码安装在/include/openssl/applink.c, 并且应该加入到你的项目或者简单的#include-d到一个源代码文件中[仅一个],失败.."no OPENSSL_Applink"错误。 3、我如何用ASN1函数读或者写一个DER编码缓冲? 你有两个选项,你能够用内存BIO与i2d_*_bio()或者d2i_*_bio()函数一起或者你能够直接用i2d_*(),d2i_*()函数。 因为这经常导致麻烦,下面用PKCS7代码例子说明: unsigned char *buf, *p; int len; len = i2d_PKCS7(p7, NULL); buf = OPENSSL_malloc(len); /* or Malloc, error checking omitted */ p = buf; i2d_PKCS7(p7, &p); 到这里,buf包含p7编码的DER的长度字节。 相反的,假设已经在buf中包含长度字节: unsigned char *p; p = buf; p7 = d2i_PKCS7(NULL, &p, len); 到这里,p7包含一个有效的PKCS7空结构,如果发生错误,应该用ERR_print_errors(bio)得到更多信息。 p存在的原因是ASN1函数增加传递的指针,这样它能够准备读写下个结构。这经常引起问题:没有临时变量, 缓冲指针指向被读或写的数据之后。当尝试释放缓存将有不可预知的结果,因为指针地址已经改变。 4、OpenSSL用DER,但是我需要BER格式:OpenSSL支持BER吗? 最简单的答案是YES,因为DER是BER的特殊情况,OpenSSL ASN1能够解码和处理BER。 详细的答案是ASN1结构能够用一系列不同的编码。一部分是基本编码规则(BER),用不同的允许的编码,BER的一个 限制是高贵编码规则(DER):它们唯一的指定一个给定的结构如何编码。 因此,因为DER是BER的特殊情况,DER是BER一个可接收的编码。 5、我尝试用,我得到错误,为什么? 这通常在你尝试用C++编译器编译用PKCS#12宏的代码。几乎可以在程序中从不用PKCS#12宏,解析和建立PKCS#12证书用 PKCS12_parse()和PKCS12_create()函数是非常简单的,它的文档在doc/openssl.txt,例子在demos/pkcs12,'pkcs12' 程序用宏是用来打印调试信息。 6、我调用,它失败了,为什么? 在提交报告或者询问邮件列表之前,你应该尝试确定原因。你可以在调用失败后调用ERR_print_errors()或者 ERR_print_errors_fp(),然后查看消息帮助。注意问题可能比你想的简单-你应该尽可能在每个调用之后都检测 错误,否则真实的问题可能被隐藏,因为某些OpenSSL函数要清除错误状态。 7、我仅仅从错误输出中得到一串数字,它们意味着什么? 真实的格式在ERR_print_errors()手册页中描述,你应该在处理之前调用函数ERR_load_crypto_strings(),那么 将输出文本格式。如果你不能这样做(例如它是预编译的二进制),你能够在错误代码上用errstr工具(第二个冒号 之后的十六进制数字)。 8、为什么我得到未知算法的错误? 这在几种情况下可能发生,例如读加密私钥或者尝试解密PKCS#12证书,原因是忘记用OpenSSL_add_all_algorithms() 加载OpenSSL的算法表。参考手册页。 9、为什么OpenSSH配置脚本不能检测OpenSSL? 自动检测存在问题有几个原因。OpenSSH至少需要OpenSSL 0.9.5a,有时系统发行在系统位置安装的是旧版本,在检测时 没有检测到新版本。OpenSSL库可能是为其它CPU或者其它模式(32/64位)编译的,可能不允许。 通用的解答是检测OpenSSH配置脚本生成的config.log文件,它应该包含为什么OpenSSL库没有检测到或者不兼容的详细信息。 10、我能不能以非阻塞IO用OpenSSL的SSL库? YES,请读SSL_get_error(3)手册页。 避免一个缺陷:不要假设SSL_read()将仅仅从下面的传输层读取,或者SSL_write()仅仅写到里面——可能SSL_write() 直到有数据读取之前不能工作,或者SSL_read()直到可能发送数据之前不能做任何事情。可能的一个原因是在协议的 任何时候,Peer可能需要一个新的SSL/TLS握手,请求双向消息交换。SSL_read()和SSL_write()都会尝试继续未决的握手。 11、为什么我的服务器程序没有接收一个客户端证书? 在TLS协议定义中,如果服务器明确的要求,客户端仅仅发送证书。用SSL_CTX_set_verify()函数的SSL_VERIFY_PEER 来允许用客户端证书。 12、为什么因为一个未定义标记NID_uniqueIdentifier编译失败? 在OpenSSL 0.9.7,OID表被扩展和修正。在早期版本中,uniqueIdentifier被错误的用在X.509证书中。依照 RFC2256(LDAP)正确的名称是x500UniqueIdentifier,当你用OpenSSL 0.9.7编译时,改变你的代码去用新的名称。 13、我认为我检测到一个内存泄漏, 这是BUG吗? 在许多情况下,内存泄漏是程序启动时分配的OpenSSL内部表,这个表不会随着时间的流逝而增加大小,所以时无害的。 这些内部表能够在程序关闭时用不同的函数释放。当前包括: 线程局部清除函数: ERR_remove_state() 明白用法的程序全局清除函数(因此时线程安全的): ENGINE_cleanup() and CONF_modules_unload() "残忍的"(线程不安全的)程序全局清除函数: ERR_free_strings(), EVP_cleanup() and CRYPTO_cleanup_all_ex_data().