百韵网 >>  正文

linux下使用openssl检测PE文件数字签名的证书是否有效 linux下使用openssl检测PE文件数字签名的证书是否...

来源:www.baiyundou.net   日期:较早时间
  第一个坑: 有效期
  windows在判断证书是否有效时不检测证书的有效期, 即使该证书超过有效期好几年了, 只要没有被吊销, 微软仍然认为它是有效的. 但在 openssl 提供的 X509_verify_cert 函数会验证证书的有效期, 因此需要注释掉验证有效期的那部分代码并重新编译 openssl...
  OK, 从 openssl 官网 上下载最新的版本, 好吧, 现在还是刚刚修复 Heartbleed 漏洞的 1.0.1g 版本...
  下载, 解压, 看下 INSTALL 文档, 先试试可以编译不:
  ./config
make

  运气不错, 不用安装什么依赖直接编译成功. 将代码根目录产生的 libcrypto.a 添加到项目中测试下, OK, 可以使用, 下面开始折腾了~
  在 crypto/x509/x509_vfy.c 的 153 行找到 X509_verify_cert 函数(在线查看), 局部变量 ok 缓存每一步验证是否通过, 它依次调用了:
  check_issued
check_chain_extensions
check_name_constraints
check_trust
check_revocation
internal_verify
check_policy

  其中 internal_verify (在线查看)验证了证书的有效期, 进入这个函数, 在 1654 行找到这个代码:
  ok = check_cert_time(ctx, xs);
if (!ok)
goto end;

  看看 check_cert_time 函数, 确认是检查 notBefore 和 notAfter, 因此将上面三行代码注释掉, 验证证书时就不会检测有效期了.
  然后就是重新编译 openssl, 将 libcrypto.a 集成到项目里了~
  第二个坑: unhandled critical extension
  搜索了下, 在 openssl 官网上找到这个:
  -ignore_critical
Normally if an unhandled critical extension is present which is not supported by OpenSSL the certificate is rejected (as required by RFC5280). If this option is set critical extensions are ignored.

  原来是当openssl遇到证书中有它不支持的 未处理的关键扩展(unhandled critical extension ?) 时, 它会拒绝加载该证书.
  再搜索下 -ignore_critical, 在 verify.c 中找到如下代码片段:
  else if (strcmp(*argv,"-ignore_critical") == 0)
vflags |= X509_V_FLAG_IGNORE_CRITICAL;

  然后再使用 X509_STORE_set_flags 函数设置标志位:
  X509_STORE *ctx;
...
X509_STORE_set_flags(ctx, vflags);

  即可.
  第三个坑: certificate signature failure
  这个坑填不上了, openssl 说:
  7 X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure
the signature of the certificate is invalid.

  在windows下导出证书文件, 直接用 openssl 验证, 在加载证书就会出错, PEM_read_bio_X509 返回为空....
  第四个坑: A certificate was explicitly revoked by its issuer.
  A certificate was explicitly revoked by its issuer. 是 Sysinternals 提供的工具sigcheck.exe 的检测结果, 把文件拎出来一看, 证书真的被撤销了...
  OK, 只好根据证书上的 CRL Distribution Point(CRL 分发点) 提供的 URL 下载 撤销证书列表 文件, 然后在调用 X509_verify_cert 验证证书链之前, 设置填充被撤销的证书列表:
  X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl); // 读取被撤销的证书列表

STACK_OF(X509_CRL) *sk_X509_CRL_new_null();
#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val)); // sk_X509_CRL_push(STACK_OF(X509_CRL) *crls, X509_CRL *crl);

