数字签名 digital signature
文章目录
- 1、严谨的定义
- 2、技术原理:如何工作?
- 第一步:发送者 - 签名过程
- 第二步:接收者 - 签名验证过程
- 3、C语言实现示例
- 4、关键技术要点
- 5、安全注意事项
- 6、最重要的应用:TLS/SSL 与网站安全
1、严谨的定义
数字签名是一种利用非对称密码学(公钥密码学)技术来验证数字信息、软件或文件的真实性、完整性和不可否认性的数学方案。
它解决了三个核心安全问题:
- 认证:这条信息确实来自声称的发送者。
- 完整性:信息在传输过程中没有被篡改过。
- 不可否认性:发送者事后无法否认他发送过这条信息。
2、技术原理:如何工作?
数字签名基于非对称加密,它使用一对数学上相关的密钥:
- 私钥:由所有者严格保密,绝不泄露。用于创建签名。
- 公钥:可以公开发布给任何人。用于验证签名。
其工作流程分为两大步:签名 和 验证。
第一步:发送者 - 签名过程
为什么先哈希再加密?
- 效率:非对称加密非常慢,而哈希函数很快。加密一个短的摘要(如256位)比加密整个大文件(几个GB)要高效得多。
- 通用性:非对称加密算法有输入长度限制,而哈希后的摘要长度是固定的,适用于所有加密算法。
第二步:接收者 - 签名验证过程
3、C语言实现示例
以下是一个简化的数字签名实现示例,使用OpenSSL库:
#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;// 初始化OpenSSLOpenSSL_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、关键技术要点
- 哈希函数的作用:SHA-256将任意长度消息转换为固定长度摘要,确保效率和安全性
- 非对称加密:私钥签名,公钥验证,实现身份认证
- 安全性依赖:
- 哈希函数的抗碰撞性
- RSA算法的数学困难性(大数分解问题)
- 实际应用:
- SSL/TLS证书验证
- 软件分发验证
- 区块链交易签名
- 安全电子邮件(S/MIME)
5、安全注意事项
- 私钥必须安全存储,最好使用硬件安全模块(HSM)
- 使用足够长的密钥(RSA推荐2048位以上)
- 定期更新密钥对
- 使用安全的随机数生成器
数字签名是现代网络安全的基础构建块,为数字通信提供了不可或缺的真实性、完整性和不可否认性保障。
6、最重要的应用:TLS/SSL 与网站安全
当你用浏览器访问 https://
开头的网站时,就会用到数字签名。
- 网站服务器会把它公钥和身份信息(域名等)打包成一个 SSL 证书。
- 这个证书需要由证书颁发机构用 CA 的私钥进行数字签名。
- 你的电脑和浏览器里预装了受信任的 CA 的公钥。
- 浏览器收到网站证书后,用内置的 CA 公钥去验证证书上的签名。
- 验证成功:说明此证书真实有效,且未被篡改。你就能确信你连接的就是
google.com
,而不是一个钓鱼网站。随后才会开始加密通信。 - 验证失败:浏览器就会弹出巨大的红色警告,阻止你继续访问。
总结
特性 | 如何实现 |
---|---|
真实性 | 只有用发送者的私钥才能生成能被其公钥成功解开的签名。 |
完整性 | 签名的生成依赖于原始消息的哈希值,任何改动都会导致哈希值巨变,使验证失败。 |
不可否认性 | 由于私钥由发送者唯一持有,成功验证的签名可以作为法律证据,证明发送者确实生成了该签名。 |
简单来说,数字签名是现实世界中手写签名和印章在数字世界的终极升级版,它不仅证明了签署者的身份,还保证了被签署内容本身一丝一毫都未被改变。