Go語言實(shí)現(xiàn)對(duì)稱加密和非對(duì)稱加密的示例代碼
對(duì)稱加密和非對(duì)稱加密的區(qū)別主要有以下幾個(gè)方面:
1、密鑰的使用:對(duì)稱加密中,加密和解密使用的是同一個(gè)密鑰,而非對(duì)稱加密則使用兩個(gè)不同的密鑰,一般
使用公鑰進(jìn)行加密,私鑰進(jìn)行解密。
2、速度和效率:對(duì)稱加密解密的速度比較快,適合數(shù)據(jù)比較長時(shí)的使用,而非對(duì)稱加密和解密花費(fèi)的時(shí)間
長、速度相對(duì)較慢,只適合對(duì)少量數(shù)據(jù)的使用。
3、安全性:對(duì)稱加密的安全性相對(duì)較低,因?yàn)橥ㄐ烹p方使用相同的秘鑰,如果一方的秘鑰遭泄露,那么整個(gè)
通信就會(huì)被破解。而非對(duì)稱加密使用一對(duì)秘鑰,一個(gè)用來加密,一個(gè)用來解密,而且公鑰是公開的,私鑰是自
己保存的,不需要像對(duì)稱加密那樣在通信之前要先同步秘鑰,因此其安全性更好。
4、密鑰分發(fā):在對(duì)稱加密中,需要在通信雙方之間安全地共享密鑰。如果沒有安全的通道來共享密鑰,可能
會(huì)被黑客截獲,導(dǎo)致數(shù)據(jù)泄露。而非對(duì)稱加密則不需要在通信之前共享密鑰,因此更加安全。
在實(shí)際應(yīng)用中,對(duì)稱加密和非對(duì)稱加密經(jīng)常結(jié)合使用,以充分發(fā)揮它們各自的優(yōu)點(diǎn)。例如,可以使用對(duì)稱加密來加
密大量數(shù)據(jù),然后使用非對(duì)稱加密來安全地分發(fā)對(duì)稱加密的密鑰。
1、對(duì)稱加密
1.1 AES
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
// AES加密
func main() {
// AES加密占16、24或32字節(jié)
key := "12345678abcdefgh"
// 加密的字符串
str := "hello world!"
fmt.Println("加密前的字符串:", str)
cipherText, _ := SCEncryptString(str, key)
fmt.Println("加密后的字符串:", cipherText)
originalText, _ := SCDecryptString(cipherText, key)
fmt.Println("解密后的字符串:", originalText)
}
// 對(duì)稱加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、對(duì)明文進(jìn)行填充(參數(shù)為原始字節(jié)切片和密碼對(duì)象的區(qū)塊個(gè)數(shù))
paddingBytes := PKCS5Padding(originalBytes, blockSize)
// 3、實(shí)例化加密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 4、對(duì)填充字節(jié)后的明文進(jìn)行加密(參數(shù)為加密字節(jié)切片和填充字節(jié)切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
// 對(duì)稱解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、實(shí)例化解密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 3、對(duì)密文進(jìn)行解密(參數(shù)為填充字節(jié)切片和加密字節(jié)切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充的字節(jié)(參數(shù)為填充切片)
originalBytes := PKCS5UnPadding(paddingBytes)
return originalBytes, nil
}
// 封裝字符串對(duì)稱加密
func SCEncryptString(originalText, key string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key))
if err != nil {
return "", err
}
// base64編碼(encoded)
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
// 封裝字符串對(duì)稱解密
func SCDecryptString(cipherText, key string) (string, error) {
// base64解碼(decode)
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key))
if err != nil {
return "", err
}
return string(cipherBytes), nil
}
// 末尾填充字節(jié)
func PKCS5Padding(data []byte, blockSize int) []byte {
// 要填充的值和個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)二進(jìn)制值
slice1 := []byte{byte(padding)}
// 要填充的二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
// 要填充的個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)0數(shù)據(jù)
slice1 := []byte{0}
// 要填充的0二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 去除填充的字節(jié)
func PKCS5UnPadding(data []byte) []byte {
// 獲取二進(jìn)制數(shù)組最后一個(gè)數(shù)值
unpadding := data[len(data)-1]
// 截取開始至總長度減去填充值之間的有效數(shù)據(jù)
result := data[:(len(data) - int(unpadding))]
return result
}
// 去除填充的0
func ZerosUnPadding(data []byte) []byte {
// 去除滿足條件的子切片
return bytes.TrimRightFunc(data, func(r rune) bool {
return r == 0
})
}
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
// AES加密
// AES加密占16、24或32字節(jié)
var encryptionKey = []byte("12345678abcdefgh")
func encrypt(data []byte) (string, error) {
block, err := aes.NewCipher(encryptionKey)
if err != nil {
return "", err
}
ciphertext := make([]byte, aes.BlockSize+len(data))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], data)
return base64.URLEncoding.EncodeToString(ciphertext), nil
}
func decrypt(encodedData string) ([]byte, error) {
ciphertext, err := base64.URLEncoding.DecodeString(encodedData)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
if len(ciphertext) < aes.BlockSize {
return nil, fmt.Errorf("加密數(shù)據(jù)長度無效")
}
iv := ciphertext[:aes.BlockSize]
ciphertext = ciphertext[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
return ciphertext, nil
}
func main() {
data := []byte("Hello World!")
encryptedData, err := encrypt(data)
if err != nil {
fmt.Println("加密失敗:", err)
return
}
fmt.Println("加密后的數(shù)據(jù):", encryptedData)
decryptedData, err := decrypt(encryptedData)
if err != nil {
fmt.Println("解密失敗:", err)
return
}
fmt.Println("解密后的數(shù)據(jù):", string(decryptedData))
}
1.2 DES
package main
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"fmt"
)
// DES加密
func main() {
// DES密鑰占8字節(jié)
key := "1234abcd"
// 加密的字符串
str := "hello world!"
fmt.Println("加密前的字符串:", str)
cipherText, _ := SCEncryptString(str, key)
fmt.Println("加密后的字符串:", cipherText)
originalText, _ := SCDecryptString(cipherText, key)
fmt.Println("解密后的字符串:", originalText)
}
// 對(duì)稱加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、對(duì)明文進(jìn)行填充(參數(shù)為原始字節(jié)切片和密碼對(duì)象的區(qū)塊個(gè)數(shù))
paddingBytes := PKCS5Padding(originalBytes, blockSize)
// 3、實(shí)例化加密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 4、對(duì)填充字節(jié)后的明文進(jìn)行加密(參數(shù)為加密字節(jié)切片和填充字節(jié)切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
// 對(duì)稱解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、實(shí)例化解密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 3、對(duì)密文進(jìn)行解密(參數(shù)為填充字節(jié)切片和加密字節(jié)切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充的字節(jié)(參數(shù)為填充切片)
originalBytes := PKCS5UnPadding(paddingBytes)
return originalBytes, nil
}
// 封裝字符串對(duì)稱加密
func SCEncryptString(originalText, key string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key))
if err != nil {
return "", err
}
// base64編碼(encoded)
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
// 封裝字符串對(duì)稱解密
func SCDecryptString(cipherText, key string) (string, error) {
// base64解碼(decode)
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key))
if err != nil {
return "", err
}
return string(cipherBytes), nil
}
// 末尾填充字節(jié)
func PKCS5Padding(data []byte, blockSize int) []byte {
// 要填充的值和個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)二進(jìn)制值
slice1 := []byte{byte(padding)}
// 要填充的二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
// 要填充的個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)0數(shù)據(jù)
slice1 := []byte{0}
// 要填充的0二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 去除填充的字節(jié)
func PKCS5UnPadding(data []byte) []byte {
// 獲取二進(jìn)制數(shù)組最后一個(gè)數(shù)值
unpadding := data[len(data)-1]
// 截取開始至總長度減去填充值之間的有效數(shù)據(jù)
result := data[:(len(data) - int(unpadding))]
return result
}
// 去除填充的0
func ZerosUnPadding(data []byte) []byte {
// 去除滿足條件的子切片
return bytes.TrimRightFunc(data, func(r rune) bool {
return r == 0
})
}
package main
import (
"crypto/cipher"
"crypto/des"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
// DES加密
// DES密鑰占8字節(jié)
var encryptionKey = []byte("1234abcd")
func encrypt(data []byte) (string, error) {
block, err := des.NewCipher(encryptionKey)
if err != nil {
return "", err
}
ciphertext := make([]byte, des.BlockSize+len(data))
iv := ciphertext[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[des.BlockSize:], data)
return base64.URLEncoding.EncodeToString(ciphertext), nil
}
func decrypt(encodedData string) ([]byte, error) {
ciphertext, err := base64.URLEncoding.DecodeString(encodedData)
if err != nil {
return nil, err
}
block, err := des.NewCipher(encryptionKey)
if err != nil {
return nil, err
}
if len(ciphertext) < des.BlockSize {
return nil, fmt.Errorf("加密數(shù)據(jù)長度無效")
}
iv := ciphertext[:des.BlockSize]
ciphertext = ciphertext[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
return ciphertext, nil
}
func main() {
data := []byte("Hello")
encryptedData, err := encrypt(data)
if err != nil {
fmt.Println("加密失敗:", err)
return
}
fmt.Println("加密后的數(shù)據(jù):", encryptedData)
decryptedData, err := decrypt(encryptedData)
if err != nil {
fmt.Println("解密失敗:", err)
return
}
fmt.Println("解密后的數(shù)據(jù):", string(decryptedData))
}
1.3 3DES
package main
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/base64"
"fmt"
)
// 3DES加密
func main() {
// 3DES密鑰占24字節(jié)
key := "abcdefghijklmn0123456789"
// 加密的字符串
str := "hello world!"
fmt.Println("加密前的字符串:", str)
cipherText, _ := SCEncryptString(str, key)
fmt.Println("加密后的字符串:", cipherText)
originalText, _ := SCDecryptString("3eS626HB2R9ZGcOAYLuWCw==", key)
fmt.Println("解密后的字符串:", originalText)
}
// 對(duì)稱加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、對(duì)明文進(jìn)行填充(參數(shù)為原始字節(jié)切片和密碼對(duì)象的區(qū)塊個(gè)數(shù))
paddingBytes := PKCS5Padding(originalBytes, blockSize)
// 3、實(shí)例化加密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
// 4、對(duì)填充字節(jié)后的明文進(jìn)行加密(參數(shù)為加密字節(jié)切片和填充字節(jié)切片)
cipherBytes := make([]byte, len(paddingBytes))
blockMode.CryptBlocks(cipherBytes, paddingBytes)
return cipherBytes, nil
}
// 對(duì)稱解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
// 1、實(shí)例化密碼器block(參數(shù)為密鑰)
block, err := des.NewTripleDESCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 2、實(shí)例化解密模式(參數(shù)為密碼對(duì)象和密鑰)
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
// 3、對(duì)密文進(jìn)行解密(參數(shù)為填充字節(jié)切片和加密字節(jié)切片)
paddingBytes := make([]byte, len(cipherBytes))
blockMode.CryptBlocks(paddingBytes, cipherBytes)
// 4、去除填充的字節(jié)(參數(shù)為填充切片)
originalBytes := PKCS5UnPadding(paddingBytes)
return originalBytes, nil
}
// 封裝字符串對(duì)稱加密
func SCEncryptString(originalText, key string) (string, error) {
cipherBytes, err := SCEncrypt([]byte(originalText), []byte(key))
if err != nil {
return "", err
}
// base64編碼(encoded)
base64str := base64.StdEncoding.EncodeToString(cipherBytes)
return base64str, nil
}
// 封裝字符串對(duì)稱解密
func SCDecryptString(cipherText, key string) (string, error) {
// base64解碼(decode)
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
cipherBytes, err := SCDecrypt(cipherBytes, []byte(key))
if err != nil {
return "", err
}
return string(cipherBytes), nil
}
// 末尾填充字節(jié)
func PKCS5Padding(data []byte, blockSize int) []byte {
// 要填充的值和個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)二進(jìn)制值
slice1 := []byte{byte(padding)}
// 要填充的二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
// 要填充的個(gè)數(shù)
padding := blockSize - len(data)%blockSize
// 要填充的單個(gè)0數(shù)據(jù)
slice1 := []byte{0}
// 要填充的0二進(jìn)制數(shù)組
slice2 := bytes.Repeat(slice1, padding)
// 填充到數(shù)據(jù)末端
return append(data, slice2...)
}
// 去除填充的字節(jié)
func PKCS5UnPadding(data []byte) []byte {
// 獲取二進(jìn)制數(shù)組最后一個(gè)數(shù)值
unpadding := data[len(data)-1]
// 截取開始至總長度減去填充值之間的有效數(shù)據(jù)
result := data[:(len(data) - int(unpadding))]
return result
}
// 去除填充的0
func ZerosUnPadding(data []byte) []byte {
// 去除滿足條件的子切片
return bytes.TrimRightFunc(data, func(r rune) bool {
return r == 0
})
}
package main
import (
"crypto/cipher"
"crypto/des"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
// 3DES加密
// 3DES密鑰占24字節(jié)
var encryptionKey = []byte("abcdefghijklmn0123456789")
func encrypt(data []byte) (string, error) {
block, err := des.NewTripleDESCipher(encryptionKey)
if err != nil {
return "", err
}
ciphertext := make([]byte, des.BlockSize+len(data))
iv := ciphertext[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[des.BlockSize:], data)
return base64.URLEncoding.EncodeToString(ciphertext), nil
}
func decrypt(encodedData string) ([]byte, error) {
ciphertext, err := base64.URLEncoding.DecodeString(encodedData)
if err != nil {
return nil, err
}
block, err := des.NewTripleDESCipher(encryptionKey)
if err != nil {
return nil, err
}
if len(ciphertext) < des.BlockSize {
return nil, fmt.Errorf("加密數(shù)據(jù)長度無效")
}
iv := ciphertext[:des.BlockSize]
ciphertext = ciphertext[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(ciphertext, ciphertext)
return ciphertext, nil
}
func main() {
data := []byte("Hello")
encryptedData, err := encrypt(data)
if err != nil {
fmt.Println("加密失敗:", err)
return
}
fmt.Println("加密后的數(shù)據(jù):", encryptedData)
decryptedData, err := decrypt(encryptedData)
if err != nil {
fmt.Println("解密失敗:", err)
return
}
fmt.Println("解密后的數(shù)據(jù):", string(decryptedData))
}
2、非對(duì)稱加密算法RSA
2.1 生成密鑰對(duì)
生成密鑰對(duì),分別存儲(chǔ)到公鑰文件(public.pem),私鑰文件中(private.pem)。
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"log"
"os"
)
func main() {
if err := GenerateRSAKey(); err != nil {
log.Fatal("密鑰生成失敗!")
}
log.Println("密鑰生成成功!")
}
// 生成密鑰對(duì)并保存到文件
func GenerateRSAKey() error {
// 1、RSA生成私鑰文件的核心步驟
// 1)、生成RSA密鑰對(duì)
// 密鑰長度,默認(rèn)值為1024位
bits := 1024
privateKer, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
// 2)、將私鑰對(duì)象轉(zhuǎn)換成DER編碼形式
derPrivateKer := x509.MarshalPKCS1PrivateKey(privateKer)
// 3)、創(chuàng)建私鑰pem文件
file, err := os.Create("../certs/private.pem")
if err != nil {
return err
}
// 4)、對(duì)密鑰信息進(jìn)行編碼,寫入到私鑰文件中
block := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: derPrivateKer,
}
err = pem.Encode(file, block)
if err != nil {
return err
}
// 2、RSA生成公鑰文件的核心步驟
// 1)、生成公鑰對(duì)象
publicKey := &privateKer.PublicKey
// 2)、將公鑰對(duì)象序列化為DER編碼格式
derPublicKey, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return err
}
// 3)、創(chuàng)建公鑰pem文件
file, err = os.Create("../certs/public.pem")
if err != nil {
return err
}
// 4)、對(duì)公鑰信息進(jìn)行編碼,寫入到公鑰文件中
block = &pem.Block{
Type: "PUBLIC KEY",
Bytes: derPublicKey,
}
err = pem.Encode(file, block)
if err != nil {
return err
}
return nil
}
2.2 RSA加密解密過程
公鑰加密,私鑰解密。
加密過程:
- 1、讀取公鑰文件,解析出公鑰對(duì)象
- 2、使用公鑰對(duì)明文進(jìn)行加密
解密過程:
- 1、讀取私鑰文件,解析出公鑰對(duì)象
- 2、使用私鑰對(duì)密文進(jìn)行解密
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
)
func main() {
str := "Hello World!"
encryptstr, _ := RSAEncryptString(str, "../certs/public.pem")
fmt.Println(encryptstr)
decrypt, _ := RSADecryptString(encryptstr, "../certs/private.pem")
fmt.Println(decrypt)
}
// RSA加密字節(jié)數(shù)組,返回字節(jié)數(shù)組
func RSAEncrypt(originalBytes []byte, filename string) ([]byte, error) {
// 1、讀取公鑰文件,解析出公鑰對(duì)象
publicKey, err := ReadParsePublicKey(filename)
if err != nil {
return nil, err
}
// 2、RSA加密,參數(shù)是隨機(jī)數(shù)、公鑰對(duì)象、需要加密的字節(jié)
// Reader是一個(gè)全局共享的密碼安全的強(qiáng)大的偽隨機(jī)生成器
return rsa.EncryptPKCS1v15(rand.Reader, publicKey, originalBytes)
}
// RSA解密字節(jié)數(shù)組,返回字節(jié)數(shù)組
func RSADecrypt(cipherBytes []byte, filename string) ([]byte, error) {
// 1、讀取私鑰文件,解析出私鑰對(duì)象
privateKey, err := ReadParsePrivaterKey(filename)
if err != nil {
return nil, err
}
// 2、ras解密,參數(shù)是隨機(jī)數(shù)、私鑰對(duì)象、需要解密的字節(jié)
return rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherBytes)
}
// 讀取公鑰文件,解析出公鑰對(duì)象
func ReadParsePublicKey(filename string) (*rsa.PublicKey, error) {
// 1、讀取公鑰文件,獲取公鑰字節(jié)
publicKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
// 2、解碼公鑰字節(jié),生成加密塊對(duì)象
block, _ := pem.Decode(publicKeyBytes)
if block == nil {
return nil, errors.New("公鑰信息錯(cuò)誤!")
}
// 3、解析DER編碼的公鑰,生成公鑰接口
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
// 4、公鑰接口轉(zhuǎn)型成公鑰對(duì)象
publicKey := publicKeyInterface.(*rsa.PublicKey)
return publicKey, nil
}
// 讀取私鑰文件,解析出私鑰對(duì)象
func ReadParsePrivaterKey(filename string) (*rsa.PrivateKey, error) {
// 1、讀取私鑰文件,獲取私鑰字節(jié)
privateKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
// 2、對(duì)私鑰文件進(jìn)行編碼,生成加密塊對(duì)象
block, _ := pem.Decode(privateKeyBytes)
if block == nil {
return nil, errors.New("私鑰信息錯(cuò)誤!")
}
// 3、解析DER編碼的私鑰,生成私鑰對(duì)象
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return privateKey, nil
}
// RSA加密字符串,返回base64處理的字符串
func RSAEncryptString(originalText, filename string) (string, error) {
cipherBytes, err := RSAEncrypt([]byte(originalText), filename)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(cipherBytes), nil
}
// RSA解密經(jīng)過base64處理的加密字符串,返回加密前的明文
func RSADecryptString(cipherlText, filename string) (string, error) {
cipherBytes, _ := base64.StdEncoding.DecodeString(cipherlText)
originalBytes, err := RSADecrypt(cipherBytes, filename)
if err != nil {
return "", err
}
return string(originalBytes), nil
}
2.3 數(shù)字簽名驗(yàn)證
加密與簽名的區(qū)別:
- 加密:公鑰加密,私鑰解密
- 簽名:私鑰簽名,公鑰驗(yàn)證
數(shù)字簽名過程:
- 原文的哈希值用自己私鑰簽名,原文+簽名給對(duì)方,對(duì)方用公鑰驗(yàn)證簽名時(shí)與原文哈希比對(duì)。
加密并簽名:
原文用對(duì)方公鑰加密,原文的哈希值用自己的私鑰簽名,密文+簽名給對(duì)方,對(duì)方公鑰驗(yàn)證簽名和自己私鑰解
密原文的哈希值比對(duì)。
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
)
func main() {
str := "Hello World!"
base64Sig, _ := RSASign([]byte(str), "../certs/private.pem")
fmt.Println("簽名后的信息:", base64Sig)
err := RSAVerify([]byte(str), base64Sig, "../certs/public.pem")
if err == nil {
fmt.Println("驗(yàn)證成功!")
} else {
fmt.Println("驗(yàn)證失敗!")
}
}
// 私鑰簽名過程
func RSASign(data []byte, filename string) (string, error) {
// 1、選擇hash算法,對(duì)需要簽名的數(shù)據(jù)進(jìn)行hash運(yùn)算
myhash := crypto.SHA256
hashInstance := myhash.New()
hashInstance.Write(data)
hashed := hashInstance.Sum(nil)
// 2、讀取私鑰文件,解析出私鑰對(duì)象
privateKey, err := ReadParsePrivaterKey(filename)
if err != nil {
return "", err
}
// 3、RSA數(shù)字簽名(參數(shù)是隨機(jī)數(shù)、私鑰對(duì)象、哈希類型、簽名文件的哈希串),生成base64編碼的簽名字符串
bytes, err := rsa.SignPKCS1v15(rand.Reader, privateKey, myhash, hashed)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(bytes), nil
}
// 公鑰驗(yàn)證簽名過程
func RSAVerify(data []byte, base64Sig, filename string) error {
// 1、對(duì)base64編碼的簽名內(nèi)容進(jìn)行解碼,返回簽名字節(jié)
bytes, err := base64.StdEncoding.DecodeString(base64Sig)
if err != nil {
return err
}
// 2、選擇hash算法,對(duì)需要簽名的數(shù)據(jù)進(jìn)行hash運(yùn)算
myhash := crypto.SHA256
hashInstance := myhash.New()
hashInstance.Write(data)
hashed := hashInstance.Sum(nil)
// 3、讀取公鑰文件,解析出公鑰對(duì)象
publicKey, err := ReadParsePublicKey(filename)
if err != nil {
return err
}
// 4、RSA驗(yàn)證數(shù)字簽名(參數(shù)是公鑰對(duì)象、哈希類型、簽名文件的哈希串、簽名后的字節(jié))
return rsa.VerifyPKCS1v15(publicKey, myhash, hashed, bytes)
}
// 讀取公鑰文件,解析出公鑰對(duì)象
func ReadParsePublicKey(filename string) (*rsa.PublicKey, error) {
// 1、讀取公鑰文件,獲取公鑰字節(jié)
publicKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
// 2、解碼公鑰字節(jié),生成加密塊對(duì)象
block, _ := pem.Decode(publicKeyBytes)
if block == nil {
return nil, errors.New("公鑰信息錯(cuò)誤!")
}
// 3、解析DER編碼的公鑰,生成公鑰接口
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
// 4、公鑰接口轉(zhuǎn)型成公鑰對(duì)象
publicKey := publicKeyInterface.(*rsa.PublicKey)
return publicKey, nil
}
// 讀取私鑰文件,解析出私鑰對(duì)象
func ReadParsePrivaterKey(filename string) (*rsa.PrivateKey, error) {
// 1、讀取私鑰文件,獲取私鑰字節(jié)
privateKeyBytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
// 2、對(duì)私鑰文件進(jìn)行編碼,生成加密塊對(duì)象
block, _ := pem.Decode(privateKeyBytes)
if block == nil {
return nil, errors.New("私鑰信息錯(cuò)誤!")
}
// 3、解析DER編碼的私鑰,生成私鑰對(duì)象
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return privateKey, nil
}到此這篇關(guān)于Go語言實(shí)現(xiàn)對(duì)稱加密和非對(duì)稱加密的示例代碼的文章就介紹到這了,更多相關(guān)Go語言 對(duì)稱加密和非對(duì)稱加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Go語言實(shí)現(xiàn)Yaml編碼和解碼的方法詳解
在這篇文章中,我們將介紹如何使用Go語言編寫代碼來實(shí)現(xiàn)Yaml編碼和解碼,文中有詳細(xì)的代碼示例供大家參考,對(duì)大家的學(xué)習(xí)和工作有一定的幫助,需要的朋友可以參考下2023-11-11
淺談Go切片的值修改是否會(huì)覆蓋數(shù)組的值?
本文主要介紹了淺談Go切片的值修改是否會(huì)覆蓋數(shù)組的值,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下?2022-02-02