void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk); // 设置被撤销的证书列表

  同时, 也要设置检查被撤销证书列表的标志位 X509_V_FLAG_CRL_CHECK, 然后再调用X509_verify_cert 验证证书链即可.
  填了第四个坑后又引起了第五个坑(如何获取撤销证书列表)和第六个坑(设置检测撤销证书列表的标识位后, 如果该证书没有撤销证书列表则直接报错)...
  第五个坑: 获取撤销证书列表文件
  证书上的 CRL Distribution Point(CRL 分发点) 属于扩展属性, 在 PKCS #7: Cryptographic Message Syntax V1.5 上没有相关介绍.
  在 StackOverflow 上找到这个问答 Openssl - How to check if a certificate is revoked or not, 其中第二个回答说 CRL 是在 RFC 5280 中定义的, 除了证书中附带被撤销的证书列表以外还有使用 OCSP 协议的, 即使证书撤销列表也分为使用 URL分发点和 LDAP DNs(???)提供的, 目前先考虑使用 URL 作为 CRL分发点 的情况吧.
  然而 openssl 没有提供直接获取 CRL 分发点 URL 的API, 那个回答说 Apache 的 mod_ssl 模块有本地 CRL 和 OCSP 检测的实现代码, 但没有说明哪里有检测使用 URL 作为 CRL分发点 的实现方法.
  然后又在 frank4dd.com上找到这个代码 certextensions.c, 他给出了一个如何使用 openssl 从 X.509v3 版本的证书文件中提取扩展内容的示例程序, 太感谢 Frank4DD 这位仁兄了~~~
  到这里后, 可以直接使用他的示例程序, 根据关键字 Full Name 和 URI 定位 CRL 分发点 的 URL, 也可以看看 openssl 是如何提取这个 URL 的, 然后自己实现一个接口.
  如果自作孽使用第二种方法的话, 就编译个 debug 版的 openssl 库, 然后调试跟进X509V3_EXT_print 函数, 一步一步的向下走, 直到走到 GENERAL_NAME_print 函数, 这里就是终点了...然后就知道了 CRL 分发点 的 URL 的编号为 6, 也就是 GEN_URI, 直接取结果吧.
  第六个坑: CRL有效期
  在windows环境下每次查看PE文件的数字签名时, windows 都会从 CRL分发点 下载吊销证书列表做验证, 一般来说, 每个 CRL的有效期是非常短的, 大概只有 5~20 天的有效期吧, 然而我们不可能像 windows 一样每次查看数字签名时就从 CRL分发点 下载最新的吊销列表.
  另外, windows 遇到过期的 CRL 时不会产生证书链无效的结果, 但 openssl 在遇到过期的 CRL 时就会导致证书链验证失败, 因此在加载和验证 CRL 时, 要忽略 CRL 的有效期.
  分析 openssl 源代码, X509_verify_cert 调用 check_revocation , 之后调用 check_cert , 然后再调用 check_crl , 在这个函数里有检测 CRL 有效期的代码:
  if (!(ctx->current_crl_score & CRL_SCORE_TIME))
{
ok = check_crl_time(ctx, crl, 1);
if (!ok)
goto err;
}

  将其注释掉即可忽略检测 CRL 有效期.
  第七个坑: CRL 列表为空导致 openssl 认为没有加载 CRL
  
  9 初始化顺序
  10 证书名: key_id


linux下使用openssl检测PE文件数字签名的证书是否有效~

windows在判断证书是否有效时不检测证书的有效期, 即使该证书超过有效期好几年了, 只要没有被吊销, 微软仍然认为它是有效的. 但在 openssl 提供的 X509_verify_cert 函数会验证证书的有效期, 因此需要注释掉验证有效期的那部分代码并重新编译 openssl...
OK, 从 openssl 官网 上下载最新的版本, 好吧, 现在还是刚刚修复 Heartbleed 漏洞的 1.0.1g 版本...
下载, 解压, 看下 INSTALL 文档, 先试试可以编译不:
./config
make


运气不错, 不用安装什么依赖直接编译成功. 将代码根目录产生的 libcrypto.a 添加到项目中测试下, OK, 可以使用, 下面开始折腾了~
在 crypto/x509/x509_vfy.c 的 153 行找到 X509_verify_cert 函数(在线查看), 局部变量 ok 缓存每一步验证是否通过, 它依次调用了:
check_issued
check_chain_extensions
check_name_constraints
check_trust
check_revocation
internal_verify
check_policy


其中 internal_verify (在线查看)验证了证书的有效期, 进入这个函数, 在 1654 行找到这个代码:
ok = check_cert_time(ctx, xs);
if (!ok)
goto end;


看看 check_cert_time 函数, 确认是检查 notBefore 和 notAfter, 因此将上面三行代码注释掉, 验证证书时就不会检测有效期了.
然后就是重新编译 openssl, 将 libcrypto.a 集成到项目里了~

