Go语言实现对称加密和非对称加密的示例代码

来自:网络
时间:2024-03-30
阅读:

对称加密和非对称加密的区别主要有以下几个方面:

  • 1、密钥的使用:对称加密中,加密和解密使用的是同一个密钥,而非对称加密则使用两个不同的密钥,一般

    使用公钥进行加密,私钥进行解密。

  • 2、速度和效率:对称加密解密的速度比较快,适合数据比较长时的使用,而非对称加密和解密花费的时间

    长、速度相对较慢,只适合对少量数据的使用。

  • 3、安全性:对称加密的安全性相对较低,因为通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个

    通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,私钥是自

    己保存的,不需要像对称加密那样在通信之前要先同步秘钥,因此其安全性更好。

  • 4、密钥分发:在对称加密中,需要在通信双方之间安全地共享密钥。如果没有安全的通道来共享密钥,可能

    会被黑客截获,导致数据泄露。而非对称加密则不需要在通信之前共享密钥,因此更加安全。

在实际应用中,对称加密和非对称加密经常结合使用,以充分发挥它们各自的优点。例如,可以使用对称加密来加

密大量数据,然后使用非对称加密来安全地分发对称加密的密钥。

1、对称加密

1.1 AES

package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"fmt"
)

// AES加密
func main() {
	// AES加密占16、24或32字节
	key := "12345678abcdefgh"
	// 加密的字符串
	str := "hello world!"
	fmt.Println("加密前的字符串:", str)
	cipherText, _ := SCEncryptString(str, key)
	fmt.Println("加密后的字符串:", cipherText)
	originalText, _ := SCDecryptString(cipherText, key)
	fmt.Println("解密后的字符串:", originalText)
}

// 对称加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、对明文进行填充(参数为原始字节切片和密码对象的区块个数)
	paddingBytes := PKCS5Padding(originalBytes, blockSize)
	// 3、实例化加密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
	cipherBytes := make([]byte, len(paddingBytes))
	blockMode.CryptBlocks(cipherBytes, paddingBytes)
	return cipherBytes, nil
}

// 对称解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、实例化解密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	// 3、对密文进行解密(参数为填充字节切片和加密字节切片)
	paddingBytes := make([]byte, len(cipherBytes))
	blockMode.CryptBlocks(paddingBytes, cipherBytes)
	// 4、去除填充的字节(参数为填充切片)
	originalBytes := PKCS5UnPadding(paddingBytes)
	return originalBytes, nil
}

// 封装字符串对称加密
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
}

// 封装字符串对称解密
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
}

// 末尾填充字节
func PKCS5Padding(data []byte, blockSize int) []byte {
	// 要填充的值和个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个二进制值
	slice1 := []byte{byte(padding)}
	// 要填充的二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
	// 要填充的个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个0数据
	slice1 := []byte{0}
	// 要填充的0二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 去除填充的字节
func PKCS5UnPadding(data []byte) []byte {
	// 获取二进制数组最后一个数值
	unpadding := data[len(data)-1]
	// 截取开始至总长度减去填充值之间的有效数据
	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字节
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("加密数据长度无效")
	}

	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("加密后的数据:", encryptedData)

	decryptedData, err := decrypt(encryptedData)
	if err != nil {
		fmt.Println("解密失败:", err)
		return
	}

	fmt.Println("解密后的数据:", string(decryptedData))
}

1.2 DES

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/base64"
	"fmt"
)

// DES加密
func main() {
	// DES密钥占8字节
	key := "1234abcd"
	// 加密的字符串
	str := "hello world!"
	fmt.Println("加密前的字符串:", str)
	cipherText, _ := SCEncryptString(str, key)
	fmt.Println("加密后的字符串:", cipherText)
	originalText, _ := SCDecryptString(cipherText, key)
	fmt.Println("解密后的字符串:", originalText)
}

