DSA密钥对的生成请参考我这篇文章openssl在windows上生成RSA密钥、DSA密钥
//DSA用私钥对文件内容签名
#pragma warning(disable:4996)
#include
#include
#include
#include
using namespace std;
/*
函数名:DSA_sign
函数功能:用openssl的DSA接口读取DSA私钥,对指定文件内容进行签名,将签名保存到另一个文件中
输入参数:None
返回参数:bool 若签名成功,返回true,否则返回false
作者:Leo Ma
时间:2019.09.15
*/
bool DSA_sign(string input_file,string sign_file)
{
DSA* dsa_private_key = DSA_new();//定义DSA私钥
unsigned char* input_string = new unsigned char;//定义要签名的字符串
unsigned char* sign_string;//定义签名后的字符串
unsigned int sig_len;//签名长度
//从文件中读取DSA私钥
BIO *priio;//Binary IO
priio = BIO_new_file("dsa_private_key.pem", "rb");
dsa_private_key = PEM_read_bio_DSAPrivateKey(priio, &dsa_private_key, NULL, NULL);
//从文件中读取要签名的内容,放在input_string中
ifstream fin(input_file);
if (!fin.is_open())
{
cout << "WARNING! NOT FOUND CHECK FILE,PLEASE CONTACT TO THE ADMISTRATOR!!!" << endl;
return 0;
}
fin >> input_string;
fin.close();
//为签名后的字符串sign_string分配内存,如果不能正常分配内存,DSA_sign()将返回false
sign_string = (unsigned char*)calloc(DSA_size(dsa_private_key), sizeof(unsigned char));
if (sign_string == NULL)
{
fprintf(stderr, "Unable to allocate memory for sign_string\n");
return false;
//exit(-1);
}
//对input_string进行签名
//DSA_sign输入参数:签名类型,要签名的字符串地址,要签名的字符串长度,签名后的字符串存放地址,签名后的字符串长度,私钥
//如果签名失败,DSA_sign()将返回0,DSA_sign()将返回false
if (DSA_sign(0, input_string, strlen((char*)input_string),
sign_string, &sig_len, dsa_private_key) == 0)
{
fprintf(stderr, "Sign Error.\n");
return false;
//exit(-1);
}
//将签名后的字符串内容保存到一个文件中
ofstream fout;
fout.open(sign_file);
fout << sign_string;
fout.close();
return true;
}
int main(int argc, char** argv)
{
DSA_sign("check_file.txt", "checked_file.txt");
system("pause");
}
#pragma warning(disable:4996)
#include
#include
#include
#include
#include
using namespace std;
/*
函数名:DSA_verify_general
函数功能:用openssl的DSA接口验证解签后的信息是否与给定信息相同
输入参数: string sign_file 签名文件
string verify_string 给定的验证信息
返回参数:bool 若验证通过,返回true,否则返回false
作者:Leo Ma
时间:2019.09.15
*/
bool DSA_verify_general(string sign_file, string verify_string)
{
//将DSA公钥写死在文件中
//把DSA公钥文件内容复制到下面的字符串里,将多余的空格(这是VS编辑器的问题)删掉,换行符遵循UNIX(LF)格式,即使用\n换行
string dsa_public_key_string = "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAKenvEftAsim1cta2VzV+SCSiwJZFq6v\n+UvbdOTkM+mB9vq4NcV1mOEgPyXczgb+dU/Mn7Y0Zi5CkvCe18YyjaillKfGjVCt\n9ftffA/ML3axyfxsiPAuX0I1GRWJk6qbFaXImUAKUAGUiK1yKtJPnXIbnIQBYxji\nAXUcV6Pa6KwfAhUAhHBmLP8lIBIso865Bz7z5XQMKmkCgYBZiMp+oVyEuzZ8eS1d\nBWvbyKk/gnvGMxv10o/X1dWiD7JlT9iUl6J1kh8BnEIB6D4+zXStgq/g/t8+j/fK\nbwmin/zTC5LrzPtvzS2nsCEM4jL5UJzil24k3F8AQX5PUCt+TOwA0DudLz59K+An\nME+CxAPrCkcjg2tmco1RwO1QhQOBhAACgYA3ix4u+0IrSKDI605qCUgmBBbD3YlK\niACidMGZpzZnTaY3GzFt5m/Yn8o2mRfU2/Ouhssuum7uKXep4N9OhidM76ErPbpV\nIHP7n6fWx09MdLz5HkOmomVI8s9gQEog89Y9sw5KMymxln44QGyJPRqnRIKK+h58\ncX/Uar7hPftz7A==\n-----END PUBLIC KEY-----\n";
ofstream public_key_file;
public_key_file.open("dsa_public_key.pem");
public_key_file << dsa_public_key_string;
public_key_file.close();
//从刚写好的文件中读取DSA公钥
DSA* dsa_public_key = DSA_new();
BIO *pubio;//Binary IO
pubio = BIO_new_file("dsa_public_key.pem", "rb");
dsa_public_key = PEM_read_bio_DSA_PUBKEY(pubio, &dsa_public_key, NULL, NULL);
/*
//另一种读取DSA公钥的方法
DSA* dsa_public_key = DSA_new();
FILE *pubio;
pubio = fopen("dsa_public_key.pem", "rb");
dsa_public_key = PEM_read_DSA_PUBKEY(pubio, &dsa_public_key, NULL, NULL);
*/
//从文件中读取DSA签名
string sign_string;
ifstream fin(sign_file);
if (!fin.is_open())
{
cout << "WARNING! NOT FOUND CHECKED FILE,PLEASE CONTACT TO THE ADMISTRATOR!!!" << endl;
return 0;
}
fin >> sign_string;
fin.close();
//用DSA公钥解签并验证是否跟验证信息一致
int is_valid_signature = DSA_verify(0, (const unsigned char*)verify_string.data(), verify_string.length(),
(const unsigned char*)sign_string.data(), sign_string.length(), dsa_public_key);
//返回一个bool型变量
if (is_valid_signature == 1)return true;
else return false;
}
int main()
{
if (DSA_verify_general("checked_file.txt", "BFEBFBFF000906E9E0D55EC381F0"))
{
cout << "VERIFY SUCCESSFULLY!!!" << endl;
}
else
{
cout << "VERIFY FAIL!!!" << endl;
}
system("pause");
return 0;
}
关于如何获取运行机器的机器码请参考我这篇文章C++在windows下获得运行主机的硬件信息:CPU序列号、MAC地址、硬盘序列号、主板序列号
#pragma warning(disable:4996)
#include
#include
#include
#include "get hardware information/get_hardware_information.h"
#include
#include
using namespace std;
/*
函数名:my_get_hardware_information
函数功能:获得本机硬件信息:CPU序列号,Mac地址,主板序列号,硬盘序列号
输入参数:None
返回参数:string类型,CPU序列号+Mac地址
作者:Leo Ma
时间:2019.09.15
*/
string my_get_hardware_information()
{
char lpszCpu[128] = "";
char lpszMac[128] = "";
char lpszBaseBoard[128] = "";
char lpszHDSerial[128] = "";
GetCpuSerialByCmd(lpszCpu, 128);
GetMacByCmd(lpszMac, 128);
GetBaseBoardByCmd(lpszBaseBoard, 128);
GetHDSerialByCmd(lpszHDSerial);
//cout << "CPU ID is " << lpszCpu << endl;
//cout << "MAC ID is " << lpszMac << endl;
//cout << "Base Board ID is " << lpszBaseBoard << endl;
//cout << "HD Serial is " << lpszHDSerial << endl;
string string_return;
string_return.assign(lpszCpu);
string_return.append(lpszMac);
//string_return.append("\0");
//string_return.append(lpszBaseBoard);
//string_return.append(lpszHDSerial);
//cout << string_return << endl;
return string_return;
}
/*
函数名:DSA_verify_machine
函数功能:用openssl的DSA接口验证当前机器码是否与解签的机器码一致
输入参数:None
返回参数:bool 若验证通过,返回true,否则返回false
作者:Leo Ma
时间:2019.09.15
*/
bool DSA_verify_machine()
{
//读取本机机器码
string hardware_info;
hardware_info = my_get_hardware_information();//只获取CPU ID和Mac地址
//hardware_info = get_hardware_information("check_file.txt");//获取CPU ID、Mac地址、主板序列号、硬盘序列号,并且生成文件
//将DSA公钥写死在文件中
//把DSA公钥文件内容复制到下面的字符串里,将多余的空格(这是VS编辑器的问题)删掉,换行符遵循UNIX(LF)格式,即使用\n换行
string dsa_public_key_string = "-----BEGIN PUBLIC KEY-----\nMIIBtjCCASsGByqGSM44BAEwggEeAoGBAKenvEftAsim1cta2VzV+SCSiwJZFq6v\n+UvbdOTkM+mB9vq4NcV1mOEgPyXczgb+dU/Mn7Y0Zi5CkvCe18YyjaillKfGjVCt\n9ftffA/ML3axyfxsiPAuX0I1GRWJk6qbFaXImUAKUAGUiK1yKtJPnXIbnIQBYxji\nAXUcV6Pa6KwfAhUAhHBmLP8lIBIso865Bz7z5XQMKmkCgYBZiMp+oVyEuzZ8eS1d\nBWvbyKk/gnvGMxv10o/X1dWiD7JlT9iUl6J1kh8BnEIB6D4+zXStgq/g/t8+j/fK\nbwmin/zTC5LrzPtvzS2nsCEM4jL5UJzil24k3F8AQX5PUCt+TOwA0DudLz59K+An\nME+CxAPrCkcjg2tmco1RwO1QhQOBhAACgYA3ix4u+0IrSKDI605qCUgmBBbD3YlK\niACidMGZpzZnTaY3GzFt5m/Yn8o2mRfU2/Ouhssuum7uKXep4N9OhidM76ErPbpV\nIHP7n6fWx09MdLz5HkOmomVI8s9gQEog89Y9sw5KMymxln44QGyJPRqnRIKK+h58\ncX/Uar7hPftz7A==\n-----END PUBLIC KEY-----\n";
ofstream public_key_file;
public_key_file.open("dsa_public_key.pem");
public_key_file << dsa_public_key_string;
public_key_file.close();
//从刚写好的文件中读取DSA公钥
DSA* dsa_public_key = DSA_new();
BIO *pubio;//Binary IO
pubio = BIO_new_file("dsa_public_key.pem", "rb");
dsa_public_key = PEM_read_bio_DSA_PUBKEY(pubio, &dsa_public_key, NULL, NULL);
/*
//另一种读取DSA公钥的方法
DSA* dsa_public_key = DSA_new();
FILE *pubio;
pubio = fopen("dsa_public_key.pem", "rb");
dsa_public_key = PEM_read_DSA_PUBKEY(pubio, &dsa_public_key, NULL, NULL);
*/
//从文件中读取DSA签名
string sign_string;
ifstream fin("checked_file.txt");
if (!fin.is_open())
{
cout << "WARNING! NOT FOUND CHECKED FILE,PLEASE CONTACT TO THE ADMISTRATOR!!!" << endl;
return 0;
}
fin >> sign_string;
fin.close();
//用DSA公钥验证签名和读取机器码是否一致
int is_valid_signature = DSA_verify(0, (const unsigned char*)hardware_info.data(), hardware_info.length(),
(const unsigned char*)sign_string.data(), sign_string.length(), dsa_public_key);
//返回一个bool型变量
if (is_valid_signature == 1)return true;
else return false;
}
int main()
{
if (DSA_verify_machine())
{
cout << "验证通过,假装执行代码" << endl;
}
else
{
cout << "CHECKED FAIL!PLEASE CONTACT THE ADMINASTOR!!!" << endl;
}
system("pause");
return 0;
}