openssl3.2 - 检查rsa证书和私钥是否匹配(快速手搓一个工具)

发布时间:2024年01月23日

openssl3.2 - 检查rsa证书和私钥是否匹配(快速手搓一个工具)

概述

在学习openssl官方的/test/certs的脚本实现, 做到第30个脚本实验时, 发现根CA证书和key不匹配.
估计做实验时, 遇到脚本需要的文件, 就随便拷贝一个同名的文件过来, 导致证书和key不是一个脚本产生的, 所以不匹配

就想从前面的实验中, 找出匹配的证书和key来做实验, 肯定有啊.

这事应该openssl编程就能做到. 不过时间紧, 先不用openssl编程来做.
看有没有简单暴力的方法.

在网上找到如下2个openssl命令, 可以输出证书和key的模块信息.

// 打印X509证书的模块信息
openssl x509 -inform PEM -modulus -in ca-cert.pem -noout

// 打印rsa私钥的模块信息
openssl rsa -inform PEM -modulus -in ca-key.pem -noout

这2个命令输出的都是文本信息, 如果这2个文本信息相同, 则说明这2个证书和私钥是匹配的
按照这个原理, 手工输入命令, 然后人肉比对. 原始操作就是这样的, 就可以知道一对证书和key是否匹配.

可以重定向为文件(e.g. openssl x509 -inform PEM -modulus -in ca-cert.pem -noout > cert_info.txt)

然后用win10自带的FC.exe 就可以比较2个文件是否相同(e.g. fc file_a file_b), 如果fc返回0, 这2个文件就是相同的.

但是作为研发, 能用程序做的, 绝对不可能用人工操作来折磨自己, 那肯定不能够啊.

用了一个小时, 手搓了一个原始工具来干活.

效果

在这里插入图片描述

笔记

编程环境

vs2019 vc++ MFC + Dialog模板

界面控件的设置

对话框设置为可以接收文件.
2个编辑框(证书和key), 也设置为可以接收文件.

增加文件拖拽的类

从CEdit继承一个类CDropEdit(用类向导很方便), 加入拖拽消息处理(用类向导加入消息处理), 框架代码不用自己写.

#pragma once
#include <afxwin.h>
class CDropEdit :
    public CEdit
{
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnDropFiles(HDROP hDropInfo);
};


#include "pch.h"
#include "CDropEdit.h"
BEGIN_MESSAGE_MAP(CDropEdit, CEdit)
	ON_WM_DROPFILES()
END_MESSAGE_MAP()


void CDropEdit::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	// 拖拽实现很多, 可以参考msdn, 我就直接用下面这位同学分享的片段
	// https://blog.csdn.net/wrl112/article/details/120335725
	
    TCHAR szTmp[MAX_PATH * 2];
    CString strVal;
    unsigned int nRet = 0, nInx = 0;

    do {
        nRet = ::DragQueryFile(hDropInfo, nInx++, szTmp, sizeof(szTmp));
        if (nRet > 0) {
            strVal += szTmp;
        }
        else {
        }
        break;
    } while (1);
    ::DragFinish(hDropInfo);
    SetWindowText(strVal);

	CEdit::OnDropFiles(hDropInfo);
}

RSA证书和key是否匹配的实现

#include <string>

std::string my_W2A(std::wstring str)
{
	USES_CONVERSION;
	std::string str_rc = W2A(str.c_str());
	return str_rc;
}

void CCertKeyMatchDlg::OnBnClickedButtonMatch()
{
	// TODO: 在此添加控件通知处理程序代码
	CString csFileA;
	CString csFileB;
	CString csTmp;

	std::string strFileA;
	std::string strFileB;

	char szBuf[10 * 1024];

	int i_rc = 0;

	do {
		this->SetWindowTextW(_T(""));

		m_EditFileA.GetWindowText(csFileA);
		m_EditFileB.GetWindowText(csFileB);

		if ((csFileA.GetLength() <= 0) || (csFileB.GetLength() <= 0))
		{
			TRACE(_T("文件名必须都不为空"));
			break;
		}

		strFileA = my_W2A((LPCWSTR)csFileA);
		strFileB = my_W2A((LPCWSTR)csFileB);

		/*
		// 打印X509证书的模块信息
		openssl x509 -inform PEM -modulus -in ca-cert.pem -noout

		// 打印rsa私钥的模块信息
		openssl rsa -inform PEM -modulus -in ca-key.pem -noout
		*/

		sprintf(szBuf, "openssl x509 -inform PEM -modulus -in %s -noout > cert_info.txt", strFileA.c_str());
		i_rc = system(szBuf);
		_ASSERT(0 == i_rc);

		sprintf(szBuf, "openssl rsa -inform PEM -modulus -in %s -noout > key_info.txt", strFileB.c_str());
		i_rc = system(szBuf);
		_ASSERT(0 == i_rc);

		i_rc = system("fc cert_info.txt key_info.txt");
		csTmp.Format(_T("证书和私钥%s"), (0 == i_rc) ? _T("匹配") : _T("不匹配"));
		this->SetWindowTextW(csTmp);
	} while (false);


}

void CCertKeyMatchDlg::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialogEx::OnDropFiles(hDropInfo);
}

在程序中加入环境变量

在对话框初始化时, 加入了openssl的path, 除非必要, 不污染环境变量.

BOOL CCertKeyMatchDlg::OnInitDialog()
{
// ...
	// TODO: 在此添加额外的初始化代码

	char* psz_env_buf = new char[1024 * 1024];
	if (NULL != psz_env_buf)
	{
		char* psz_env = getenv("path");
		// ::SetEnvironmentStrings()
		sprintf(psz_env_buf, "path=%s;%s", "C:\\openssl_3d2\\bin", psz_env);

		int i_rc = _putenv(psz_env_buf);
		_ASSERT(0 == i_rc);

		delete[]psz_env_buf;
	}


	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

加入环境变量后, 调用程序时, 就不用写全路径, 就可以调用openssl.exe了.

备注

感觉自己还挺机智的:P

备注

因为cert和key的pem是成对的, 用everything看一下, 将cert.pem列出来, 然后进入对应目录找一下是否有对应的key.pem, 最好从生成时间早的目录找, 然后用这个工具比对.
很快就找出来了.
在这里插入图片描述

END

文章来源:https://blog.csdn.net/LostSpeed/article/details/135782511
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。