一、密码学基础:对称加密与非对称加密概述、哈希函数、C语言中的大数运算库简介

各位同学,欢迎来到《C语言加密解密与安全编程实战》的第一章。我是你们这门课的老朋友,一个在安全领域摸爬滚打多年的工程师。今天咱们不聊虚的,直接切入正题——密码学基础。

很多人一听到「密码学」三个字就头大,觉得那是数学家干的事。其实不然。你想想看,我们每天都在用密码学:微信聊天、网上银行、甚至你登录这台电脑的密码验证,背后都离不开它。作为C语言开发者,我们不仅要会用,还得知道它为什么安全、又可能在哪儿翻车。

核心观点:密码学的本质,是在不安全的信道上实现安全通信。说白了,就是让该看的人看懂,不该看的人看不懂。

1.1 对称加密:一把钥匙开一把锁

对称加密,顾名思义,加密和解密用的是同一把密钥。就像你家的门锁,用同一把钥匙锁门和开门。

常见的对称加密算法有:AES、DES、3DES、SM4(国密标准)。其中AES是目前应用最广泛的,我个人习惯在项目里优先选用AES-256。

对称加密的工作流程:

  1. 发送方用密钥K对明文P加密,得到密文C
  2. 密文C通过网络传输给接收方
  3. 接收方用同样的密钥K对密文C解密,还原出明文P

我的经验:我在项目中遇到过一个问题——密钥怎么安全地传给对方?如果网络本身不安全,你传密钥的过程就可能被截获。这就是对称加密最大的痛点:密钥分发问题。后来我改用非对称加密来传对称密钥,才彻底解决。

对称加密的优缺点:

优点 缺点
加解密速度快,适合大数据量 密钥分发困难,需要安全通道
算法成熟,硬件支持好 密钥数量爆炸(n个人需要n(n-1)/2个密钥)
实现相对简单 无法提供数字签名功能

1.2 非对称加密:公钥私钥,各司其职

非对称加密的出现,解决了对称加密的密钥分发难题。它使用一对密钥:公钥(公开)和私钥(保密)。公钥加密的数据只能用私钥解密,私钥加密的数据只能用公钥解密。

常见的非对称加密算法:RSA、ECC(椭圆曲线)、SM2(国密)。RSA是最经典的,但ECC在同等安全强度下密钥更短、性能更好。

非对称加密的核心流程:

  1. 接收方生成密钥对(公钥PK,私钥SK),把公钥公开
  2. 发送方用公钥PK加密明文P,得到密文C
  3. 接收方用私钥SK解密密文C,还原出明文P

避坑指南:我曾经犯过一个低级错误——直接用RSA加密大文件。结果呢?RSA有长度限制,1024位密钥最多只能加密117字节。超过这个长度,要么报错,要么数据被截断。正确的做法是:用非对称加密传对称密钥,用对称密钥加密实际数据。这叫「混合加密」,HTTPS就是这么干的。

1.3 哈希函数:数据的「指纹」

哈希函数,也叫散列函数。它能把任意长度的输入,变成固定长度的输出(哈希值)。而且这个输出是不可逆的——你没法从哈希值反推出原始数据。

常见的哈希算法:MD5(已不安全)、SHA-1(已不安全)、SHA-256、SHA-3、SM3(国密)。

哈希函数的三大特性:

  • 抗原像性:给定哈希值H,找不到任何消息M使得Hash(M)=H
  • 抗第二原像性:给定消息M1,找不到另一个消息M2使得Hash(M1)=Hash(M2)
  • 抗碰撞性:找不到任意两个不同的消息M1和M2使得Hash(M1)=Hash(M2)

实际应用场景:

  • 密码存储:不存明文密码,只存哈希值。即使用户数据库泄露,攻击者也拿不到原始密码。
  • 文件完整性校验:下载文件后比对哈希值,看文件是否被篡改。
  • 数字签名:先对消息哈希,再对哈希值签名,效率更高。

嗯,这里要注意一点:哈希不是加密。加密是可逆的,哈希是不可逆的。千万别搞混了。

1.4 C语言中的大数运算库简介

密码学离不开大数运算。RSA的密钥动辄2048位,ECC的曲线参数也是几百位的大整数。C语言自带的int、long根本装不下。怎么办?得用大数运算库。

主流的大数运算库:

库名 特点 适用场景
OpenSSL (BN) 功能最全,性能好,跨平台 生产环境,商业项目
GMP 性能极致,但API较底层 科研计算,高性能需求
libtommath 轻量级,代码清晰,适合学习 嵌入式系统,教学演示
Miracl 专为密码学设计,支持椭圆曲线 密码学算法实现

我个人习惯用OpenSSL的BN库。它封装得比较好,加减乘除、模幂、求逆这些操作都有现成函数。而且OpenSSL几乎成了Linux系统的标配,省去了额外安装的麻烦。

一个简单的BN使用示例:

#include <openssl/bn.h>
#include <stdio.h>

int main() {
    BIGNUM *a, *b, *c;
    BN_CTX *ctx;

    // 初始化
    ctx = BN_CTX_new();
    a = BN_new();
    b = BN_new();
    c = BN_new();

    // 赋值:a = 12345678901234567890
    BN_dec2bn(&a, "12345678901234567890");
    // 赋值:b = 98765432109876543210
    BN_dec2bn(&b, "98765432109876543210");

    // 计算 c = a + b
    BN_add(c, a, b);

    // 打印结果
    char *result = BN_bn2dec(c);
    printf("a + b = %s\n", result);
    OPENSSL_free(result);

    // 清理
    BN_free(a);
    BN_free(b);
    BN_free(c);
    BN_CTX_free(ctx);

    return 0;
}

编译提示:编译时记得链接OpenSSL库:gcc -o test test.c -lssl -lcrypto

你可能会问:为什么需要BN_CTX?说白了,大数运算过程中会产生很多临时变量,BN_CTX就是用来管理这些临时变量的内存池,避免频繁申请释放内存,提高性能。

本章知识体系总览

下面这张图,把本章的核心知识点串起来了。你可以把它当作一张「密码学基础地图」,以后学新内容时随时回来对照。

密码学基础 · 知识体系 对称加密 非对称加密 哈希函数 AES / DES / SM4 密钥分发问题 RSA / ECC / SM2 公钥加密,私钥解密 SHA-256 / SM3 不可逆,抗碰撞 C语言大数运算库 OpenSSL BN GMP / libtommath Miracl

好了,第一章的内容就到这里。对称加密、非对称加密、哈希函数、大数运算库——这四个概念是后面所有章节的基石。你可能会觉得哈希函数有点抽象,没关系,后面讲到数字签名和证书时,你会看到它到底有多重要。

记住一句话:密码学不是魔法,它只是把数学问题变成了工程问题。而我们要做的,就是用好C语言这把手术刀,把这些数学原理变成可靠的代码。


公众号:蓝海资料掘金营,微信deep3321