// 对称加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、对明文进行填充(参数为原始字节切片和密码对象的区块个数)
	paddingBytes := PKCS5Padding(originalBytes, blockSize)
	// 3、实例化加密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
	cipherBytes := make([]byte, len(paddingBytes))
	blockMode.CryptBlocks(cipherBytes, paddingBytes)
	return cipherBytes, nil
}

// 对称解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、实例化解密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	// 3、对密文进行解密(参数为填充字节切片和加密字节切片)
	paddingBytes := make([]byte, len(cipherBytes))
	blockMode.CryptBlocks(paddingBytes, cipherBytes)
	// 4、去除填充的字节(参数为填充切片)
	originalBytes := PKCS5UnPadding(paddingBytes)
	return originalBytes, nil
}

// 封装字符串对称加密
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
}

// 封装字符串对称解密
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
}

// 末尾填充字节
func PKCS5Padding(data []byte, blockSize int) []byte {
	// 要填充的值和个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个二进制值
	slice1 := []byte{byte(padding)}
	// 要填充的二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
	// 要填充的个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个0数据
	slice1 := []byte{0}
	// 要填充的0二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 去除填充的字节
func PKCS5UnPadding(data []byte) []byte {
	// 获取二进制数组最后一个数值
	unpadding := data[len(data)-1]
	// 截取开始至总长度减去填充值之间的有效数据
	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字节
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("加密数据长度无效")
	}

	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("加密后的数据:", encryptedData)

	decryptedData, err := decrypt(encryptedData)
	if err != nil {
		fmt.Println("解密失败:", err)
		return
	}

	fmt.Println("解密后的数据:", string(decryptedData))
}

1.3 3DES

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/base64"
	"fmt"
)

// 3DES加密
func main() {
	// 3DES密钥占24字节
	key := "abcdefghijklmn0123456789"
	// 加密的字符串
	str := "hello world!"
	fmt.Println("加密前的字符串:", str)
	cipherText, _ := SCEncryptString(str, key)
	fmt.Println("加密后的字符串:", cipherText)
	originalText, _ := SCDecryptString("3eS626HB2R9ZGcOAYLuWCw==", key)
	fmt.Println("解密后的字符串:", originalText)
}

// 对称加密
func SCEncrypt(originalBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、对明文进行填充(参数为原始字节切片和密码对象的区块个数)
	paddingBytes := PKCS5Padding(originalBytes, blockSize)
	// 3、实例化加密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
	// 4、对填充字节后的明文进行加密(参数为加密字节切片和填充字节切片)
	cipherBytes := make([]byte, len(paddingBytes))
	blockMode.CryptBlocks(cipherBytes, paddingBytes)
	return cipherBytes, nil
}

// 对称解密
func SCDecrypt(cipherBytes, key []byte) ([]byte, error) {
	// 1、实例化密码器block(参数为密钥)
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		return nil, err
	}
	blockSize := block.BlockSize()
	// 2、实例化解密模式(参数为密码对象和密钥)
	blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
	// 3、对密文进行解密(参数为填充字节切片和加密字节切片)
	paddingBytes := make([]byte, len(cipherBytes))
	blockMode.CryptBlocks(paddingBytes, cipherBytes)
	// 4、去除填充的字节(参数为填充切片)
	originalBytes := PKCS5UnPadding(paddingBytes)
	return originalBytes, nil
}

// 封装字符串对称加密
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
}

// 封装字符串对称解密
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
}

