package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"fmt"
)
// main 入口函數
func main() {
// DES密鑰
key := "12345678" // 占8字節
// 3DES密鑰
// key = "abcdefgh0123456712345678" //占24字節
// AES密鑰 key長度 16 24 32 對應 AES-128 AES-192 AES-256
// key = "abcdefgh0123456712345678" //占24字節
data := "學習技術,改變世界"
chipherArr, err := SCEncryptString(data, key, "des")
if err != nil {
panic(err)
}
fmt.Printf("加密后字節數組:%v\n", chipherArr)
fmt.Printf("加密后16進制:%x\n", chipherArr)
originalBytes, err := SCDecryptString(chipherArr, key, "des")
if err != nil {
panic(err)
}
fmt.Println("解密后:", string(originalBytes))
}
// SCEncrypt DES加密
func SCEncrypt(originalBytes, key []byte, scType string) ([]byte, error) {
// 1、實例化密碼器block(參數為密鑰)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
fmt.Println("---blockSize---", blockSize)
// 2、對明文填充字節(參數為原始字節切片和密碼對象的區塊個數)
paddingBytes := PKCSSPadding(originalBytes, blockSize)
fmt.Println("填充后的字節切片:", paddingBytes)
// 3、 實例化加密模式(參數為密碼對象和密鑰)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
fmt.Println("加密模式:", blockMode)
// 4、對填充字節后的明文進行加密(參數為加密字節切片和填充字節切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
// SCDecrypt 解密字節切片,返回字節切片
func SCDecrypt(cipherBytes, key []byte, scType string) ([]byte, error) {
// 1、實例化密碼器block(參數為密鑰)
var err error
var block cipher.Block
switch scType {
case "des":
block, err = des.NewCipher(key)
case "3des":
block, err = des.NewTripleDESCipher(key)
case "aes":
block, err = aes.NewCipher(key)
}
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、 實例化解密模式(參數為密碼對象和密鑰)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// fmt.Println("解密模式:", blockMode)
// 3、對密文進行解密(參數為加密字節切片和填充字節切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充字節(參數為填充切片)
originalBytes := PKCSSUnPadding(paddingBytes)
return originalBytes, nil
}
// SCEncryptString SCEncryptString
func SCEncryptString(originalText, key, scType string) (string, error) {
chipherArr, err := SCEncrypt([]byte(originalText), []byte(key), scType)
if err != nil {
panic(err)
}
base64str := base64.StdEncoding.EncodeToString(chipherArr)
return base64str, nil
}
// SCDecryptString SCDecryptString
func SCDecryptString(chipherText, key, scType string) (string, error) {
chipherArr, _ := base64.StdEncoding.DecodeString(chipherText)
chipherArr, err := SCDecrypt(chipherArr, []byte(key), scType)
if err != nil {
panic(err)
}
return string(chipherArr), nil
}
// PKCSSPadding 填充字節的函數
func PKCSSPadding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
fmt.Println("要填充的字節:", padding)
// 初始化一個元素為padding的切片
slice1 := []byte{byte(padding)}
slice2 := bytes.Repeat(slice1, padding)
return append(data, slice2...)
}
// ZeroPadding 填充字節的函數
func ZeroPadding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
fmt.Println("要填充的字節:", padding)
// 初始化一個元素為padding的切片
slice1 := []byte{0}
slice2 := bytes.Repeat(slice1, padding)
return append(data, slice2...)
}
// PKCSSUnPadding 去除填充字節的函數
func PKCSSUnPadding(data []byte) []byte {
unpadding := data[len(data)-1]
result := data[:(len(data) - int(unpadding))]
return result
}
// ZeroUnPadding 去除填充字節的函數
func ZeroUnPadding(data []byte) []byte {
return bytes.TrimRightFunc(data, func(r rune) bool {
return r == 0
})
}