linux C++ 使用openssl rsa算法实现对计算机物理地址进行签名和认证

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wushuangge/article/details/81001585

首先需要使用openssl生成公钥和私钥,然后对字符串进行签名和认证.
license.h

#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <vector>

#define DEFAULT_BUFFER_SIZE 8192

class License {
public:
    License() {}

    ~License() {}

    ///获取mac
    void parse_mac_address(const char *file_name, const char *match_words, std::string &mac_address)
    {
        mac_address.c_str();
        std::ifstream ifs(file_name, std::ios::binary);
        if (!ifs.is_open()) {
            return;
        }

        char line[4096] = {0};
        while (!ifs.eof()) {
            ifs.getline(line, sizeof(line));
            if (!ifs.good()) {
                break;
            }

            const char *mac = strstr(line, match_words);
            if (NULL == mac) {
                continue;
            }
            mac += strlen(match_words);

            while ('\0' != mac[0]) {
                if (' ' != mac[0] && ':' != mac[0]) {
                    mac_address.push_back(mac[0]);
                }
                ++mac;
            }

            if (!mac_address.empty()) {
                break;
            }
        }

        ifs.close();
    }

    ///by_system获取mac
    bool get_mac_address_by_system(std::string &mac_address)
    {
        mac_address.clear();
        const char *lshw_result = ".lshw_result.txt";
        char command[512] = {0};
        snprintf(command, sizeof(command), "lshw -c network | grep serial | head -n 1 > %s", lshw_result);

        if (0 == system(command)) {
            parse_mac_address(lshw_result, "serial:", mac_address);
        }

        unlink(lshw_result);

        return (!mac_address.empty());
    }

    ///获取本机全部的mac地址
    bool get_mac_address(std::vector<std::string> &mac_address)
    {
        struct ifreq ifr;
        struct ifconf ifc;
        char buf[2048];
        int success = 0;

        int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
        if (sock == -1) {
            printf("socket error\n");
            return -1;
        }

        ifc.ifc_len = sizeof(buf);
        ifc.ifc_buf = buf;
        if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
            printf("ioctl error\n");
            return -1;
        }