// 末尾填充字节
func PKCS5Padding(data []byte, blockSize int) []byte {
	// 要填充的值和个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个二进制值
	slice1 := []byte{byte(padding)}
	// 要填充的二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 末尾填充0
func ZerosPadding(data []byte, blockSize int) []byte {
	// 要填充的个数
	padding := blockSize - len(data)%blockSize
	// 要填充的单个0数据
	slice1 := []byte{0}
	// 要填充的0二进制数组
	slice2 := bytes.Repeat(slice1, padding)
	// 填充到数据末端
	return append(data, slice2...)
}

// 去除填充的字节
func PKCS5UnPadding(data []byte) []byte {
	// 获取二进制数组最后一个数值
	unpadding := data[len(data)-1]
	// 截取开始至总长度减去填充值之间的有效数据
	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字节
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("加密数据长度无效")
	}

	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("加密后的数据:", encryptedData)

	decryptedData, err := decrypt(encryptedData)
	if err != nil {
		fmt.Println("解密失败:", err)
		return
	}

	fmt.Println("解密后的数据:", string(decryptedData))
}

2、非对称加密算法RSA

2.1 生成密钥对

生成密钥对,分别存储到公钥文件(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("密钥生成成功!")
}

// 生成密钥对并保存到文件
func GenerateRSAKey() error {
	// 1、RSA生成私钥文件的核心步骤
	// 1)、生成RSA密钥对
	// 密钥长度,默认值为1024位
	bits := 1024
	privateKer, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return err
	}
	// 2)、将私钥对象转换成DER编码形式
	derPrivateKer := x509.MarshalPKCS1PrivateKey(privateKer)
	// 3)、创建私钥pem文件
	file, err := os.Create("../certs/private.pem")
	if err != nil {
		return err
	}
	// 4)、对密钥信息进行编码,写入到私钥文件中
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: derPrivateKer,
	}
	err = pem.Encode(file, block)
	if err != nil {
		return err
	}
	// 2、RSA生成公钥文件的核心步骤
	// 1)、生成公钥对象
	publicKey := &privateKer.PublicKey
	// 2)、将公钥对象序列化为DER编码格式
	derPublicKey, err := x509.MarshalPKIXPublicKey(publicKey)
	if err != nil {
		return err
	}
	// 3)、创建公钥pem文件
	file, err = os.Create("../certs/public.pem")
	if err != nil {
		return err
	}
	// 4)、对公钥信息进行编码,写入到公钥文件中
	block = &pem.Block{
		Type:  "PUBLIC KEY",
		Bytes: derPublicKey,
	}
	err = pem.Encode(file, block)
	if err != nil {
		return err
	}
	return nil
}

2.2 RSA加密解密过程

公钥加密,私钥解密。

加密过程:

  • 1、读取公钥文件,解析出公钥对象
  • 2、使用公钥对明文进行加密

解密过程:

  • 1、读取私钥文件,解析出公钥对象
  • 2、使用私钥对密文进行解密
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加密字节数组,返回字节数组
func RSAEncrypt(originalBytes []byte, filename string) ([]byte, error) {
	// 1、读取公钥文件,解析出公钥对象
	publicKey, err := ReadParsePublicKey(filename)
	if err != nil {
		return nil, err
	}
	// 2、RSA加密,参数是随机数、公钥对象、需要加密的字节
	// Reader是一个全局共享的密码安全的强大的伪随机生成器
	return rsa.EncryptPKCS1v15(rand.Reader, publicKey, originalBytes)
}

// RSA解密字节数组,返回字节数组
func RSADecrypt(cipherBytes []byte, filename string) ([]byte, error) {
	// 1、读取私钥文件,解析出私钥对象
	privateKey, err := ReadParsePrivaterKey(filename)
	if err != nil {
		return nil, err
	}
	// 2、ras解密,参数是随机数、私钥对象、需要解密的字节
	return rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherBytes)
}

// 读取公钥文件,解析出公钥对象
func ReadParsePublicKey(filename string) (*rsa.PublicKey, error) {
	// 1、读取公钥文件,获取公钥字节
	publicKeyBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	// 2、解码公钥字节,生成加密块对象
	block, _ := pem.Decode(publicKeyBytes)
	if block == nil {
		return nil, errors.New("公钥信息错误!")
	}
	// 3、解析DER编码的公钥,生成公钥接口
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	// 4、公钥接口转型成公钥对象
	publicKey := publicKeyInterface.(*rsa.PublicKey)
	return publicKey, nil
}

