android开发使用openssl3.3.2加解密国密sm2代码实现

#include "openssl/rsa.h"
#include "openssl/pem.h"
#include "openssl/err.h"
#include "openssl/evp.h"
#include "openssl/ec.h"
#include <string>
#include <unistd.h>
#include "openssl_sm2.hpp"
#include "log/android_log.h"

std::string GetErrorStr() {
    unsigned long er = 0;
    char erbuf[512] = {0};
    size_t erlen = 512;
    er = ERR_get_error();
    ERR_error_string_n(er, erbuf, erlen);
    return std::string(erbuf, erlen);
}

//加密
int my_sm2encrpt(std::string keystr, unsigned char *sourStr, int cStrlen, unsigned char *enStr) {
    BIO *bp = NULL;
    EVP_PKEY *pkey = NULL;
    EVP_PKEY_CTX *ectx = NULL;
    size_t cEnStrlen;
    char *cEnStr = NULL;
    char *chPublicKey = const_cast<char *>(keystr.c_str());
    int ret = -1;
    if ((bp = BIO_new_mem_buf(chPublicKey, -1)) == NULL) {
        ALOGE("BIO_new_mem_buf failed!\n");
        return 0;
    }
    pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL);
    BIO_free_all(bp);
//     要去掉,不然执行EVP_PKEY_encrypt_init会报错返回-2
//    if ((EVP_PKEY_set_type(pkey, EVP_PKEY_SM2)) != 1) {
//        goto clean_up;
//    }

    if (!(ectx = EVP_PKEY_CTX_new(pkey, NULL))) {
        goto clean_up;
    }

    ret = EVP_PKEY_encrypt_init(ectx);
    ALOGI("EVP_PKEY_encrypt_init ret=%d\n", ret);
    if (ret != 1) {
        ALOGI("EVP_PKEY_encrypt_init error=%s\n", GetErrorStr().c_str());
        goto clean_up;
    }

    if ((EVP_PKEY_encrypt(ectx, NULL, &cEnStrlen, reinterpret_cast<unsigned char *>(sourStr),
                          (size_t) (cStrlen))) != 1) {
        goto clean_up;
    }
    if (!(cEnStr = (char *) malloc(cEnStrlen))) {
        goto clean_up;
    }

    if ((EVP_PKEY_encrypt(ectx, reinterpret_cast<unsigned char *>(cEnStr), &cEnStrlen,
                          reinterpret_cast<unsigned char *>(sourStr), cStrlen)) != 1) {
        goto clean_up;
    }
    ALOGI("enStrLen2: %ld\n", cEnStrlen);
    memcpy(enStr, cEnStr, cEnStrlen);
    return (int) (cEnStrlen);

    clean_up:

    if (pkey) {
        EVP_PKEY_free(pkey);
    }
    if (ectx) {
        EVP_PKEY_CTX_free(ectx);
    }
    if (cEnStr) {
        free(cEnStr);
    }
    return 0;
}

