文章目录
一、引言
在当今数字化时代,数据已成为最具价值的资产之一,而保护这些数据免受未授权访问、篡改和盗窃的需求比以往任何时候都更加迫切。加密技术作为信息安全的核心支柱,为数据提供了一层强大的保护,确保敏感信息在存储和传输过程中保持机密性和完整性。简单来说,加密是一种将可读数据(明文)转换为不可读格式(密文)的过程,使得只有拥有正确密钥的人能够恢复原始信息。这一基本概念虽然简单,但其实施方式却极其复杂和多样化,形成了当今密码学的广阔领域。
加密的重要性不容忽视。随着越来越多的个人和企业将关键数据迁移到云存储,通过互联网进行敏感通信,并依赖数字系统处理日常事务,保护这些数据免受恶意行为者侵害的需求变得尤为迫切。没有强大的加密,我们的数字通信和交易将容易受到各种形式的网络威胁,包括身份盗窃、数据泄露和金融欺诈。加密技术的应用范围广泛,从保护个人隐私(如电子邮件和消息应用)到维护国家安全和商业机密,几乎涵盖了数字世界的方方面面。
加密技术的历史可以追溯到古代,但现代加密技术,特别是计算机时代的加密算法,经历了从简单的替换密码到复杂的数学算法的漫长发展过程。随着计算能力的飞速提升,加密算法也不断演进,以应对日益复杂的网络安全威胁。
二、发展历史
-
早期加密方法:在计算机时代之前,加密主要依靠机械和手工方法。例如,二战期间使用的
Enigma
机器就是一个著名的加密设备,它通过一系列的转子和电线来实现加密。虽然这些早期方法在当时具有一定的安全性,但它们往往容易被破解,且效率低下。艾伦·麦席森·图灵(英语:
Alan Mathison Turing
,1912-06-23
~1954-06-07
),英国计算机科学家、数学家、逻辑学家、密码分析学家、理论生物学家,“计算机科学之父”、“人工智能之父”,英国皇家学会院士。-
1935
年当选为剑桥大学国王学院研究员; -
1936
年提出被称为图灵机的逻辑机通用模型; -
1938
年获普林斯顿大学博士学位; -
1939
年开始在英国军方工作,期间破解德国密码系统恩尼格玛密码机和金枪鱼密码机,加速了盟军取得了二战的胜利; -
1946
年获大英帝国勋章; -
1945
年至1948
年在伦敦泰丁顿国家物理实验室负责自动计算引擎(ACE
)的研究工作; -
1948
年任曼彻斯特大学高级讲师、自动数字计算机(Madam
)项目的负责人助理; -
1949
年任曼彻斯特大学计算机实验室副主任; -
1950
年提出机器具备思维的可能性和 “图灵测试” 的概念; -
1951
年当选为英国皇家学会院士; -
1954
年服用含氰化物的苹果去世,享年41
岁。
豆瓣电影
Top155
推荐:模仿游戏 The Imitation Game (2014) -
-
现代加密算法的发展:随着计算机技术的发展,加密算法也进入了数字化时代。
1976
年,Diffie
(图左)和Hellman
(图右)提出了非对称加密的概念(荣获2015
年图灵奖),这标志着现代密码学的一个重要里程碑。非对称加密使用一对密钥:一个公钥和一个私钥,使得加密和解密可以由不同的密钥完成。这种方法极大地提高了通信的安全性,因为它允许在不安全的信道上安全地交换密钥。
-
对称加密算法的演进:对称加密算法也在不断发展。
DES(Data Encryption Standard)
(数据加密标准)是最早的对称加密算法之一,但它使用56
位密钥,安全性相对较弱。为了提高安全性,3DES(Triple DES)
被提出,它使用三个DES
加密步骤,大大增加了破解的难度。随后,AES(Advanced Encryption Standard)
(高级加密标准)被开发出来,它使用128
位、192
位或256
位密钥,提供了更高的安全性,并且被广泛采用。 -
哈希函数和数字签名:除了加密算法,哈希函数和数字签名也是现代密码学的重要组成部分。哈希函数将数据映射到固定长度的哈希值,用于数据完整性检查和密码存储等场景,而数字签名允许验证消息的来源和完整性。
三、分类与原理
-
对称加密与非对称加密:加密算法主要分为对称加密和非对称加密两大类。对称加密使用相同的密钥进行加密和解密,而非对称加密则使用一对不同的密钥:公钥和私钥。对称加密速度快,适合大量数据的加密,而非对称加密则在密钥分发和数字签名方面具有优势。
-
哈希函数与消息认证码:哈希函数和消息认证码(
MAC(Message Authentication Code)
)是两种不同的数据验证机制。哈希函数(无需密钥)将输入数据映射到固定长度的输出,且具有单向性和碰撞抗性。消息认证码(需要密钥)则结合了加密和哈希函数,用于验证消息的完整性和来源的真实性。 -
加密算法的基本原理:加密算法的基本原理是将明文通过一定的数学变换转换为密文,使得只有拥有正确密钥的人才能恢复原始信息。这些算法通常基于复杂的数学问题,如大整数分解、离散对数等,使得在没有密钥的情况下破解加密变得极其困难。
加密算法分类 | 特点 |
---|---|
对称加密 | 加解密使用相同密钥 加密速度快,适合大量数据加密 |
非对称加密 | 公钥加密,私钥解密 计算开销大,密钥分发存在天然优势 |
哈希函数 | 将输入数据映射到固定长度输出 无需密钥、单向不可逆、抗碰撞性 |
消息认证码 | 哈希函数 + 对称加密 |
数字签名 | 哈希函数 + 非对称加密 |
四、常见加密算法
加密算法填充模式:加密算法在处理数据时,常常需要确保数据长度符合特定的要求,这通常是因为加密算法需要处理固定大小的数据块。为了满足这一要求,当数据长度不满足这一要求时,就需要使用填充模式(Padding Scheme
)。填充模式是在数据的末尾添加一些额外的信息,使得数据长度达到一个合适的长度,以便进行加密。
填充模式 | 填充方式 | 优点 | 缺点 |
---|---|---|---|
Zero Padding | 直接在数据的末尾添加零(0x00 ),直到达到所需的长度 | 最简单的填充方法,简单易实现 | 如果原始数据本身以 0 结尾,可能会导致数据与填充部分难以区分 |
PKCS#5/7 | 填充的字节都是相同的值,该值等于需要填充的字节数。例如,如果需要填充 5 个字节,那么这 5 个字节的值都是 0x05 | 常用的填充模式,可以明确知道填充了多少字节,便于解填充 | 如果原始数据本身以 1 结尾,且填充值为 1 ,可能会与数据本身混淆 |
PKCS#1 v1.5 | 主要用于 RSA 加密,使用一个固定的填充模式,包括一些特定的字节和随机数据 | 提供了更高的安全性 | 比较复杂,且不适用于所有类型的加密算法 |
ANSI X.923 | 填充字节除了最后一个字节外,其余字节都填充为零。最后一个字节表示填充的字节数 | 相对简单,且可以明确知道填充了多少字节 | 如果数据本身以 0 结尾,可能会导致数据与填充部分难以区分 |
ISO 10126 | 除了最后一个字节外,其余填充字节都是随机数据。最后一个字节表示填充的字节数 | 随机性增加了安全性 | 需要生成随机数,增加了实现的复杂性 |
ISO/IEC 7816-4 | 主要用于智能卡中,填充字节除了最后一个字节外,其余字节都是 0x00 。最后一个字节表示填充的字节数 | 适用于智能卡等特定场景 | 应用场景有限 |
PKCS
:Public Key Cryptography Standards
ANSI
:American National Standards Institute
ISO
:International Organization for Standardization
IEC
:International Electrotechnical Commission
// padding 填充函数 (PKCS5/PKCS7)
func padding(src []byte, blockSize int) []byte {
paddingSize := blockSize - len(src)%blockSize
padText := bytes.Repeat([]byte{byte(paddingSize)}, paddingSize)
return append(src, padText...)
}
// unPadding 去填充函数
func unPadding(src []byte) []byte {
length := len(src)
unPaddingSize := int(src[length-1])
return src[:(length - unPaddingSize)]
}
4.1 对称加密
-
DES(Data Encryption Standard)
:DES
是最早的对称加密算法之一,使用56
位密钥将64
位明文块加密为64
位密文块。由于其密钥长度较短,安全性相对较弱,已被AES
取代。// desEncrypt DES 加密 func desEncrypt(key, iv, plaintext []byte) ([]byte, error) { block, err := des.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() plaintext = padding(plaintext, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) blockMode.CryptBlocks(ciphertext, plaintext) return ciphertext, nil } // desDecrypt DES 解密 func desDecrypt(key, iv, ciphertext []byte) ([]byte, error) { block, err := des.NewCipher(key) if err != nil { return nil, err } blockMode := cipher.NewCBCDecrypter(block, iv) plaintext := make([]byte, len(ciphertext)) blockMode.CryptBlocks(plaintext, ciphertext) plaintext = unPadding(plaintext) return plaintext, nil }
-
3DES(Triple DES)
:3DES
使用三个DES
加密步骤,大大增加了破解的难度。它使用两个或三个不同的密钥,提供了比单DES
更高的安全性。// tripleDesEncrypt 3DES 加密 func tripleDesEncrypt(key, iv, plaintext []byte) ([]byte, error) { block, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() plaintext = padding(plaintext, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) blockMode.CryptBlocks(ciphertext, plaintext) return ciphertext, nil } // tripleDesDecrypt 3DES 解密 func tripleDesDecrypt(key, iv, ciphertext []byte) ([]byte, error) { block, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } blockMode := cipher.NewCBCDecrypter(block, iv) plaintext := make([]byte, len(ciphertext)) blockMode.CryptBlocks(plaintext, ciphertext) plaintext = unPadding(plaintext) return plaintext, nil }
-
AES(Advanced Encryption Standard)
:AES
是目前最常用的对称加密算法之一,使用128
位、192
位或256
位密钥将128
位明文块加密为128
位密文块。AES
基于有限域上的字节替代、行移位、列混淆和轮密钥加等操作,提供了高强度的安全性。// aesEncrypt AES 加密 func aesEncrypt(key, iv, plaintext []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() plaintext = padding(plaintext, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) blockMode.CryptBlocks(ciphertext, plaintext) return ciphertext, nil } // aesDecrypt AES 解密 func aesDecrypt(key, iv, ciphertext []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } blockMode := cipher.NewCBCDecrypter(block, iv) plaintext := make([]byte, len(ciphertext)) blockMode.CryptBlocks(plaintext, ciphertext) plaintext = unPadding(plaintext) return plaintext, nil }
-
SM4
:SM4
是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于2012
年3
月21
日发布,相关标准为 “GM/T 0002-2012《SM4分组密码算法》(原SMS4分组密码算法)”。2016
年8
月,成为中国国家密码标准(GB/T 32907-2016)。// sm4Encrypt SM4 加密 func sm4Encrypt(key, iv, plaintext []byte) ([]byte, error) { block, err := sm4.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() plaintext = padding(plaintext, blockSize) blockMode := cipher.NewCBCEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) blockMode.CryptBlocks(ciphertext, plaintext) return ciphertext, nil } // sm4Decrypt SM4 解密 func sm4Decrypt(key, iv, ciphertext []byte) ([]byte, error) { block, err := sm4.NewCipher(key) if err != nil { return nil, err } blockMode := cipher.NewCBCDecrypter(block, iv) plaintext := make([]byte, len(ciphertext)) blockMode.CryptBlocks(plaintext, ciphertext) plaintext = unPadding(plaintext) return plaintext, nil }
算法 | 分组大小 | 密钥长度 | 说明 |
---|---|---|---|
DES | 64 位 | 56 位 | 已淘汰(被暴力破解) |
3DES | 64 位 | 168 位 | DES 的三次迭代,逐渐被弃用 |
AES | 128 位 | 128/192/256 位 | 美国国家标准技术研究院认证标准,硬件加速支持 |
SM4 | 128 位 | 128 位 | 国密标准,安全性高 |
4.2 非对称加密
-
RSA(Rivest–Shamir–Adleman algorithm)
:RSA
是非对称加密算法的代表,基于大整数分解的数学难题。它使用一个公钥和一个私钥,公钥用于加密,私钥用于解密。RSA
算法广泛应用于数据加密、数字签名和密钥交换等领域。func generateRSAKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { return nil, nil, err } return privateKey, &privateKey.PublicKey, nil } func rsaEncrypt(publicKey *rsa.PublicKey, plaintext []byte) ([]byte, error) { return rsa.EncryptOAEP( sha256.New(), rand.Reader, publicKey, plaintext, nil, ) } func rsaDecrypt(privateKey *rsa.PrivateKey, ciphertext []byte) ([]byte, error) { return rsa.DecryptOAEP( sha256.New(), rand.Reader, privateKey, ciphertext, nil, ) } func rsaSign(privateKey *rsa.PrivateKey, message []byte) ([]byte, error) { hashed := sha256.Sum256(message) return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:]) } func rsaVerify(publicKey *rsa.PublicKey, message, signature []byte) error { hashed := sha256.Sum256(message) return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature) }
-
DSA(Digital Signature Algorithm)
:DSA
是一种基于离散对数的困难性的非对称加密算法。DSA
算法的安全性依赖于离散对数的难度,目前已经有1024
位的DSA
公钥被成功破解,因此建议使用2048
位或以上的密钥长度。func generateDSAKeyPair() (*dsa.PrivateKey, *dsa.PublicKey, error) { privateKey := new(dsa.PrivateKey) params := new(dsa.Parameters) if err := dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160); err != nil { return nil, nil, err } privateKey.PublicKey.Parameters = *params if err := dsa.GenerateKey(privateKey, rand.Reader); err != nil { return nil, nil, err } return privateKey, &privateKey.PublicKey, nil } func dsaSign(privateKey *dsa.PrivateKey, message []byte) ([]byte, error) { r, s, err := dsa.Sign(rand.Reader, privateKey, message) if err != nil { return nil, err } signature := make([]byte, 40) rBytes := r.Bytes() sBytes := s.Bytes() copy(signature[20-len(rBytes):20], rBytes) copy(signature[40-len(sBytes):40], sBytes) return signature, nil } func dsaVerify(publicKey *dsa.PublicKey, message, signature []byte) bool { if len(signature) != 40 { return false } r := new(big.Int).SetBytes(signature[:20]) s := new(big.Int).SetBytes(signature[20:]) return dsa.Verify(publicKey, message, r, s) }
-
ECC(Elliptic Curve Cryptography)
(椭圆曲线加密):ECC
基于椭圆曲线上点的离散对数问题,提供了与RSA
相同的安全性,但使用更短的密钥长度。这使得ECC
在计算效率和带宽方面具有优势,特别适合资源受限的环境。func generateECCKeyPair() (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) { privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, nil, err } return privateKey, &privateKey.PublicKey, nil } func eccSign(privateKey *ecdsa.PrivateKey, message []byte) ([]byte, error) { hashed := sha256.Sum256(message) r, s, err := ecdsa.Sign(rand.Reader, privateKey, hashed[:]) if err != nil { return nil, err } signature := make([]byte, 64) rBytes := r.Bytes() sBytes := s.Bytes() copy(signature[32-len(rBytes):32], rBytes) copy(signature[64-len(sBytes):64], sBytes) return signature, nil } func eccVerify(publicKey *ecdsa.PublicKey, message, signature []byte) bool { if len(signature) != 64 { return false } hashed := sha256.Sum256(message) r := new(big.Int).SetBytes(signature[:32]) s := new(big.Int).SetBytes(signature[32:]) return ecdsa.Verify(publicKey, hashed[:], r, s) }
-
SM2
:SM2
椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1
椭圆曲线数字签名算法,SM2-2
椭圆曲线密钥交换协议,SM2-3
椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2
算法与RSA
算法不同的是,SM2
算法是基于椭圆曲线上点群离散对数难题,相对于RSA
算法,256
位的SM2
密码强度已经比2048
位的RSA
密码强度要高,且运算速度快于RSA
。import ( "github.com/tjfoc/gmsm/sm2" ) func generateSM2KeyPair() (*sm2.PrivateKey, *sm2.PublicKey, error) { privateKey, err := sm2.GenerateKey(rand.Reader) if err != nil { return nil, nil, err } return privateKey, &privateKey.PublicKey, nil } func sm2Encrypt(publicKey *sm2.PublicKey, plaintext []byte) ([]byte, error) { return sm2.Encrypt(publicKey, plaintext, rand.Reader, sm2.C1C3C2) } func sm2Decrypt(privateKey *sm2.PrivateKey, ciphertext []byte) ([]byte, error) { return sm2.Decrypt(privateKey, ciphertext, sm2.C1C3C2) } // SM2 签名(原始形式返回 r,s) func sm2SignRaw(privateKey *sm2.PrivateKey, message []byte) (*big.Int, *big.Int, error) { defaultUID := []byte("1234567812345678") // 国密标准默认 UID return sm2.Sm2Sign(privateKey, message, defaultUID, rand.Reader) } // SM2签名(返回 64 字节格式) func sm2Sign(privateKey *sm2.PrivateKey, message []byte) ([]byte, error) { r, s, err := sm2SignRaw(privateKey, message) if err != nil { return nil, err } // 将 r 和 s 转换为固定长度字节(各 32 字节) rBytes := r.Bytes() sBytes := s.Bytes() signature := make([]byte, 64) copy(signature[32-len(rBytes):32], rBytes) copy(signature[64-len(sBytes):64], sBytes) return signature, nil } // SM2 验签(接受 r,s 原始形式) func sm2VerifyRaw(publicKey *sm2.PublicKey, message []byte, r, s *big.Int) bool { defaultUID := []byte("1234567812345678") return sm2.Sm2Verify(publicKey, message, defaultUID, r, s) } // SM2 验签(接受 64 字节签名) func sm2Verify(publicKey *sm2.PublicKey, message, signature []byte) bool { if len(signature) != 64 { return false } r := new(big.Int).SetBytes(signature[:32]) s := new(big.Int).SetBytes(signature[32:]) return sm2VerifyRaw(publicKey, message, r, s) }
算法 | 密钥长度 | 说明 |
---|---|---|
RSA | 2048/4096 位 | 基于大整数分解难题(两个大素数相乘很容易,对乘积进行因式分解极其困难); 加密速度慢于对称加密 1000 倍 |
DSA | 2048/3072 位 | 基于离散对数难题;生成密钥对速度比 RSA 快,但签名速度比 RSA 慢;主要用于数字签名 |
ECC | 256/384 位 | 基于椭圆曲线上点的离散对数问题;相同安全强度下密钥更短(256 位 ECC ≈ 3072 位 RSA );适合移动 IoT 等资源受限场景 |
SM2 | 256 位 | 基于 ECC ,中国商用密码标准;256 位 SM2 密码强度相当于 2048 位 RSA ;运算速度快于 RSA |
4.3 哈希算法
-
MD5(Message Digest)
:MD5
是一种广泛使用的哈希函数,将输入数据映射为128
位的哈希值。然而,MD5
已被发现存在碰撞漏洞,不再推荐用于安全敏感的应用。func computeMD5(data []byte) string { hash := md5.New() hash.Write(data) return hex.EncodeToString(hash.Sum(nil)) }
-
SHA-1(Secure Hash Algorithm)
:SHA-1
是另一种常见的哈希函数,产生160
位的哈希值。虽然SHA-1
比MD5
更安全,但也有研究表明其可能存在碰撞风险,因此逐渐被SHA-2
和SHA-3
取代。 -
SHA-2
:SHA-2
是一组哈希函数,包括SHA-256
、SHA-384
和SHA-512
等,分别产生256
位、384
位和512
位的哈希值。SHA-2
目前被认为是安全的,广泛应用于各种安全应用中。func computeSHA256(data []byte) string { hash := sha256.New() hash.Write(data) return hex.EncodeToString(hash.Sum(nil)) }
-
SHA-3
:SHA-3
是最新一代的哈希函数,基于Keccak
算法,提供了与SHA-2
相同的安全级别,但采用了不同的设计结构。SHA-3
旨在作为SHA-2
的后继,提供更强的安全性。 -
SM3
:SM3
适用于商用密码应用中的数字签名和验证,是在SHA-256
基础上改进实现的一种算法,其安全性和SHA-256
相当。SM3
和MD5
的迭代过程类似,也采用Merkle-Damgard
结构。消息分组长度为512
位,摘要值长度为256
位。import ( "github.com/tjfoc/gmsm/sm3" ) func computeSM3(data []byte) string { hash := sm3.New() hash.Write(data) return hex.EncodeToString(hash.Sum(nil)) }
算法 | 输出长度 | 说明 |
---|---|---|
MD5 | 32 位 | 存在碰撞漏洞,不再推荐使用 |
SHA-1 | 160 位 | 存在碰撞风险,逐渐被 SHA-2 取代 |
SHA-2 | 256/384/512 位 | 安全(比特币挖矿核心算法) |
SHA-3 | 224/256/384/512 位 | 最新 NIST 标准,抗量子计算特性 |
SM3 | 256 位 | 中国商用标准 |
4.4 消息认证码
MAC(Message Authentication Code)
,消息认证码结合了加密和哈希函数,用于验证消息的完整性和来源的真实性。常见的 MAC
算法包括 HMAC
(基于哈希的 MAC
)和 UMAC
(通用 MAC
)等。
HMAC
是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code
),HMAC
运算利用哈希算法(MD5
、SHA1
等),以一个密钥和一个消息为输入,生成一个消息摘要作为输出。
HMAC
使用发送方和接收方都有的 key
进行计算,而没有这把 key
的第三方,则是无法计算出正确的散列值的,这样就可以防止数据被篡改。
import (
"golang.org/x/crypto/poly1305"
)
// ================== HMAC ==================
// computeHMAC 计算 HMAC 值
func computeHMAC(hashFunc func() hash.Hash, key, message []byte) string {
mac := hmac.New(hashFunc, key)
mac.Write(message)
return hex.EncodeToString(mac.Sum(nil))
}
// verifyHMAC 验证 HMAC 值
func verifyHMAC(hashFunc func() hash.Hash, key, message []byte, expectedMAC string) bool {
actualMAC := computeHMAC(hashFunc, key, message)
return hmac.Equal([]byte(actualMAC), []byte(expectedMAC))
}
// ================== UMAC (使用 Poly1305 实现) ==================
// computeUMAC 计算 UMAC (使用 Poly1305 作为示例实现)
func computeUMAC(key, message []byte) (string, error) {
if len(key) != 32 {
return "", fmt.Errorf("UMAC key must be 32 bytes long")
}
var keyArray [32]byte
copy(keyArray[:], key)
var mac [16]byte
poly1305.Sum(&mac, message, &keyArray)
return hex.EncodeToString(mac[:]), nil
}
// verifyUMAC 验证 UMAC
func verifyUMAC(key, message []byte, expectedMAC string) (bool, error) {
computedMAC, err := computeUMAC(key, message)
if err != nil {
return false, err
}
return computedMAC == expectedMAC, nil
}
五、应用场景与实践
-
网络通信安全:在互联网通信中,加密技术用于保护数据的机密性和完整性。例如,
HTTPS
协议使用TLS/SSL
协议进行加密通信,确保用户与网站之间的数据传输安全。TLS/SSL
协议结合了非对称加密、对称加密和哈希函数,提供了端到端的加密通信。HTTPS
通信简化流程:- 客户端发起
SSL
握手请求 - 服务端返回
RSA/ECC
公钥 - 客户端生成临时会话密钥(如
AES-256
),用公钥加密后传输 - 双方使用对称密钥加密通信数据
- 客户端发起
-
数据存储安全:在数据存储方面,加密技术用于保护敏感数据,如密码、个人身份信息等。例如,许多操作系统和文件系统提供了加密功能,允许用户加密文件和文件夹,防止未授权访问。此外,数据库加密也是保护敏感数据的重要手段,它可以防止未经授权的用户访问数据库中的敏感信息。
-
数字签名与身份验证:数字签名是验证消息来源和完整性的有效方法。在电子邮件和软件分发中,数字签名被广泛使用,以确保消息或软件的来源真实可靠。例如,
PGP
(Pretty Good Privacy
)是一个用于加密和签名电子邮件的软件,它使用RSA
或DSA
算法进行数字签名,确保邮件的完整性和真实性;并用AES
对邮件正文进行加密。 -
密码存储与验证:在密码存储方面,加密技术用于保护用户密码的安全。传统的做法是将密码存储为明文,这存在严重的安全隐患。现代系统通常使用哈希函数和盐值(
salt
)来存储密码,确保即使数据库被泄露,攻击者也无法直接获取用户的明文密码。例如,bcrypt
是一种密码哈希算法,它使用慢哈希函数和盐值来保护密码,防止暴力破解和彩虹表攻击(盐(Salt
)在密码学中,是指通过在密码任意固定位置插入特定的字符串,让哈希后的结果和使用原始密码的哈希结果不相符,这种过程称之为 “加盐”)。 -
微信《电商类小程序结算周期变更通知》回调报文案例:
-
微信支付平台公钥验签(
RSA
):https://pay.weixin.qq.com/doc/v3/merchant/4013053420{ "id": "0ce9eec0-be84-53cd-b0b8-0cadcae96e20", "create_time": "2025-05-12T16:15:10+08:00", "resource_type": "encrypt-resource", "event_type": "MERCHANT_NOTIFY.NOTIFY", "summary": "订阅消息", "resource": { "original_type": "merchant_notify", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "wUMcIAkDIq4jiuS/5jTrtFfdomvbYIX7R8gfF1dgAJBi8htAYsjBm/I5vRaJ80Y+cEBn9/upYFA8LPatkY/uxEuOL/HrSyFo4wvCSH63RFMqUnpbRYki7NiStJsTyzRthkaK2zoyeWH+3xcxVjm/c/05yobLNA1C3Vh41g4CdDBx+eHEOAmBpa8SV9NHcbNzTSOvigOAOHlpFMu6V0NWPTgpQcV7oVM7lv76YWZfujmXKuV/y/lddcnX3irOePywaMjFtbb83q4NcmF1Wu7YIyyy0utiqcACgj+OdekGDqW02skpnLyeKZhJ0u5ptQNPMq6mewUwccJ8KN5eOfwTW9hzlQNB2iDunTaduZcIESq/FRupLRIt+ypTY9QzZqMMap8P2ELEjuMJfBz50tij7KwyxsCUcjY7//EVqRRsb2bnBsXw6jPQNbYZN8oIC03CzUiIfzolJBmDZy++gOpWi3rwxqm/", "associated_data": "merchant_notify", "nonce": "qfFLtAsgTxyd" } }
// 读取请求体内容 bytes, err := io.ReadAll(ctx.Request.Body) if err != nil { doFailed(ctx, "读取请求体内容失败", err, "") return } defer ctx.Request.Body.Close() global.ZapLogger.Info("wxmp: request body content", zap.String("reqBody", string(bytes))) // 签名验证,详见:https://pay.weixin.qq.com/doc/v3/merchant/4013053420 validHeaderCount := 3 headers := ctx.Request.Header for key, values := range headers { for _, value := range values { global.ZapLogger.Info("wxmp: callback header", zap.String("key", key), zap.String("val", value)) } if key == constants.HeaderWechatPayTimestamp || key == constants.HeaderWechatPayNonce || key == constants.HeaderWechatPaySignature { validHeaderCount-- } } if validHeaderCount > 0 { doFailed(ctx, "请求头缺失必要验签字段", fmt.Errorf("Wechatpay-Timestamp,Wechatpay-Signature,Wechatpay-Nonce needed"), "") return } needSignStr := fmt.Sprintf("%s\n%s\n%s\n", headers[constants.HeaderWechatPayTimestamp][0], headers[constants.HeaderWechatPayNonce][0], string(bytes), ) err = cipher.VerifyWechatPaySignature(needSignStr, headers[constants.HeaderWechatPaySignature][0], global.AppCfg.WXMP.VerifyPublicKeyFilePath) if err != nil { doFailed(ctx, "微信订阅消息验签失败", err, "") return } // VerifyWechatPaySignature 验证微信支付签名 // needSignStr: 需要验签的字符串 // signature: Base64 编码的签名 // publicKeyPath: 微信支付平台公钥文件路径 func VerifyWechatPaySignature(needSignStr, signature, publicKeyPath string) (err error) { // 1. 加载公钥 if global.WechatRSAPublicKey == nil { global.WechatRSAPublicKey, err = loadPublicKeyFromCert(publicKeyPath) if err != nil { return } } // 2. Base64 解码签名 decodedSignature, err := base64.StdEncoding.DecodeString(signature) if err != nil { return } // 3. 计算 needSignStr 的 SHA-256 哈希 hashed := sha256.Sum256([]byte(needSignStr)) // 4. 签名验证 err = rsa.VerifyPKCS1v15(global.WechatRSAPublicKey, crypto.SHA256, hashed[:], decodedSignature) if err != nil { return } return }
-
使用
APIv3
密钥解密报文(AES-256-GCM
):https://pay.weixin.qq.com/doc/v3/merchant/4012071382// 解密前 { "original_type": "merchant_notify", "algorithm": "AEAD_AES_256_GCM", "ciphertext": "wUMcIAkDIq4jiuS/5jTrtFfdomvbYIX7R8gfF1dgAJBi8htAYsjBm/I5vRaJ80Y+cEBn9/upYFA8LPatkY/uxEuOL/HrSyFo4wvCSH63RFMqUnpbRYki7NiStJsTyzRthkaK2zoyeWH+3xcxVjm/c/05yobLNA1C3Vh41g4CdDBx+eHEOAmBpa8SV9NHcbNzTSOvigOAOHlpFMu6V0NWPTgpQcV7oVM7lv76YWZfujmXKuV/y/lddcnX3irOePywaMjFtbb83q4NcmF1Wu7YIyyy0utiqcACgj+OdekGDqW02skpnLyeKZhJ0u5ptQNPMq6mewUwccJ8KN5eOfwTW9hzlQNB2iDunTaduZcIESq/FRupLRIt+ypTY9QzZqMMap8P2ELEjuMJfBz50tij7KwyxsCUcjY7//EVqRRsb2bnBsXw6jPQNbYZN8oIC03CzUiIfzolJBmDZy++gOpWi3rwxqm/", "associated_data": "merchant_notify", "nonce": "qfFLtAsgTxyd" } // 解密后 { "message_content": { "merchant_code": "781314402", "merchant_company_name": "陕西国钢有限公司", "business_time": "2020-02-19T18:21:31+08:00", "business_code": "wx31f2346bffb82bdf", "business_state": "ADJUSTED" }, "topic_name": { "topic_english_name": "SettleCycleByAppid", "topic_chinese_name": "电商类小程序结算周期变更通知" } }
// Decrypt 使用 AES-256-GCM 算法解密数据,加密内容先用 base64 解码 func Decrypt(ciphertext, associatedData, key, nonce string) (plaintext string, err error) { // AES-256 需要一个 32 字节长度的密钥 keyBytes := []byte(key) if len(keyBytes) != 32 { err = errors.New("key length must be 32 bytes") return } block, err := aes.NewCipher(keyBytes) if err != nil { return } // 创建 GCM 实例 aesGCM, err := cipher.NewGCM(block) if err != nil { return } // 解码密文 ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext) if err != nil { return } // 解密 plaintextBytes, err := aesGCM.Open(nil, []byte(nonce), ciphertextBytes, []byte(associatedData)) if err != nil { return } return string(plaintextBytes), nil }
-
六、算法选择指南
-
算法分类与核心用途:
算法分类 特点 典型应用 推荐算法 对称加密 加解密使用相同密钥,速度快 大数据量加密、数据库加密、实时通信 AES (128/192/256位)
:全球标准,硬件加速支持SM4
:中国商用密码标准,与AES
相当ChaCha20
:移动设备首选,比AES
更抗侧信道攻击非对称加密 公私钥分离,速度慢但无需密钥交换 密钥协商、数字签名、身份认证 RSA (2048位以上)
:兼容性最广,适合加密小数据ECC (P-256/P-384)
:同等安全下密钥更短,移动端首选SM2
:中国商用标准,基于ECC
改进哈希算法 单向不可逆,固定长度输出 数据完整性校验、密码存储、数字指纹 SHA-256/512
:通用安全哈希SM3
:中国商用标准,安全性等同SHA-256
Argon2
(密码存储专用):抗GPU/ASIC
破解消息认证码(MAC) 带密钥的哈希,验证来源和完整性 API请求验证、金融交易防篡改 HMAC-SHA256
:通用标准Poly1305 (配合ChaCha20)
:高性能场景GMAC
(GCM模式专用):加密同时认证 -
选择决策树:
是否需要... ├─ 加密大数据? → 对称加密(AES/SM4) ├─ 安全交换密钥? → 非对称加密(ECC/RSA) ├─ 验证数据完整性? → 哈希(SHA-256/SM3) └─ 验证消息来源? → MAC(HMAC/Poly1305)
-
安全等级推荐:
安全需求 推荐算法组合 基础安全 AES-128 + SHA-256 商业级 AES-256-GCM + ECC-P256 + HMAC 金融/政府 SM4-CBC + SM2 + SM3 + HMAC-SM3 超高安全 ChaCha20-Poly1305 + Ed448 -
国密算法应用场景:
SM4
:替代AES
,所有电子政务系统强制要求SM2
:替代RSA/ECC
,数字证书、VPN
身份认证SM3
:替代SHA-256
,区块链、数字签名
七、安全性分析
- 密钥管理的重要性:密钥管理是加密系统中至关重要的一环。如果密钥被泄露或丢失,加密数据的安全性将受到严重威胁。因此,密钥管理需要遵循一系列最佳实践,包括密钥生成、存储、分发和销毁等环节。例如,密钥应该使用加密随机数生成器生成,存储时应该加密,分发时应该通过安全信道,销毁时应该彻底删除,防止恢复。
- 算法强度与密钥长度:加密算法的安全性与其强度和密钥长度密切相关。一般来说,密钥长度越长,破解难度越大。例如,
AES
使用128
位密钥被认为是安全的,但对于高安全要求的场景,可能需要使用192
位或256
位密钥。同样,RSA
的密钥长度也应该足够长,目前推荐使用2048
位或更长的密钥。 - 侧信道攻击与物理安全:除了传统的密码分析攻击外,侧信道攻击也是加密系统面临的重要威胁。侧信道攻击通过分析加密设备的物理特性,如功耗、电磁辐射等,推断出密钥信息。因此,加密系统需要考虑物理安全,防止侧信道攻击。例如,硬件加密设备应该设计为抗侧信道攻击,软件加密也应该避免在内存中明文存储密钥。
八、未来发展趋势
- 后量子加密技术:随着量子计算的发展,传统的加密算法可能面临被破解的风险。量子计算机可以高效地解决大整数分解和离散对数问题,这将使
RSA
和ECC
等加密算法失效。因此,研究后量子加密技术成为当前的重要课题。后量子加密技术基于不同的数学难题,如格基密码、多变量密码、哈希基密码等,这些算法在量子计算下仍然保持安全性。例如,NIST
(美国国家标准与技术研究院)已经启动了后量子密码标准的评选工作,预计将在未来几年内确定最终标准。 - 零知识证明与隐私保护:零知识证明是一种允许一方证明自己拥有某个信息,而不必透露该信息本身的技术。它在隐私保护方面具有重要应用,例如在区块链和匿名通信中。随着对隐私保护需求的增加,零知识证明技术将得到更广泛的应用和发展。例如,
zk-SNARKs
(零知识简洁非交互式知识论证)已经在Zcash
等加密货币中使用,允许用户在不泄露交易细节的情况下验证交易的有效性。 - 区块链与加密货币:区块链和加密货币的发展也对加密技术提出了新的要求和挑战。区块链使用加密哈希和数字签名来确保交易的完整性和真实性,而加密货币如比特币和以太坊则使用密码学来保护交易和账户的安全。未来,随着区块链和加密货币的进一步发展,新的加密技术也将不断涌现,以满足这些系统的需求。例如,同态加密允许在加密数据上进行计算,这在区块链智能合约中具有重要应用。
九、结论
加密技术是保护数字世界安全的核心工具,随着技术的发展和威胁的演变,加密算法也在不断进步。从对称加密到非对称加密,从传统哈希函数到后量子加密,加密技术的发展历程体现了人类在保护信息安全方面的不懈努力。在未来的数字化社会中,加密技术将继续发挥关键作用,为我们的数据和通信提供安全保障。
十、附录
国密即国家密码局认定的国产密码算法。主要有 SM1
,SM2
,SM3
,SM4
。
SM1
为对称加密。其加密强度与AES
相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。SM2
为非对称加密,基于ECC
。该算法已公开。由于该算法基于ECC
,故其签名速度与秘钥生成速度都快于RSA
。ECC256
位安全强度比RSA2048
位高,但运算速度快于RSA
。SM3
为哈希算法。可以用MD5
作为对比理解。该算法已公开。校验结果为256
位。SM4
为对称加密,密钥长度和分组长度均为128
位,是无线局域网标准的分组数据算法。