真接上源码
//-------------------------------------------------------------------// Copyright (c) Microsoft Corporation. All rights reserved.// Example of verifying the embedded signature of a PE file by using // the WinVerifyTrust function.#define _UNICODE 1#define UNICODE 1#include #include #include #include #include #include #include // Link with the Wintrust.lib file.#pragma comment (lib, "wintrust")BOOL VerifyEmbeddedSignature(LPCWSTR pwszSourceFile){ LONG lStatus; DWORD dwLastError; // Initialize the WINTRUST_FILE_INFO structure. WINTRUST_FILE_INFO FileData; memset(&FileData, 0, sizeof(FileData)); FileData.cbStruct = sizeof(WINTRUST_FILE_INFO); FileData.pcwszFilePath = pwszSourceFile; FileData.hFile = NULL; FileData.pgKnownSubject = NULL; /* WVTPolicyGUID specifies the policy to apply on the file WINTRUST_ACTION_GENERIC_VERIFY_V2 policy checks: 1) The certificate used to sign the file chains up to a root certificate located in the trusted root certificate store. This implies that the identity of the publisher has been verified by a certification authority. 2) In cases where user interface is displayed (which this example does not do), WinVerifyTrust will check for whether the end entity certificate is stored in the trusted publisher store, implying that the user trusts content from this publisher. 3) The end entity certificate has sufficient permission to sign code, as indicated by the presence of a code signing EKU or no EKU. */ GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_DATA WinTrustData; // Initialize the WinVerifyTrust input data structure. // Default all fields to 0. memset(&WinTrustData, 0, sizeof(WinTrustData)); WinTrustData.cbStruct = sizeof(WinTrustData); // Use default code signing EKU. WinTrustData.pPolicyCallbackData = NULL; // No data to pass to SIP. WinTrustData.pSIPClientData = NULL; // Disable WVT UI. WinTrustData.dwUIChoice = WTD_UI_NONE; // No revocation checking. WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE; // Verify an embedded signature on a file. WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; // Default verification. WinTrustData.dwStateAction = 0; // Not applicable for default verification of embedded signature. WinTrustData.hWVTStateData = NULL; // Not used. WinTrustData.pwszURLReference = NULL; // Default. WinTrustData.dwProvFlags = WTD_SAFER_FLAG; // This is not applicable if there is no UI because it changes // the UI to accommodate running applications instead of // installing applications. WinTrustData.dwUIContext = 0; // Set pFile. WinTrustData.pFile = &FileData; // WinVerifyTrust verifies signatures as specified by the GUID // and Wintrust_Data. lStatus = WinVerifyTrust( NULL, &WVTPolicyGUID, &WinTrustData); switch (lStatus) { case ERROR_SUCCESS: /* Signed file: - Hash that represents the subject is trusted. - Trusted publisher without any verification errors. - UI was disabled in dwUIChoice. No publisher or time stamp chain errors. - UI was enabled in dwUIChoice and the user clicked "Yes" when asked to install and run the signed subject. */ wprintf_s(L"The file \"%s\" is signed and the signature " L"was verified.
", pwszSourceFile); break; case TRUST_E_NOSIGNATURE: // The file was not signed or had a signature // that was not valid. // Get the reason for no signature. dwLastError = GetLastError(); if (TRUST_E_NOSIGNATURE == dwLastError || TRUST_E_SUBJECT_FORM_UNKNOWN == dwLastError || TRUST_E_PROVIDER_UNKNOWN == dwLastError) { // The file was not signed. wprintf_s(L"The file \"%s\" is not signed.
", pwszSourceFile); } else { // The signature was not valid or there was an error // opening the file. wprintf_s(L"An unknown error occurred trying to " L"verify the signature of the \"%s\" file.
", pwszSourceFile); } break; case TRUST_E_EXPLICIT_DISTRUST: // The hash that represents the subject or the publisher // is not allowed by the admin or user. wprintf_s(L"The signature is present, but specifically " L"disallowed.
"); break; case TRUST_E_SUBJECT_NOT_TRUSTED: // The user clicked "No" when asked to install and run. wprintf_s(L"The signature is present, but not " L"trusted.
"); break; case CRYPT_E_SECURITY_SETTINGS: /* The hash that represents the subject or the publisher was not explicitly trusted by the admin and the admin policy has disabled user trust. No signature, publisher or time stamp errors. */ wprintf_s(L"CRYPT_E_SECURITY_SETTINGS - The hash " L"representing the subject or the publisher wasn't " L"explicitly trusted by the admin and admin policy " L"has disabled user trust. No signature, publisher " L"or timestamp errors.
"); break; default: // The UI was disabled in dwUIChoice or the admin policy // has disabled user trust. lStatus contains the // publisher or time stamp chain error. wprintf_s(L"Error is: 0x%x.
", lStatus); break; } return true;}int _tmain(int argc, _TCHAR* argv[]){ if(argc > 1) { VerifyEmbeddedSignature(argv[1]); } return 0;}

