首页 > 其他分享 >【OpenSSL】哈希、非对称加密和对称加密函数使用

【OpenSSL】哈希、非对称加密和对称加密函数使用

时间:2023-12-07 21:11:20浏览次数:29  
标签:加密 rsa int OpenSSL RSA char 哈希 unsigned

1.哈希

1.1 md5的使用

  • 头文件
#include <openssl/md5.h>
#include <openssl/sha.h>
  • MD5 散列值的长度
# define MD5_DIGEST_LENGTH 16    // 根据这个分配一块空内存保存散列值
  • 初始化MD5 -> 给MD5传入运算的数据(可以多次传入) -> 计算MD5
# define MD5_DIGEST_LENGTH 16    // md5哈希值长度
// 初始化函数, 初始化参数 c
int MD5_Init(MD5_CTX *c);
/*    参数c: 传出参数    */

// 添加md5运算的数据, 没有计算数据, 所以可以多次添加数据
int MD5_Update(MD5_CTX *c, const void *data, size_t len);
/*  参数:
        c: MD5_Init() 初始化得到的
        data: 传入参数, 字符串
        len: data数据的长度   */

// 对添加的数据进行md5计算        
int MD5_Final(unsigned char *md, MD5_CTX *c);
/*  参数:
        md: 传出参数, 存储得到的哈希值
        c: MD5_Init() 初始化得到的        */
  • 通过传参直接生成 md5 哈希值
// 通过传递的参数, 直接生成一个md5哈希值,只能添加一次数据
unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md);
/*  参数:
        - d: 传入, 要进行md5运算的字符串
        - n: 字符串的的长度
        - md: 传出, 存储md5的哈希值
    返回值: 这个地址的函数第三个参数md地址        */
  • 编译时记得加 lcrypto -lssl

2. 非对称加密

2.1 非对称加密简介

  • 密钥对:公钥、私钥(非对称加密,一方加密只有另一方可以解密)
    • 公钥加密、必须私钥解密
    • 私钥加密、必须公钥解密
  • 应用场景:
    • 密钥分发(对称加密的密钥分发)
      • 公钥加密,私钥解密
      • 将公钥分发给其他人,其他人都可以使用公钥加密数据,但只有自己的私钥可以解密数据
    • 数字签名(验证数据是否被篡改、数据的所有者)
      • 私钥加密,公钥解密
      • 签名
        • 对原始数据进行哈希运算,对哈希值加密得到密文
        • 将原始数据和加密的哈希值发送给其他人
      • 校验签名
        • 收到 原始数据 和 加密的哈希值
        • 对原始数据求 哈希值
        • 对加密的哈希值解密得到 哈希值
        • 比较两个哈希值判断数据是否被篡改(还需要验证公钥的发送人身份,CA机构就是干这个的)

2.2 生成RSA密钥对

  • 头文件
#include <openssl/rsa.h>
  • 得到RSA类型的变量
RSA* RSA_new(void);        // 申请一块内存, 存储了公钥和私钥
  • 生成密钥对,取公钥和私钥
int RSA_generate_key_ex(RSA* rsa, int bits, BIGNUM* e, BN_GENCB* cb);
/*  参数:
        rsa: 通过RSA_new()获得
        bits: 秘钥长度, 单位: bit, 常用的长度 1024*n (n正整数)
        e: 比较大的数(5位以内)
            通过 BIGNUM* e = BN_new(); 获得
            初始化: BN_set_word(e, 12345);
        cb: 回调函数, 用不到, 直接写NULL       */

// rsa公钥私钥类型是一样的: RSA类型
// 将参数rsa中的公钥提取出来
RSA* RSAPublicKey_dup(RSA* rsa);
/*  rsa参数: 秘钥信息
    返回值: rsa公钥      */
// 将参数rsa中的私钥提取出来
RSA* RSAPrivateKey_dup(RSA* rsa);
/*  rsa参数: 秘钥信息
    返回值: rsa私钥    */
  • 将密钥存储到磁盘
#include <openssl/pem.h>    // 头文件
extern "C"
{    // 由于dll库里没有这个部分,需要包含进去一起编译
    #include <openssl/applink.c>
}

int PEM_write_RSAPublicKey(FILE* fp, const RSA* r);
int PEM_write_RSAPrivateKey(FILE* fp, const RSA* r, const EVP_CIPHER* enc, unsigned char* kstr, int klen, pem_password_cb *cb, void* u);    
/*  参数:
        fp: 需要打开一个磁盘文件, 并且指定写权限
        r: 存储了密钥对
        /------- 私钥独有的参数 -------/
        enc: 指定的加密算法 -> 对称加密 -> NULL
        kstr: 对称加密的秘钥 -> NULL
        klen: 秘钥长度 -> 0
        cb: 回调函数, 用不到, NULL
        u: 给回调传参, 用不到, NULL        */
RSA* PEM_read_RSAPublicKey(FILE* fp, RSA** r, pem_password_cb *cb, void* u);
RSA* PEM_read_RSAPrivateKey(FILE* fp, RSA** r, pem_password_cb *cb, void* u);
  • 示例代码
