密码学
加密算法
加密算法分类:对称加密算法、非对称加密算法和杂凑算法(散列函数)
- 对称加密算法:DES、3DES(重复三次DES过程)、AES、SM4
- 常用加密模式:ECB、CBC、CFB、OFB、CRT等 参考
- 非对称加密算法:RSA、DSA、SM2、ECDSA(椭圆加密)
非对称加密算法根据加密所使用的密钥不同,可分为加密(用公钥加密私钥解密)和数字签名(私钥加密公钥解密)
- 杂凑算法:MD5、SHA-1系列、SHA-2系列、SM3
杂凑算法又称为散列算法,不同算法得到定长的散列值。介绍
对称加密算法
DES
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/hex"
"fmt"
)
//使用DES加密
//src 待加密明文 , key 密钥
//加密
func EncryptDES(src, key []byte) []byte {
//创建cipher.Block接口 其对应的就是一个加密块
block, err := des.NewCipher(key)
if nil != err {
panic(err)
}
length := block.BlockSize()
//填充最后一组数据
src = PaddingText(src, length)
//初始化向量
iv := []byte("12345678")
//创建cbc加密模式
blockMode := cipher.NewCBCEncrypter(block, iv)
//创建切片,用于存储加密后的数据
dst := make([]byte, len(src))
blockMode.CryptBlocks(dst, src)
return dst
}
//解密
func DecryptDES(src, key []byte) []byte {
//创建解密块
block, err := des.NewCipher(key)
if nil != err {
panic(err)
}
iv := []byte("12345678")
//创建cbc解密模式
blockMode := cipher.NewCBCDecrypter(block, iv)
dst := make([]byte, len(src))
blockMode.CryptBlocks(dst, src)
return UnPaddingText(dst)
}
func main() {
src := []byte("你好!XXX")
key := []byte("87654321")
encryptedMsg := EncryptDES(src, key)
fmt.Println("加密后:", hex.EncodeToString(encryptedMsg))
decryptedMsg := DecryptDES(encryptedMsg, key)
fmt.Println("解密后的明文:", string(decryptedMsg))
}
//给最后一组数据填充至64字节
func PaddingText(src []byte, blockSize int) []byte {
//求出最后一个分组需要填充的字节数
padding := blockSize - len(src)%blockSize
//创建新的切片,切片字节数为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
//将新创建的切片和带填充的数据进行拼接
nextText := append(src, padText...)
return nextText
}
//取出数据尾部填充的赘余字符
func UnPaddingText(src []byte) []byte {
//获取待处理数据长度
len := len(src)
//取出最后一个字符
num := int(src[len-1])
newText := src[:len-num]
return newText
}
3DES
import (
"bytes"
"crypto/cipher"
"crypto/des"
"encoding/hex"
"fmt"
)
func Encrypt3DES(src, key []byte) []byte {
//创建加密区块
block, err := des.NewTripleDESCipher(key)
if nil != err {
panic(err)
}
//填充数据
src = PaddingText(src, block.BlockSize())
//加密
blockmode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
dst := make([]byte, len(src))
blockmode.CryptBlocks(dst, src)
return dst
}
func Decrypt3DES(dst, key []byte) []byte {
//创建解密块
block, err := des.NewTripleDESCipher(key)
if nil != err {
panic(err)
}
//创建解密模式
blockmode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
src := make([]byte, len(dst))
blockmode.CryptBlocks(src, dst)
//去除填充的数据
src = UnPaddingText(src)
return src
}
func main() {
encrypt_msg := []byte("你好 XXX")
key := []byte("123456788765432112345678")
encrypted3DES_msg := Encrypt3DES(encrypt_msg, key)
fmt.Println(hex.EncodeToString(encrypted3DES_msg))
decrypt_msg := Decrypt3DES(encrypted3DES_msg, key)
fmt.Println(string(decrypt_msg))
}
//给最后一组数据填充至64字节
func PaddingText(src []byte, blockSize int) []byte {
//求出最后一个分组需要填充的字节数
padding := blockSize - len(src)%blockSize
//创建新的切片,切片字节数为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
//将新创建的切片和带填充的数据进行拼接
nextText := append(src, padText...)
return nextText
}
//取出数据尾部填充的赘余字符
func UnPaddingText(src []byte) []byte {
//获取待处理数据长度
len := len(src)
//取出最后一个字符
num := int(src[len-1])
newText := src[:len-num]
return newText
}
AES
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
func EncryptAES(src, key []byte) []byte {
block, err := aes.NewCipher(key)
if nil != err {
panic(err)
}
//填充
src = PaddingText(src, block.BlockSize())
//初始化向量
iv := []byte("12345678abcdefgh")
//创建加密模式
blockmode := cipher.NewCBCEncrypter(block, iv)
dst := make([]byte, len(src))
//加密
blockmode.CryptBlocks(dst, src)
return dst
}
func DecryptAES(src, key []byte) []byte {
block, err := aes.NewCipher(key)
if nil != err {
panic(err)
}
//初始化向量
iv := []byte("12345678abcdefgh")
blockmode := cipher.NewCBCDecrypter(block, iv)
//解密
dst := make([]byte, len(src))
blockmode.CryptBlocks(dst, src)
//去除填充
dst = UnPaddingText(dst)
return dst
}
func main() {
src := []byte("你好!潘丽萍")
key := []byte("8765432112345678")
encryptedMsg := EncryptAES(src, key)
fmt.Println("加密后:", hex.EncodeToString(encryptedMsg))
decryptedMsg := DecryptAES(encryptedMsg, key)
fmt.Println("解密后的明文:", string(decryptedMsg))
}
//给最后一组数据填充至64字节
func PaddingText(src []byte, blockSize int) []byte {
//求出最后一个分组需要填充的字节数
padding := blockSize - len(src)%blockSize
//创建新的切片,切片字节数为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
//将新创建的切片和带填充的数据进行拼接
nextText := append(src, padText...)
return nextText
}
//取出数据尾部填充的赘余字符
func UnPaddingText(src []byte) []byte {
//获取待处理数据长度
len := len(src)
//取出最后一个字符
num := int(src[len-1])
newText := src[:len-num]
return newText
}
SM4
import (
"bytes"
"crypto/cipher"
"encoding/hex"
"fmt"
"github.com/tjfoc/gmsm/sm4"
)
func EncryptSM4(src, pwd []byte) []byte {
//创建加密块
block, err := sm4.NewCipher([]byte(pwd))
if nil != err {
panic(err)
}
//填充数据
src = PaddingText(src, block.BlockSize())
//初始化向量
iv := []byte("1234567887654321")
//设置加密模式
blockmode := cipher.NewCBCEncrypter(block, iv)
dst := make([]byte, len(src))
blockmode.CryptBlocks(dst, src)
return dst
}
func DecryptSM4(src, pwd []byte) []byte {
//创建解密块
block, err := sm4.NewCipher(pwd)
if nil != err {
panic(err)
}
//初始化向量
iv := []byte("1234567887654321")
//创建解密模式
blockmode := cipher.NewCBCDecrypter(block, iv)
dst := make([]byte, len(src))
//解密
blockmode.CryptBlocks(dst, src)
//去除填充
dst = UnPaddingText(dst)
return dst
}
func main() {
msg := []byte("你好!XXX")
pwd := []byte("1234567887654321")
encryptedMsg := EncryptSM4(msg, pwd)
decryptMsg := DecryptSM4(encryptedMsg, pwd)
fmt.Printf("%v\n%v", hex.EncodeToString(encryptedMsg), string(decryptMsg))
}
//给最后一组数据填充至64字节
func PaddingText(src []byte, blockSize int) []byte {
//求出最后一个分组需要填充的字节数
padding := blockSize - len(src)%blockSize
//创建新的切片,切片字节数为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
//将新创建的切片和带填充的数据进行拼接
nextText := append(src, padText...)
return nextText
}
//取出数据尾部填充的赘余字符
func UnPaddingText(src []byte) []byte {
//获取待处理数据长度
len := len(src)
//取出最后一个字符
num := int(src[len-1])
newText := src[:len-num]
return newText
}
非对称加密算法
DSA
import (
"crypto/dsa"
"crypto/rand"
"fmt"
"math/big"
)
//对消息进行加密生成数字签名
func GenDSA() (*dsa.PrivateKey, *dsa.PublicKey) {
//生成私钥所需要的参数
var para dsa.Parameters
//GenerateParameters的第三个参数决定L、N的长度,长度越长加密程度越高
dsa.GenerateParameters(¶, rand.Reader, dsa.L1024N160)
//将初始化好的参数传入给私钥
var priKey dsa.PrivateKey
priKey.Parameters = para
dsa.GenerateKey(&priKey, rand.Reader)
return &priKey, &priKey.PublicKey
}
//验证数字签名
func EncryptDSA(priKey *dsa.PrivateKey, src []byte) (r, s *big.Int) {
r, s, err := dsa.Sign(rand.Reader, priKey, src)
if nil != err {
panic(err)
}
return r, s
}
//验证数字签名的真实性
func VerifyDSA(pubKey *dsa.PublicKey, src []byte, r, s *big.Int) bool {
return dsa.Verify(pubKey, src, r, s)
}
//对消息本身进行签名
func main() {
priKey, publicKey := GenDSA()
msg := []byte("你好! XXX")
r, s := EncryptDSA(priKey, msg)
verifyDSA := VerifyDSA(publicKey, msg, r, s)
if verifyDSA {
fmt.Println("验证通过!")
} else {
fmt.Println("验证失败!")
}
}
RSA
import (
"crypto"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"fmt"
)
//生成密钥对
func GenKey() (*rsa.PrivateKey, *rsa.PublicKey) {
PriKey, err := rsa.GenerateKey(rand.Reader, 2048)
if nil != err {
panic(err)
}
return PriKey, &PriKey.PublicKey
}
//用私钥和指定的hash函数对消息的散列值进行加密形成数字签名
func EncryptRSA(priKey *rsa.PrivateKey, src string) []byte {
//对消息进行hash
hash := md5.New()
hash.Write([]byte(src))
bytes := hash.Sum(nil)
//对散列值进行加密
opt := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.MD5}
sig, err := rsa.SignPSS(rand.Reader, priKey, crypto.MD5, bytes, opt)
if nil != err {
panic(err)
}
return sig
}
//验证数字签名的真实性
func VerifyRSA(pubKey *rsa.PublicKey, src string, sig []byte) bool {
//对消息进行散列处理
hash := md5.New()
hash.Write([]byte(src))
bytes := hash.Sum(nil)
//对数字签名进行验证
opt := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.MD5}
err := rsa.VerifyPSS(pubKey, crypto.MD5, bytes, sig, opt)
if nil != err {
fmt.Println(err)
return false
} else {
return true
}
}
//rsa对消息的散列值进行数字签名和验证
func main() {
priKey, publicKey := GenKey()
sig := EncryptRSA(priKey, "你好!XXX")
verifyRSA := VerifyRSA(publicKey, "你好!XXX", sig)
if verifyRSA {
fmt.Println("验证通过!")
} else {
fmt.Println("验证失败!")
}
}
SM2
import (
"crypto/rand"
"fmt"
"github.com/tjfoc/gmsm/sm2"
)
//生成密钥对
func GenKeyPair() (*sm2.PrivateKey, *sm2.PublicKey) {
privateKey, err := sm2.GenerateKey(rand.Reader)
if nil != err {
panic(err)
}
return privateKey, &privateKey.PublicKey
}
//对消息进行加密
func EncryptSM2(pubKey *sm2.PublicKey, src string) []byte {
sign, err := pubKey.EncryptAsn1([]byte(src), rand.Reader)
if nil != err {
panic(err)
}
return sign
}
//对消息进行数字签名验证
func VerifySM2(priKey *sm2.PrivateKey, msg string, sign []byte) bool {
//验证数字签名的正确性
asn1, err := priKey.DecryptAsn1([]byte(msg))
if nil != err {
fmt.Println(err)
return false
} else {
fmt.Println(string(asn1))
return true
}
}
func main() {
msg := "你好!xxx"
priKey, publicKey := GenKeyPair()
sign := EncryptSM2(publicKey, msg)
verifySM2 := VerifySM2(priKey, msg, sign)
if verifySM2 {
fmt.Println("验证通过")
} else {
fmt.Println("验证失败")
}
}
ECDSA
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"fmt"
"math/big"
)
//椭圆加密算法
//生成密钥对
func GenECDSA() (*ecdsa.PrivateKey, *ecdsa.PublicKey) {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if nil != err {
panic(err)
}
return privateKey, &privateKey.PublicKey
}
func EncryptECDSA(priKey *ecdsa.PrivateKey, src string) (r, s *big.Int) {
//对信息进行hash
bytes := sha256.Sum256([]byte(src))
//对散列值进行加密
r, s, err := ecdsa.Sign(rand.Reader, priKey, bytes[:])
if nil != err {
panic(err)
}
return r, s
}
func VerifyECDSA(pubKey *ecdsa.PublicKey, src string, r, s *big.Int) bool {
//对消息进行hash
bytes := sha256.Sum256([]byte(src))
//验证签名
return ecdsa.Verify(pubKey, bytes[:], r, s)
}
func main() {
msg := "你好!XXX"
priKey, publicKey := GenECDSA()
r, s := EncryptECDSA(priKey, msg)
verifyECDSA := VerifyECDSA(publicKey, msg, r, s)
if verifyECDSA {
fmt.Println("验证通过")
} else {
fmt.Println("验证失败")
}
}
散列算法
MD5
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"os"
)
//对文件进行hash处理
func HashFileMD5(path string) string {
//1、获取文件句柄
file, err := os.Open(path)
if nil != err {
panic(err)
}
//2、将文件内容写入到hash
hash := md5.New()
_, err = io.Copy(hash, file)
if nil != err {
panic(err)
}
//3、计算散列值
bytes := hash.Sum(nil)
return hex.EncodeToString(bytes)
}
func main() {
//散列对象创建
hash := md5.New()
//将内容写入对象
hash.Write([]byte("区块链"))
//计算出散列值
sum := hash.Sum(nil)
fmt.Println(hex.EncodeToString(sum))
//75d8fafb0706c9381d4c91e3b184f19d
hash.Reset()
hash.Write([]byte("区块链"))
bytes := hash.Sum([]byte("123"))
fmt.Println(hex.EncodeToString(bytes))
//313233 75d8fafb0706c9381d4c91e3b184f19d
i := md5.Sum([]byte("区块链"))
fmt.Println(hex.EncodeToString(i[:]))
fileMD5 := HashFileMD5("privateKey.pem")
fmt.Println(fileMD5, "-------3234")
}
SHA-256
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
hash := sha256.New()
hash.Write([]byte("你好!XXX"))
bytes := hash.Sum(nil)
fmt.Println(hex.EncodeToString(bytes))
//36eda9afdaae39041fcbd101618717330a07b188373ab21f28e87e8793a7014d
}
SM3
import (
"encoding/hex"
"fmt"
"github.com/tjfoc/gmsm/sm3"
)
func EncryptSM3(msg string) string {
hash := sm3.New()
hash.Write([]byte(msg))
bytes := hash.Sum(nil)
return hex.EncodeToString(bytes)
}
func main() {
encryptSM3 := EncryptSM3("你好!XXX")
fmt.Println(encryptSM3)
sm3Sum := sm3.Sm3Sum([]byte("你好!XXX"))
fmt.Println(hex.EncodeToString(sm3Sum))
}