//解密
int dencryptStr(std::string keystr, unsigned char *cEnStr, int cEnstrlen, unsigned char *deStr) {
    BIO *priBp = NULL;
    EVP_PKEY *mSm2PriKey;
    EVP_PKEY_CTX *ectx = NULL;
    size_t cDeStrlen = 0;
    char *cDeStr = NULL;
    //create pri key
    char *chPrilicKey = const_cast<char *>(keystr.c_str());
    if ((priBp = BIO_new_mem_buf(chPrilicKey, -1)) == NULL) {
        ALOGE("BIO_new_mem_buf failed!\n");
    }
    mSm2PriKey = PEM_read_bio_PrivateKey(priBp, NULL, NULL, NULL);
    BIO_free_all(priBp);
    if (NULL == mSm2PriKey) {
        ERR_load_crypto_strings();
        char errBuf[512];
        ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
        ALOGE("load sm2 private key failed[%s]\n", errBuf);
    }
    //解密
//     要去掉,不然执行EVP_PKEY_encrypt_init会报错返回-2
//    if ((EVP_PKEY_set_type(mSm2PriKey, EVP_PKEY_SM2)) != 1) {
//        ALOGE("EVP_PKEY_set_alias_type failed!\n");
//    }

    if (!(ectx = EVP_PKEY_CTX_new(mSm2PriKey, NULL))) {
        ALOGE("EVP_PKEY_CTX_new failed!\n");
    }
    if ((EVP_PKEY_decrypt_init(ectx)) != 1) {
        ALOGE("EVP_PKEY_decrypt_init failed!\n");
    }
    if ((EVP_PKEY_decrypt(ectx, NULL, &cDeStrlen, reinterpret_cast<unsigned char *>(cEnStr),
                          cEnstrlen)) != 1) {
        ALOGE("EVP_PKEY_decrypt failed!\n");
        ERR_load_crypto_strings();
        char errBuf[512];
        ERR_error_string_n(ERR_get_error(), errBuf, sizeof(errBuf));
        ALOGE("EVP_PKEY_decrypt[%s]\n", errBuf);
    }
    if (!(cDeStr = (char *) malloc(cDeStrlen))) {
        ALOGE(" (unsigned char *)malloc(cDeStrlen)) failed!\n");
    }
    if ((EVP_PKEY_decrypt(ectx, reinterpret_cast<unsigned char *>(cDeStr), &cDeStrlen,
                          reinterpret_cast<unsigned char *>(cEnStr), cEnstrlen)) != 1) {
        ALOGE(" EVP_PKEY_decrypt failed!\n");
    }
    ALOGI("cDeStrlen:%d\n", cDeStrlen);
    memcpy(deStr, cDeStr, cDeStrlen);
    EVP_PKEY_CTX_free(ectx);
    free(cDeStr);
    return cDeStrlen;
}
//测试代码
int test_my_sm2() {
    ALOGI("test_my_sm2 start");
    //1.首先PC电脑上安装openssl客户端,然后执行下面命令生成公钥-私钥
    //2.生成私钥:openssl ecparam -outform pem -out sm2PriKey.pem -name sm2 -genkey
    //3.生成公钥:openssl ec -in sm2PriKey.pem -pubout -out sm2PubKey.pem
    //4.文本记事本分别打开私钥文件sm2PriKey.pem和公钥文件sm2PriKey.pem,分别复制里面的值给sm2PriKeyStr和sm2PubKeyStr变量
    std::string sm2PriKeyStr = "-----BEGIN SM2 PARAMETERS-----\n"
                               "BggqgRzPVQGCLQ==\n"
                               "-----END SM2 PARAMETERS-----\n"
                               "-----BEGIN PRIVATE KEY-----\n"
                               "MIGIAgEAMBQGCCqBHM9VAYItBggqgRzPVQGCLQRtMGsCAQEEIAeYlDHP36Z3ZQTZ\n"
                               "PwIQSkSU7Ut9uteRHGiGlpxiPGzroUQDQgAEOw+Byzd+Vu31TVCuOQFjewcL4jt4\n"
                               "ShOxGNS0sQaF6g1sBvRwnUbzfaGXdhmkllxCvygGxeX1TF/zI/MQNzgHjg==\n"
                               "-----END PRIVATE KEY-----\n";
    std::string sm2PubKeyStr = "-----BEGIN PUBLIC KEY-----\n"
                               "MFowFAYIKoEcz1UBgi0GCCqBHM9VAYItA0IABDsPgcs3flbt9U1QrjkBY3sHC+I7\n"
                               "eEoTsRjUtLEGheoNbAb0cJ1G832hl3YZpJZcQr8oBsXl9Uxf8yPzEDc4B44=\n"
                               "-----END PUBLIC KEY-----\n";

    unsigned char sm2_en[512], sm2_de[512];
    int sm2enStrLen, sm2deStrLen;


    unsigned char source[20] = {0x41, 0x12, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11,
                                0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20};

    sm2enStrLen = my_sm2encrpt(sm2PubKeyStr, source, 20, sm2_en);
    ALOGI("sm2enStrLen :%d \n", sm2enStrLen);
    std::string sm2_en_str;
    char buf[100];
    for (int i = 0; i < sm2enStrLen; i++) {
        snprintf(buf, 100, "0x%02x ", sm2_en[i]);
        sm2_en_str.append(buf);
    }
    ALOGI("sm2_en_str :%s\n", sm2_en_str.c_str());

    sm2deStrLen = dencryptStr(sm2PriKeyStr, sm2_en, sm2enStrLen, sm2_de);
    ALOGI("sm2deStrLen :%d \n", sm2deStrLen);
    std::string sm2_de_str;
    for (int i = 0; i < sm2deStrLen; i++) {
        snprintf(buf, 100, "0x%x ", sm2_de[i]);
        sm2_de_str.append(buf);
    }
    ALOGI("sm2_de_str :%s\n", sm2_de_str.c_str());

    ALOGI("test_my_sm2 end");
    return 0;
}
posted @ 2024-11-26 18:52  yongfengnice  阅读(39)  评论(0编辑  收藏  举报