#include <openssl/pem.h>
using namespace std;
int main()
{
    RSA* rsa = RSA_new();   // 创建RSA变量
    BIGNUM* e = BN_new();   // 创建bignum变量并实例化
    BN_set_word(e, 12345);
    RSA_generate_key_ex(rsa, 4096, e, NULL);    // 生成密钥对
    FILE* fp = fopen("public.pem", "w");
    PEM_write_RSAPublicKey(fp, rsa);    // 写入公钥
    fp = fopen("private.pem", "w");
    PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL);    // 写入私钥
    fclose(fp);
}

2.3 加密

  • 使用公钥或私钥,加密或解密(加密后的长度和密钥长度相同,还需要指定填充方案,所以传入的数据应该小于等于密钥长度 - 填充长度
// ---- 加密使用 ----
// 公钥加密
int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
// 私钥解密
int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);

// ---- 签名使用 ----
// 私钥加密
int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
// 公钥解密
int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
/*  参数:
        flen: 要加密/解密的数据长度
            长度 0 < flen <= 秘钥长度-11
        from: 传入, 要加密/解密的数据
        to: 传出, 存储数据, 加密->存储密文, 解密->存储明文
        rsa: 秘钥: 公钥/私钥
        padding: 指定填充方案, 数据填充, 不需要使用者做
            RSA_PKCS1_PADDING -> 使用该方案会填充11字节     */
  • 代码示例
#include <openssl/pem.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
    // 创建密钥过程
    RSA *rsa = RSA_new(); // 创建RSA变量
    BIGNUM *e = BN_new(); // 创建bignum变量并实例化
    BN_set_word(e, 12345);
    RSA_generate_key_ex(rsa, 1024, e, NULL); // 生成密钥对
    RSA *pubKey = RSAPublicKey_dup(rsa);
    RSA *priKey = RSAPrivateKey_dup(rsa);
    // 加密过程
    int keyLen = RSA_size(pubKey); // 数据被加密后和密钥的长度相同
    string msg = "Hello world!";
    char *buf = new char[keyLen];
    int ret = RSA_public_encrypt(msg.size(), (const unsigned char *)msg.data(), (unsigned char *)buf, pubKey, RSA_PKCS1_PADDING);
    cout << "加密后的长度为 " << ret << endl;
    // 解密过程
    char *newText = new char[keyLen];
    ret = RSA_private_decrypt(128, (const unsigned char *)buf, (unsigned char *)newText, priKey, RSA_PKCS1_PADDING);
    cout << "解密后的长度为 " << ret << endl;
    cout << newText << endl;
}

2.4 签名

  • 加密哈希值和验证哈希值
int RSA_sign(int type, const unsigned char *m, unsigned int m_length, unsigned char *sigret, unsigned int *siglen, RSA *rsa);
/*  参数:
        type: 使用的哈希算法
            NID_MD5
            NID_SHA1
            NID_SHA224
             .....
        m: 要进行签名的数据
        m_length: 要签名的数据长度
            - 0 < m_length <= 秘钥长度-11
        sigret: 传出, 存储了签名之后的数据 -> 密文
        siglen: sigret密文长度
        rsa: 私钥
    返回值: 判断函数状态          */

int RSA_verify(int type, const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, RSA *rsa);
/*  参数:
        type: 使用的哈希算法, 和签名使用的哈希算法一致
            NID_MD5
            NID_SHA1
            NID_SHA224
             .....
        m: 进行签名的原始数据 -> 接收到的
        m_length: m参数字符串的长度
        sigbuf: 接收到的签名数据
        siglen: sigbuf接收到的签名数据的长度
        rsa: 公钥
    返回值:
        如果!=1: 失败
        如果==1: 成功         */
        

3. 对称加密

  • 生成加密解密的key
#include <openssl/aes.h>
# define AES_BLOCK_SIZE 16    // 明文分组的大小
// 加密的时候调用,aes中的秘钥格式 AES_KEY
// 封装加密时候使用的秘钥
AES_KEY key;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
// 封装解密时候使用的秘钥
int AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
/*  userkey: 对称加密的密钥->字符串长度: 16, 24, 32byte
    bites: 指定密钥的长度: 单位 bit
    key: 传出参数           */
  • CBC方式加密 - 密码分组链接模式
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
                     size_t length, const AES_KEY *key,
                     unsigned char *ivec, const int enc);
/*  参数:
        in: 要加密/解密的数据
        out: 传出参数
            加密: 存储密文
            解密: 存储明文
        length: 修改第一个参数in的长度
            (len = (字符串长度 + \0) % 16) == 0
        如果不是在函数内部会自动填充
            实际长度: ((len / 16) + 1 ) * 16
        key: 初始化之后的秘钥
        ivec: 初始化向量, 字符串 ==> 长度和分组长度相同
            enc: 指定数据要解密还是解密
                # define AES_ENCRYPT     1 -> 加密
                # define AES_DECRYPT     0 -> 解密     */
  • 示例代码