        struct ifreq* it = ifc.ifc_req;
        const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
        char szMac[64];
        for (; it != end; ++it) {
            strcpy(ifr.ifr_name, it->ifr_name);
            if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0) {
                if (! (ifr.ifr_flags & IFF_LOOPBACK)) { // don't count loopback
                    if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
                        unsigned char * ptr ;
                        ptr = (unsigned char  *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0];
                        snprintf(szMac,64,"%02X:%02X:%02X:%02X:%02X:%02X",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5));
                        printf("%s : %s \n",ifr.ifr_name,szMac);
                        if(strncmp(ifr.ifr_name,"eth",3) == 0)
                        {
                            mac_address.push_back(szMac);
                            break;
                        }
                    }
                }
            }else{
                printf("get mac info error\n");
                return -1;
            }
        }
    }

    //base64转码
    char *enbase64(const char *input, size_t length, size_t size)
    {
        BIO *bmem = NULL;
        BIO *b64 = NULL;
        BUF_MEM *bptr = NULL;
        assert(NULL != input);
        b64 = BIO_new(BIO_f_base64());
        bmem = BIO_new(BIO_s_mem());
        if (NULL == b64 || NULL == bmem) {
            perror("BIO_new");
            return NULL;
        }
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

        b64 = BIO_push(b64, bmem);
        BIO_write(b64, input, length);
        BIO_flush(b64);
        BIO_get_mem_ptr(b64, &bptr);

        if ((unsigned int) (bptr->length + 1) > size) {
            BIO_free_all(b64);
            return NULL;
        }
        char *result = new char[bptr->length];
        memset(result, 0, bptr->length);
        memcpy(result, bptr->data, bptr->length);
        result[bptr->length] = 0;

        BIO_free_all(b64);

        return result;
    }

    //base64转码
    char *debase64(char *input, size_t length, size_t size)
    {
        BIO *b64 = NULL;
        BIO *bmem = NULL;
        assert(NULL != input);
        if (length > size)
            return NULL;
        char *result = new char[size];
        memset(result, 0, size);

        b64 = BIO_new(BIO_f_base64());
        bmem = BIO_new_mem_buf(input, length);
        BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
        if (NULL == b64 || NULL == bmem) {
            perror("BIO_new");
            return NULL;
        }
        bmem = BIO_push(b64, bmem);
        BIO_read(bmem, result, length);

        BIO_free_all(b64);

        return result;
    }

    ///签名
    char *rsa_sign(const char *text, size_t size, const char *sk_filename)
    {
        RSA *rsa;
        unsigned int len;
        char *signature = nullptr;

        assert(text != NULL && sk_filename != NULL);
        OpenSSL_add_all_algorithms();
        BIO *in = NULL;
        in = BIO_new(BIO_s_file());
        BIO_read_filename(in, sk_filename);
        if (in == NULL) {
            perror(sk_filename);
            return NULL;
        }

        //将IO中数据以PEM格式读入EVP_PKEY结构中
        rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, NULL);
        if (in != NULL)
            BIO_free(in);
        if (rsa == NULL) {
            perror("PEM_read_bio_RSAPrivateKey");
            return NULL;
        }

        unsigned char *sig = new unsigned char[RSA_size(rsa)];
        unsigned char sha1[20] = {'\0'};
        //result len of sha1:20 bytes
        SHA1((const unsigned char *) text, strlen(text), sha1);
        if (1 != RSA_sign(NID_sha1, sha1, 20, sig, &len, rsa)) {
            delete[] sig;
            sig = nullptr;
            RSA_free(rsa);
            printf("RSA_sign error.\n");
            return NULL;
        }
        signature = enbase64((char *) sig, 128, size);

        if (!signature) {
            delete[] sig;
            sig = nullptr;
            RSA_free(rsa);
            printf("enbase64 error.\n");
            return NULL;
        }
        delete[] sig;
        sig = nullptr;
        RSA_free(rsa);

        return signature;
    }

    ///验证
    bool rsa_verify(const char *text, char *signature, const char *pk_filename)
    {
        RSA *rsa;
        BIO *in = NULL;
        assert(NULL != text && NULL != signature);
        in = BIO_new(BIO_s_file());
        BIO_read_filename(in, pk_filename);
        if (NULL == in) {
            printf("BIO_read_filename error.\n");
            return false;
        }
        //将IO中数据以PEM格式读入EVP_PKEY结构中
        //rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
        rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);

        if (in != NULL) BIO_free(in);
        if (rsa == NULL) {
            printf("PEM_read_bio_RSA_PUBKEY error.\n");
            return false;
        }

        //unsigned char sig_temp[250];
        char *sig_debase = debase64(signature, strlen((char *) signature), 250);
        if (!sig_debase) {
            RSA_free(rsa);
            printf("debase64 error.\n");
            return false;
        }

        unsigned char sha1[20];
        SHA1((const unsigned char *) text, strlen(text), sha1);
        if (1 != RSA_verify(NID_sha1, sha1, 20, (unsigned char *) sig_debase, 128, rsa)) {
            delete[] sig_debase;
            sig_debase = nullptr;
            RSA_free(rsa);
            printf("RSA_verify error.\n");
            return false;
        }
        delete[] sig_debase;
        sig_debase = nullptr;
        RSA_free(rsa);

        return true;
    }

    //根据license-key.txt获取文件信息
    char* getlicense(const char* file_name)
    {
        FILE *pFile;
        size_t lSize;
        char *buffer;
        size_t result;
        pFile = fopen(file_name, "rb");
        if (pFile == NULL)
            fputs("File error", stderr);
        fseek(pFile, 0, SEEK_END);
        lSize = ftell(pFile);
        rewind(pFile);
        buffer = new char[lSize];
        if (buffer == NULL)
            fputs("Memory error", stderr);
        result = fread(buffer, 1, lSize, pFile);
        if (result != lSize)
            fputs("Reading error", stderr);
        return buffer;
    }
};

main.cpp

#include <iostream>
#include "license.h"

int  main()
{
    License license;
    //获取mac_address
    std::vector<std::string> vec_mac_address;
    license.get_mac_address(vec_mac_address);

    //给mac_address签名后生成一个字符串
    char *signature = license.rsa_sign(vec_mac_address[0].c_str(), DEFAULT_BUFFER_SIZE,"rsa_private_key.pem");
    printf ("signature: %s\n",signature);

    //把签名后的字符串存到license-key.txt
    FILE *fp;
    if((fp=fopen("license-key.txt","a"))==NULL)
    {
        printf("You can't open the license-key.txt!\n");
        exit(1);
    }
    fprintf(fp,"%s",signature);
    fclose(fp);

    //认证
    bool bRet =license.rsa_verify(vec_mac_address[0].c_str(),signature,"rsa_public_key.pem");
    if (bRet == true)
    {
        printf ("认证通过!\n");
    }
    else
    {
        printf ("认证失败!\n");
    }
    delete[] signature;
    signature = nullptr;

    return 0;
}

运行结果:
eth1 : 2C:FD:A1:5C:B0:B1
signature: h6dg747tF7Wxa+NNo24uo1vQKO0sYHbBgaXWTzrcG7tsXHbZ5AKAmLK9wopMohhjMFP4HSscYmKwHjaTBCqfWX3gP5RL5Ut2BV7bSbhmtDP/ow4aDBo9+hFSh5SGPBvmGN7bl0l8zER6ugCLASAyj1nQQYAsNySvfe9m9+G8go0=
认证通过!

猜你喜欢

转载自blog.csdn.net/wushuangge/article/details/81001585