文章:我用Java代码模拟出了德国二战的Enigma密码机加密 评语:这篇文章通过 Java 代码实现了德国二战时期 Enigma 密码机的加密过程,结构清晰明了。从介绍背景到代码还原,逐步解析了转子组、插接板以及加密方法,并通过测试验证了实现效果。内容既有技术深度,又对 Enigma 加密的原理和设计进行了直观展示,是对历史密码学与编程技术结合的有效实践总结。
AES
(Advanced Encryption Standard
,高级加密标准)是一种对称加密算法,即在加密和解密过程中使用同一个密钥。AES
算法属于分组加密算法,将数据按块处理,每块固定大小。AES
算法的核心思想是在多轮操作中对数据进行替换和置换,从而有效打乱数据,使其无法被破解。
本文将会介绍如何在 Go
语言里面实现 AES
算法的加解密操作。
准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。
AES
算法支持多种模式,每种模式对加密的数据结构和安全性都有不同的要求和应用场景。常见的 AES
模式包括 ECB
、CBC
、CFB
、OFB
和 GCM
。
代码实现
package main
import (
"bytes"
"crypto/aes"
"fmt"
)
func pkcs7Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func pkcs7Unpadding(data []byte) []byte {
length := len(data)
unpadding := int(data[length-1])
return data[:(length - unpadding)]
}
func encryptECB(plainText, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
plainText = pkcs7Padding(plainText, blockSize)
cipherText := make([]byte, len(plainText))
for start := 0; start < len(plainText); start += blockSize {
end := start + blockSize
block.Encrypt(cipherText[start:end], plainText[start:end])
}
return cipherText, nil
}
func decryptECB(cipherText, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
plainText := make([]byte, len(cipherText))
for start := 0; start < len(cipherText); start += blockSize {
end := start + blockSize
block.Decrypt(plainText[start:end], cipherText[start:end])
}
plainText = pkcs7Unpadding(plainText)
return plainText, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
fmt.Println("原始:", string(plainText))
// 加密
cipherText, err := encryptECB(plainText, key)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := decryptECB(cipherText, key)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("解密后:", string(decryptedText))
}
IV
)进行异或操作。IV
增加了随机性,能抵御模式攻击。package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
// PKCS#7 填充
func pkcs7Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
// 移除 PKCS#7 填充
func pkcs7Unpadding(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, fmt.Errorf("invalid padding size")
}
unpadding := int(data[length-1])
if unpadding > length {
return nil, fmt.Errorf("invalid padding size")
}
return data[:(length - unpadding)], nil
}
func encryptCBC(plainText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
plainText = pkcs7Padding(plainText, blockSize)
cipherText := make([]byte, len(plainText))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(cipherText, plainText)
return cipherText, nil
}
func decryptCBC(cipherText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(cipherText)%blockSize != 0 {
return nil, fmt.Errorf("ciphertext is not a multiple of the block size")
}
plainText := make([]byte, len(cipherText))
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(plainText, cipherText)
return pkcs7Unpadding(plainText)
}
func generateIV(blockSize int) ([]byte, error) {
iv := make([]byte, blockSize)
_, err := io.ReadFull(rand.Reader, iv)
if err != nil {
return nil, err
}
return iv, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
fmt.Println("原始:", string(plainText))
// 生成随机 IV
iv, err := generateIV(aes.BlockSize)
if err != nil {
fmt.Println("Error generating IV:", err)
return
}
fmt.Printf("IV (hex): %x\n", iv)
// 加密
cipherText, err := encryptCBC(plainText, key, iv)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := decryptCBC(cipherText, key, iv)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("解密后:", string(decryptedText))
}
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func encryptCFB(plainText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cipherText := make([]byte, len(plainText))
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(cipherText, plainText)
return cipherText, nil
}
func decryptCFB(cipherText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
plainText := make([]byte, len(cipherText))
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(plainText, cipherText)
return plainText, nil
}
func generateIV(blockSize int) ([]byte, error) {
iv := make([]byte, blockSize)
_, err := io.ReadFull(rand.Reader, iv)
if err != nil {
return nil, err
}
return iv, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
fmt.Println("原始:", string(plainText))
// 生成随机 IV
iv, err := generateIV(aes.BlockSize)
if err != nil {
fmt.Println("Error generating IV:", err)
return
}
fmt.Printf("IV (hex): %x\n", iv)
// 加密
cipherText, err := encryptCFB(plainText, key, iv)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := decryptCFB(cipherText, key, iv)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("加密:", string(decryptedText))
}
IV
或上一个密钥流块加密得到一个新的密钥块,然后将其与明文异或生成密文。CFB
类似,可用作流加密,且不会在密文中传播错误。package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func encryptOFB(plainText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cipherText := make([]byte, len(plainText))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(cipherText, plainText)
return cipherText, nil
}
func decryptOFB(cipherText, key, iv []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
plainText := make([]byte, len(cipherText))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(plainText, cipherText)
return plainText, nil
}
func generateIV(blockSize int) ([]byte, error) {
iv := make([]byte, blockSize)
_, err := io.ReadFull(rand.Reader, iv)
if err != nil {
return nil, err
}
return iv, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
fmt.Println("原始:", string(plainText))
// 生成随机 IV
iv, err := generateIV(aes.BlockSize)
if err != nil {
fmt.Println("Error generating IV:", err)
return
}
fmt.Printf("IV (hex): %x\n", iv)
// 加密
cipherText, err := encryptOFB(plainText, key, iv)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := decryptOFB(cipherText, key, iv)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("加密:", string(decryptedText))
}
Counter
)值加密生成密钥流,与明文块异或得到密文。package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func encryptCTR(plainText, key, nonce []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cipherText := make([]byte, len(plainText))
stream := cipher.NewCTR(block, nonce)
stream.XORKeyStream(cipherText, plainText)
return cipherText, nil
}
func generateNonce(blockSize int) ([]byte, error) {
nonce := make([]byte, blockSize)
_, err := io.ReadFull(rand.Reader, nonce)
if err != nil {
return nil, err
}
return nonce, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
fmt.Println("原始:", string(plainText))
// 生成随机 Nonce
nonce, err := generateNonce(aes.BlockSize)
if err != nil {
fmt.Println("Error generating nonce:", err)
return
}
fmt.Printf("Nonce (hex): %x\n", nonce)
// 加密
cipherText, err := encryptCTR(plainText, key, nonce)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := encryptCTR(cipherText, key, nonce) // CTR 解密与加密相同
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("解密:", string(decryptedText))
}
CTR
模式基础上加入认证功能,通过加密和认证来确保数据的机密性和完整性。HTTPS
、VPN。
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func encryptGCM(plainText, key, nonce, aad []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
cipherText := gcm.Seal(nil, nonce, plainText, aad)
return cipherText, nil
}
func decryptGCM(cipherText, key, nonce, aad []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
plainText, err := gcm.Open(nil, nonce, cipherText, aad)
if err != nil {
return nil, err
}
return plainText, nil
}
func generateNonce(size int) ([]byte, error) {
nonce := make([]byte, size)
_, err := io.ReadFull(rand.Reader, nonce)
if err != nil {
return nil, err
}
return nonce, nil
}
func main() {
key := []byte("1234567890123456") // 16 字节密钥
plainText := []byte("陈明勇")
aad := []byte("Additional Data") // 附加认证数据(可选)
fmt.Println("原始:", string(plainText))
// 生成随机 Nonce
nonce, err := generateNonce(12) // GCM 推荐使用 12 字节 Nonce
if err != nil {
fmt.Println("Error generating nonce:", err)
return
}
fmt.Printf("Nonce (hex): %x\n", nonce)
// 加密
cipherText, err := encryptGCM(plainText, key, nonce, aad)
if err != nil {
fmt.Println("Error encrypting:", err)
return
}
fmt.Printf("加密后 (hex): %x\n", cipherText)
// 解密
decryptedText, err := decryptGCM(cipherText, key, nonce, aad)
if err != nil {
fmt.Println("Error decrypting:", err)
return
}
fmt.Println("解密:", string(decryptedText))
}
本文简要介绍了 AES
算法的多种加密模式,并提供了对应的加解密实现代码,涵盖了以下模式:
每种模式各有特点,适用于不同的应用场景。选择加密模式时,应根据具体需求考虑性能、安全性、错误容忍度以及是否需要认证功能,合理选用适配的加密模式以满足实际需求。
你好,我是陈明勇,一名热爱技术、乐于分享的开发者,同时也是开源爱好者。
成功的路上并不拥挤,有没有兴趣结个伴?
关注我,加我好友,一起学习一起进步!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。