跳到主要内容

文件加解密

关于

加密解密在实际开发中应用比较广泛,有如下几种。

项目对称加密非对称加密校验算法
特点加解密都使用的是同一个密钥采用密钥对,加解密使用不同的密钥用于验证,防止信息被修改
信息存储密文存储信息密文存储信息密文不存储信息
代表算法AES、DES/3DESRSA、DSA、ECDSAMD5、SHA、HMAC
经典应用场景- 普通文件加密
- 大数据块文件加密
- bit流加密
- 远程登录
- 加密货币
- 小块数据加密
- 数字签名/证书
- SSL/TLS协议
文件校验
数字签名
鉴权协议
其它算力开支大
提示
  • Base64不是加密算法,它是一种数据编码方式,它的编码方式是公开的,无所谓加密。
  • 大文件加密
    一个常见的做法是使用对称加密算法(如AES)来加密文件,然后使用非对称加密算法加密对称密钥。这样,你可以安全地传输对称密钥,并在需要时解密和访问文件。

aes的gcm模式的加密和解密

在文件加密方面,aes的gcm模式是比较常用的,安全系数更高。
此类模式的核心注意点如下

  • 加解密使用的随机初始化量nonce必须相同
  • nonce的长度必须等于gcm.NonceSize()
  • aes加解密使用的公共key必须相同

被加密文件test.json

test.json
{
"CN":"Root-CA",
"key":{
"algo":"rsa",
"size":2048
},
"names":[
{
"C":"CN",
"L":"Gudong",
"ST":"shenzhen",
"O":"k8s",
"OU":"System"
}
]
}

测试代码如下

test.go
package main

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"fmt"
"log"
"os"
)

func main() {

//被加密的文本
var fileName = "./test.json"
plaintext := fileLoad(fileName)
//plaintext := "这是一个需要加密的文本字符串,长度不限"
fmt.Printf("原文:\n%v\nLen:%d\nsha256:%x\n\n",plaintext,len(plaintext),sha256.Sum256([]byte(plaintext)))

//创建随机的初始化量nonce
nonceBlock := generateRandomString(12)
//fmt.Printf("nonce:%x\nlen:%d\n\n",nonceBlock,len(nonceBlock))

//aesKEY必须是16或24或32位的字符串,分别对应AES-128,AES-192,AES-256 加密方法
aesKEY := generateRandomString(32)
//fmt.Printf("aesKEY:%x\nlen:%d\n\n",aesKEY,len(aesKEY))

//密文
encryptedText := encrypt(plaintext, nonceBlock, aesKEY)
fmt.Printf("加密后的密文:\n%x\n\n", base64.StdEncoding.EncodeToString(encryptedText))

// 解密文本
decryptedText := decrypt(encryptedText, nonceBlock, aesKEY)
fmt.Printf("解密后的文本:\n%v\nLen:%d\nsha256:%x\n\n",decryptedText,len(decryptedText),sha256.Sum256([]byte(decryptedText)))
}

//装入指定的文件
func fileLoad(filename string) (string) {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
fileContext := new(bytes.Buffer)
fileContext.ReadFrom(file)
return fileContext.String()
}

//创建指定字节数量的随机数
func generateRandomString(length int) []byte {
b := make([]byte, length)
_, err := rand.Read(b)
if err != nil {
log.Fatal("Failed to generate random string:", err)
}

// 将随机字节转换为字符串
return b
}

//加密
func encrypt(plaintext string,iv []byte,key []byte) []byte {
// 使用AES-256-GCM加密算法
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}

// 使用GCM模式进行加密
gcm, err := cipher.NewGCM(block)
if err != nil {
panic(err)
}

// 加密明文
cipherText := gcm.Seal(nil, iv, []byte(plaintext), nil)
return cipherText
}


//解密
func decrypt(ciphertext []byte, iv []byte,key []byte) string {
// 使用AES-256-GCM加密算法
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}

// 创建一个新的GCM实例
gcm, err := cipher.NewGCM(block)
if err != nil {
panic(err)
}

// 解密密文
plaintext, err := gcm.Open(nil, iv, ciphertext, nil)
if err != nil {
panic(err)
}

return string(plaintext)
}

运行

# go run test.go   # 输出如下
原文:
{
"CN":"Root-CA",
"key":{
"algo":"rsa",
"size":2048
},
"names":[
{
"C":"CN",
"L":"Gudong",
"ST":"shenzhen",
"O":"k8s",
"OU":"System"
}
]
}
Len:265
sha256:62b6a7461c78a3368c21d8cafa1276e53e44ad78cf3928e26f9ab57e263c9580

加密后的密文:
496d2f4e495955372b4b46466568593574564b5841622f494557357066647457706a34736c4d63376f735368624f6b5a56713177546557577677362f6c552b30316f6f43665370696e5547464442744d43376735773238462b4d72686f6c4a576b3050576644657a7736622f31542b6278667a662b652b46576d364a383270435879643739766e30435072386a555a3875366e6e47586d6a2f724d485243776f4a4259784849566f476263646d717363677a4e55357a53437268666d61766b53647a6a75735679654c647a6246706744455841326e67384f74315462597976484476413470476f4c546378477a4445504f697a6b7244684853696c5966576452303534673832424a3472706a437438666778684a526d44796b4652762f6149534e724c61753055344573493476426641597752656f703335774b6a415736424f6f4e2b387248453332576c514444504c556e465554796758594338425155614d7063462b3135574d4556654d794b636e673232593871773d

解密后的文本:
{
"CN":"Root-CA",
"key":{
"algo":"rsa",
"size":2048
},
"names":[
{
"C":"CN",
"L":"Gudong",
"ST":"shenzhen",
"O":"k8s",
"OU":"System"
}
]
}
Len:265
sha256:62b6a7461c78a3368c21d8cafa1276e53e44ad78cf3928e26f9ab57e263c9580

可以看出,加密前后的sha256校验码是一样的,加解密成功。