相关要点总结:

17631834628:openssl重协商功能怎么关闭linux命令
凤虽答:023/8/22 16:18:50 在Linux系统中,要禁用OpenSSL的重协商功能,您可以通过修改OpenSSL的配置文件来实现。以下是一般情况下的步骤:打开 OpenSSL 的配置文件:通常情况下,OpenSSL 的配置文件位于 /etc/ssl/openssl.cnf 或 /etc/pki/tls/openssl.cnf。在配置文件中找到或添加以下行:复制代码[system_...

17631834628:linux安装openssl问题
凤虽答:出现这个 不算错误, 已经配置了.上面是运行的 它的 测试用例..我觉得 应该是 ./configure 不是 ./config 吧.== 第二个图 绝对是个错误,没有找到 gcc(编译器),估计是你没有安装, 或者安装了, 没有在PATH里(这个可能性很小)你用什么发行版? 你可以用下面指令安装 gcc ubuntu, debian:sudo ...

17631834628:Linux下编译安装openssl1.0.1d时遇到问题怎么办?
凤虽答:1、读一下INSTALL文档\x0d\x0a2、make clean清理一下\x0d\x0a3、重新来一次\x0d\x0a./config --prefix=/usr/local --openssldir=/usr/local/openssl\x0d\x0amake;make test;make install

17631834628:如何在linux下安装ssl证书?
凤虽答:Linux+Apache下安装SSL证书的步骤如下

17631834628:Linux下生成能用的SSL证书的步骤
凤虽答:我们首先要设置 openssl 的全局配置文件 在debian下他的配置文件在 /usr/lib/ssl/openssl.cnf 需要修改的内容:具体怎么改可以自己决定 在CA目录下创建两个初始文件:为了安全起见,修改cakey.pem私钥文件权限为600或400,也可以使用子shell生成( umask 077; openssl genrsa -out private/cakey.pem 2048...

17631834628:Linux-SSL和SSH和OpenSSH,OpenSSL有什么区别
凤虽答:从编译依赖上看:openssh依赖于openssl,没有openssl的话openssh就编译不过去,也运行不了。 HTTPS可以使用TLS或者SSL协议,而openssl是TLS、SSL协议的开源实现,提供开发库和命令行程序。openssl很优秀,所以很多涉及到数据加密、传输加密的地方都会使用openssl的库来做。可 以理解成所有的HTTPS都使用...

17631834628:OpenSSL 入门:密码学基础知识
凤虽答:本文是使用 OpenSSL 的密码学基础知识的两篇文章中的第一篇,OpenSSL 是在 Linux 和其他系统上流行的生产级库和工具包。(要安装 OpenSSL 的最新版本,请参阅 这里 。)OpenSSL 实用程序可在命令行使用,程序也可以调用 OpenSSL 库中的函数。本文的示例程序使用的是 C 语言,即 OpenSSL 库的源语言。 本系列的两篇文...

17631834628:HTTPS的前世今生和原理详解
凤虽答:证书有统一的标准,其合法性(证书是否过期、数字签名是否有效、颁发的机构是否可信)通过一定的程序按标准来进行验证,如浏览器会保证HTTPS证书是否是合法的,Linux下openSSL库提供了证书验证功能。 核对证书后若证书可信,就可以使用证书中的公钥对数据进行加密与证书的拥有者进行通信。 HTTPS的证书在扩展字段中包含了域名相关...

17631834628:Linux-SSL和SSH和OpenSSH,OpenSSL有什么区别
凤虽答:2、SSH(Secure Shell 远程登陆用),安全可以和telnet比较一下,比如telnet传输用户密码是明文的,而SSH是加密的。明文的可以监听到。TCP端口22 3、OpenSSH是个SSH的软件,OpenSSH is the premier connectivity tool for remote login with the SSH protocol. linux/unix都用openssh软件提供SSH服务。简单...

17631834628:如果在Linux下使用SSH证书
凤虽答:1.重新安装ssl,过程如下:第一步:openssl genrsa -des3 -out server1.key 1024Generating RSA private key, 1024 bit long modulus...+++++...+++++e is 65537 (0x10001)Enter pass phrase for server1.key:此处设置个密码Verifying - Enter pass phrase for server1.key:重新输入设置个密...

(编辑:本站网友)
相关推荐
关于我们 | 客户服务 | 服务条款 | 联系我们 | 免责声明 | 网站地图
@ 百韵网