#include <openssl/aes.h>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
    // 1.准备数据
    const char *pt = "data1, data2, data3, data4, data5, data6, data7, data8, data9, data10";
    // 2.准备密钥
    const char *key = "123456787654321"; // 16位(或24,32)
    // 3.初始化密钥
    AES_KEY encKey;
    AES_set_encrypt_key((const unsigned char*)key, 128, &encKey);
    // 4.加密
    int length = 0;
    int len = strlen((char *)pt) + 1;
    if (len % 16 != 0)
    {
        length = ((len / 16) + 1) * 16;
    }
    else
    {
        length = len;
    }
    unsigned char *out = new unsigned char[length]; // 存储密文
    unsigned char ivec[16];
    memset(ivec, 9, sizeof(ivec));
    AES_cbc_encrypt((const unsigned char*)pt, out, length, &encKey, ivec, AES_ENCRYPT);
    // 5.解密
    unsigned char* data = new unsigned char[length];
    AES_KEY deckey;
    AES_set_decrypt_key((const unsigned char*)key, 128, &deckey);
    memset(ivec, 9, sizeof(ivec));
    AES_cbc_encrypt((const unsigned char*)out, data, length, &deckey, ivec, AES_DECRYPT);
    // 6.打印
    cout<<data<<endl;
    delete[] out;
    delete[] data;
}

 

标签:加密,rsa,int,OpenSSL,RSA,char,哈希,unsigned
From: https://www.cnblogs.com/stux/p/17882155.html

相关文章

  • 软件测试/人工智能|HTTPS加密协议,你会多少?
    什么是HTTPS?HTTPS是超文本传输协议(HTTP)的安全版本。它通过使用安全套接层协议(SSL)或传输层安全协议(TLS)来加密通信内容,确保数据在客户端和服务器之间传输时得到保护。这种加密机制防止了黑客或恶意用户窃取、篡改或窥视传输的数据。本文将详细介绍HTTPS的加密过程及其工作原理。HTT......
  • Java 标准库实现常见加密解密
    一时兴起,好奇Java中常用的加解密是如何实现的,今天就常见的bas64编码解码、MD5、SHA256、HmacSHA256做个简单小结,希望对各位有用。环境:JDK:17以下内容基于JDK17的自带工具库实现,示例如下:packagecom.example.util;importjavax.crypto.Mac;importjavax.crypto.......
  • 数据库数据恢复—sqlserver数据库和备份被加密,数据库文件名被篡改的数据恢复案例
    SQLServer数据库故障:某公司服务器上的SQLServer数据库被加密,无法使用。被加密的数据库有2个,数据库的MDF、LDF、log文件名字被篡改。数据库被加密截图:数据库备份被加密,文件名字被篡改:SQLServer数据库数据恢复过程:1、将故障数据库内的数据备份至北亚企安数据恢复中心的专用存......
  • 第13章. 哈希表
    哈希表(HashTable)一、引言TreeMap分析添加、删除、搜索的时间复杂度:O(n)特点:key必须具备可比较性元素的分布是有顺序的但是在实际应用中,很多时候的需求中Map中存储的元素不需要讲究顺序Map中的Key不需要具备可比较性不考虑顺序、不考虑Key的可比较性,Map有更好......
  • SpringBoot集成Jasypt实现数据加密
    1、环境说明JDK1.8+SpringBoot2.7 2、添加pom依赖<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.3</version></dependency> 3......
  • Vue 应用程序性能优化:代码压缩、加密和混淆配置详解
    ​简介在Vue应用程序的开发中,代码压缩、加密和混淆是优化应用程序性能和提高安全性的重要步骤。VueCLI是一个功能强大的开发工具,它提供了方便的配置选项来实现这些功能。本文将介绍如何使用VueCLI配置代码压缩、加密和混淆功能,以提高应用程序的性能和安全性。一、配置代......
  • 移动app之base64编码后的AES加密流量
    移动app之base64编码后的AES加密流量别搁那你抄我,我抄你了。咱直接抄海外okay?参考资料:https://www.vaadata.com/blog/insecure-authentication-tokens-leading-to-account-takeover/技术点AES-256-CBC加密base64编码会话管理请求包:GET/loginHTTP/1.1Host:172.23.7......
  • AES 加密
    1.AES程序加密1packagecom.demo.util;23importcom.demo.exception.BusinessException;4importcom.demo.model.enums.ErrorEnum;5importlombok.extern.slf4j.Slf4j;6importorg.apache.commons.lang3.RandomStringUtils;7importorg.apache.comm......
  • 什么是全同态加密(FHE)中的自举(Bootstrapping)?
    PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。全同态加密(FullyHomomorphicEncryption,FHE)中经常提到的一个术语是“自举”(Bootstrapping)。任何读过FHE初级材料的人都知道,自举是FHE方案中最......
  • 第五节:哈希表详解 和 面试题剖析
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......