文章目录
-
- 1、严谨的定义
- 2、技术原理:如何工作?
-
- [第一步:发送者 - 签名过程](#第一步:发送者 - 签名过程)
- [第二步:接收者 - 签名验证过程](#第二步:接收者 - 签名验证过程)
- 3、C语言实现示例
- 4、关键技术要点
- 5、安全注意事项
- [6、最重要的应用:TLS/SSL 与网站安全](#6、最重要的应用:TLS/SSL 与网站安全)
1、严谨的定义
数字签名 是一种利用非对称密码学 (公钥密码学)技术来验证数字信息、软件或文件的真实性 、完整性 和不可否认性的数学方案。
它解决了三个核心安全问题:
- 认证:这条信息确实来自声称的发送者。
- 完整性:信息在传输过程中没有被篡改过。
- 不可否认性:发送者事后无法否认他发送过这条信息。
2、技术原理:如何工作?
数字签名基于非对称加密,它使用一对数学上相关的密钥:
- 私钥:由所有者严格保密,绝不泄露。用于创建签名。
- 公钥:可以公开发布给任何人。用于验证签名。
其工作流程分为两大步:签名 和 验证。
第一步:发送者 - 签名过程
原始消息 哈希函数 Hash Function
e.g. SHA-256 得到固定长度的消息摘要
Message Digest 用发送者的私钥
加密消息摘要 生成数字签名 将数字签名附加在
原始消息后面一起发送
为什么先哈希再加密?
- 效率:非对称加密非常慢,而哈希函数很快。加密一个短的摘要(如256位)比加密整个大文件(几个GB)要高效得多。
- 通用性:非对称加密算法有输入长度限制,而哈希后的摘要长度是固定的,适用于所有加密算法。
第二步:接收者 - 签名验证过程
是 否 接收消息+签名 验证流程 分离出原始消息和数字签名 用发送者的公钥
解密数字签名 得到 解密后的摘要H1 对收到的原始消息
使用同样的哈希函数 SHA-256 得到 计算出的摘要H2 对比 H1 == H2? 验证成功
消息完整且真实 验证失败
消息被篡改或签名无效
3、C语言实现示例
以下是一个简化的数字签名实现示例,使用OpenSSL库:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#define KEY_LENGTH 2048
#define PUB_EXP 3
// 生成RSA密钥对
RSA *generate_rsa_keypair() {
RSA *rsa = RSA_new();
BIGNUM *bn = BN_new();
if (!BN_set_word(bn, PUB_EXP)) {
fprintf(stderr, "Error setting exponent\n");
return NULL;
}
if (!RSA_generate_key_ex(rsa, KEY_LENGTH, bn, NULL)) {
fprintf(stderr, "Error generating RSA key\n");
return NULL;
}
BN_free(bn);
return rsa;
}
// 生成消息的SHA-256哈希
int generate_hash(const unsigned char *message, unsigned char *hash) {
if (!message || !hash) return 0;
SHA256_CTX sha256;
if (!SHA256_Init(&sha256)) return 0;
if (!SHA256_Update(&sha256, message, strlen((char *)message))) return 0;
if (!SHA256_Final(hash, &sha256)) return 0;
return 1;
}
// 使用私钥创建签名
int create_signature(RSA *private_rsa, const unsigned char *hash,
unsigned char **signature, unsigned int *sig_len) {
if (!private_rsa || !hash || !signature || !sig_len) return 0;
*signature = (unsigned char *)malloc(RSA_size(private_rsa));
if (!*signature) return 0;
// 使用私钥加密哈希值(即签名)
if (RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH,
*signature, sig_len, private_rsa) != 1) {
free(*signature);
return 0;
}
return 1;
}
// 使用公钥验证签名
int verify_signature(RSA *public_rsa, const unsigned char *hash,
const unsigned char *signature, unsigned int sig_len) {
if (!public_rsa || !hash || !signature) return 0;
// 使用公钥验证签名
if (RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH,
signature, sig_len, public_rsa) != 1) {
return 0; // 验证失败
}
return 1; // 验证成功
}
// 示例使用
int main() {
const char *message = "这是一条需要签名的重要消息";
unsigned char hash[SHA256_DIGEST_LENGTH];
unsigned char *signature = NULL;
unsigned int sig_len = 0;
// 初始化OpenSSL
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
// 生成密钥对
RSA *rsa_keypair = generate_rsa_keypair();
if (!rsa_keypair) {
fprintf(stderr, "密钥对生成失败\n");
return 1;
}
printf("1. 生成SHA-256哈希...\n");
if (!generate_hash((unsigned char *)message, hash)) {
fprintf(stderr, "哈希生成失败\n");
return 1;
}
printf("2. 使用私钥创建签名...\n");
if (!create_signature(rsa_keypair, hash, &signature, &sig_len)) {
fprintf(stderr, "签名创建失败\n");
return 1;
}
printf("3. 使用公钥验证签名...\n");
if (verify_signature(rsa_keypair, hash, signature, sig_len)) {
printf("✅ 签名验证成功!消息完整且真实。\n");
} else {
printf("❌ 签名验证失败!消息可能被篡改。\n");
}
// 清理资源
free(signature);
RSA_free(rsa_keypair);
EVP_cleanup();
ERR_free_strings();
return 0;
}
4、关键技术要点
1.哈希函数的作用:SHA-256将任意长度消息转换为固定长度摘要,确保效率和安全性
2.非对称加密:私钥签名,公钥验证,实现身份认证
3.安全性依赖:
- 哈希函数的抗碰撞性
- RSA算法的数学困难性(大数分解问题)
4.实际应用:
- SSL/TLS证书验证
- 软件分发验证
- 区块链交易签名
- 安全电子邮件(S/MIME)
5、安全注意事项
- 私钥必须安全存储,最好使用硬件安全模块(HSM)
- 使用足够长的密钥(RSA推荐2048位以上)
- 定期更新密钥对
- 使用安全的随机数生成器
数字签名是现代网络安全的基础构建块,为数字通信提供了不可或缺的真实性、完整性和不可否认性保障。
6、最重要的应用:TLS/SSL 与网站安全
当你用浏览器访问 https://
开头的网站时,就会用到数字签名。
- 网站服务器会把它公钥 和身份信息(域名等)打包成一个 SSL 证书。
- 这个证书需要由证书颁发机构 用 CA 的私钥 进行数字签名。
- 你的电脑和浏览器里预装了受信任的 CA 的公钥。
- 浏览器收到网站证书后,用内置的 CA 公钥去验证证书上的签名。
- 验证成功 :说明此证书真实有效,且未被篡改。你就能确信你连接的就是
google.com
,而不是一个钓鱼网站。随后才会开始加密通信。 - 验证失败:浏览器就会弹出巨大的红色警告,阻止你继续访问。
总结
特性 | 如何实现 |
---|---|
真实性 | 只有用发送者的私钥才能生成能被其公钥成功解开的签名。 |
完整性 | 签名的生成依赖于原始消息的哈希值,任何改动都会导致哈希值巨变,使验证失败。 |
不可否认性 | 由于私钥由发送者唯一持有,成功验证的签名可以作为法律证据,证明发送者确实生成了该签名。 |
简单来说,数字签名是现实世界中手写签名和印章在数字世界的终极升级版,它不仅证明了签署者的身份,还保证了被签署内容本身一丝一毫都未被改变。