当前位置:   article > 正文

常用加密算法go实现_golang sm3

golang sm3

密码学

加密算法

加密算法分类:对称加密算法、非对称加密算法和杂凑算法(散列函数)

  • 对称加密算法: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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80

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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

非对称加密算法

DSA

import (
	"crypto/dsa"
	"crypto/rand"
	"fmt"
	"math/big"
)

//对消息进行加密生成数字签名
func GenDSA() (*dsa.PrivateKey, *dsa.PublicKey) {
	//生成私钥所需要的参数
	var para dsa.Parameters
	//GenerateParameters的第三个参数决定L、N的长度,长度越长加密程度越高
	dsa.GenerateParameters(&para, 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("验证失败!")
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

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("验证失败!")
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

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("验证失败")
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

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("验证失败")
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

散列算法

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")
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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))
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/647246
推荐阅读
相关标签
  

闽ICP备14008679号