// 读取私钥文件,解析出私钥对象
func ReadParsePrivaterKey(filename string) (*rsa.PrivateKey, error) {
	// 1、读取私钥文件,获取私钥字节
	privateKeyBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	// 2、对私钥文件进行编码,生成加密块对象
	block, _ := pem.Decode(privateKeyBytes)
	if block == nil {
		return nil, errors.New("私钥信息错误!")
	}
	// 3、解析DER编码的私钥,生成私钥对象
	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解密经过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 数字签名验证

加密与签名的区别:

  • 加密:公钥加密,私钥解密
  • 签名:私钥签名,公钥验证

数字签名过程:

  • 原文的哈希值用自己私钥签名,原文+签名给对方,对方用公钥验证签名时与原文哈希比对。

加密并签名:

  • 原文用对方公钥加密,原文的哈希值用自己的私钥签名,密文+签名给对方,对方公钥验证签名和自己私钥解

    密原文的哈希值比对。

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("验证成功!")
	} else {
		fmt.Println("验证失败!")
	}
}

// 私钥签名过程
func RSASign(data []byte, filename string) (string, error) {
	// 1、选择hash算法,对需要签名的数据进行hash运算
	myhash := crypto.SHA256
	hashInstance := myhash.New()
	hashInstance.Write(data)
	hashed := hashInstance.Sum(nil)
	// 2、读取私钥文件,解析出私钥对象
	privateKey, err := ReadParsePrivaterKey(filename)
	if err != nil {
		return "", err
	}
	// 3、RSA数字签名(参数是随机数、私钥对象、哈希类型、签名文件的哈希串),生成base64编码的签名字符串
	bytes, err := rsa.SignPKCS1v15(rand.Reader, privateKey, myhash, hashed)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(bytes), nil
}

// 公钥验证签名过程
func RSAVerify(data []byte, base64Sig, filename string) error {
	// 1、对base64编码的签名内容进行解码,返回签名字节
	bytes, err := base64.StdEncoding.DecodeString(base64Sig)
	if err != nil {
		return err
	}
	// 2、选择hash算法,对需要签名的数据进行hash运算
	myhash := crypto.SHA256
	hashInstance := myhash.New()
	hashInstance.Write(data)
	hashed := hashInstance.Sum(nil)
	// 3、读取公钥文件,解析出公钥对象
	publicKey, err := ReadParsePublicKey(filename)
	if err != nil {
		return err
	}
	// 4、RSA验证数字签名(参数是公钥对象、哈希类型、签名文件的哈希串、签名后的字节)
	return rsa.VerifyPKCS1v15(publicKey, myhash, hashed, bytes)
}

// 读取公钥文件,解析出公钥对象
func ReadParsePublicKey(filename string) (*rsa.PublicKey, error) {
	// 1、读取公钥文件,获取公钥字节
	publicKeyBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	// 2、解码公钥字节,生成加密块对象
	block, _ := pem.Decode(publicKeyBytes)
	if block == nil {
		return nil, errors.New("公钥信息错误!")
	}
	// 3、解析DER编码的公钥,生成公钥接口
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	// 4、公钥接口转型成公钥对象
	publicKey := publicKeyInterface.(*rsa.PublicKey)
	return publicKey, nil
}

// 读取私钥文件,解析出私钥对象
func ReadParsePrivaterKey(filename string) (*rsa.PrivateKey, error) {
	// 1、读取私钥文件,获取私钥字节
	privateKeyBytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	// 2、对私钥文件进行编码,生成加密块对象
	block, _ := pem.Decode(privateKeyBytes)
	if block == nil {
		return nil, errors.New("私钥信息错误!")
	}
	// 3、解析DER编码的私钥,生成私钥对象
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}
	return privateKey, nil
}
返回顶部
顶部