9.16 Go 加密解密算法总结

前言

加密解密在实际开发中应用比较广泛,常用加解密分为:“对称式”、“非对称式”和”数字签名“。

对称式:对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。具体算法主要有DES算法3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。

非对称加密(公钥加密):指加密和解密使用不同密钥的加密算法,也称为公私钥加密。具体算法主要有RSAElgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。

数字签名:数字签名是非对称密钥加密技术数字摘要技术的应用。主要算法有md5、hmac、sha1等。

以下介绍golang语言主要的加密解密算法实现。

md5

MD5信息摘要算法是一种被广泛使用的密码散列函数,可以产生出一个128位(16进制,32个字符)的散列值(hash value),用于确保信息传输完整一致。

  1. func GetMd5String(s string) string {
  2. h := md5.New()
  3. h.Write([]byte(s))
  4. return hex.EncodeToString(h.Sum(nil))
  5. }

hmac

HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code)的缩写,

它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。

和我们自定义的加salt算法不同,Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。

示例

  1. //key随意设置 data 要加密数据
  2. func Hmac(key, data string) string {
  3. hash:= hmac.New(md5.New, []byte(key)) // 创建对应的md5哈希加密算法
  4. hash.Write([]byte(data))
  5. return hex.EncodeToString(hash.Sum([]byte("")))
  6. }
  7. func HmacSha256(key, data string) string {
  8. hash:= hmac.New(sha256.New, []byte(key)) //创建对应的sha256哈希加密算法
  9. hash.Write([]byte(data))
  10. return hex.EncodeToString(hash.Sum([]byte("")))
  11. }

sha1

SHA-1可以生成一个被称为消息摘要的160(20字节)散列值,散列值通常的呈现形式为40个十六进制数。

  1. func Sha1(data string) string {
  2. sha1 := sha1.New()
  3. sha1.Write([]byte(data))
  4. return hex.EncodeToString(sha1.Sum([]byte("")))
  5. }

AES

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。AES中常见的有三种解决方案,分别为AES-128、AES-192和AES-256。如果采用真正的128位加密技术甚至256位加密技术,蛮力攻击要取得成功需要耗费相当长的时间。

AES 有五种加密模式:

  • 电码本模式(Electronic Codebook Book (ECB))、
  • 密码分组链接模式(Cipher Block Chaining (CBC))、
  • 计算器模式(Counter (CTR))、
  • 密码反馈模式(Cipher FeedBack (CFB))
  • 输出反馈模式(Output FeedBack (OFB))

    ECB模式

出于安全考虑,golang默认并不支持ECB模式。

  1. package main
  2. import (
  3. "crypto/aes"
  4. "fmt"
  5. )
  6. func AESEncrypt(src []byte, key []byte) (encrypted []byte) {
  7. cipher, _ := aes.NewCipher(generateKey(key))
  8. length := (len(src) + aes.BlockSize) / aes.BlockSize
  9. plain := make([]byte, length*aes.BlockSize)
  10. copy(plain, src)
  11. pad := byte(len(plain) - len(src))
  12. for i := len(src); i < len(plain); i++ {
  13. plain[i] = pad
  14. }
  15. encrypted = make([]byte, len(plain))
  16. // 分组分块加密
  17. for bs, be := 0, cipher.BlockSize(); bs <= len(src); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
  18. cipher.Encrypt(encrypted[bs:be], plain[bs:be])
  19. }
  20. return encrypted
  21. }
  22. func AESDecrypt(encrypted []byte, key []byte) (decrypted []byte) {
  23. cipher, _ := aes.NewCipher(generateKey(key))
  24. decrypted = make([]byte, len(encrypted))
  25. //
  26. for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
  27. cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
  28. }
  29. trim := 0
  30. if len(decrypted) > 0 {
  31. trim = len(decrypted) - int(decrypted[len(decrypted)-1])
  32. }
  33. return decrypted[:trim]
  34. }
  35. func generateKey(key []byte) (genKey []byte) {
  36. genKey = make([]byte, 16)
  37. copy(genKey, key)
  38. for i := 16; i < len(key); {
  39. for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
  40. genKey[j] ^= key[i]
  41. }
  42. }
  43. return genKey
  44. }
  45. func main() {
  46. source:="hello world"
  47. fmt.Println("原字符:",source)
  48. //16byte密钥
  49. key:="1443flfsaWfdas"
  50. encryptCode:=AESEncrypt([]byte(source),[]byte(key))
  51. fmt.Println("密文:",string(encryptCode))
  52. decryptCode:=AESDecrypt(encryptCode,[]byte(key))
  53. fmt.Println("解密:",string(decryptCode))
  54. }

CBC模式

  1. package main
  2. import(
  3. "bytes"
  4. "crypto/aes"
  5. "fmt"
  6. "crypto/cipher"
  7. "encoding/base64"
  8. )
  9. func main() {
  10. orig := "hello world"
  11. key := "0123456789012345"
  12. fmt.Println("原文:", orig)
  13. encryptCode := AesEncrypt(orig, key)
  14. fmt.Println("密文:" , encryptCode)
  15. decryptCode := AesDecrypt(encryptCode, key)
  16. fmt.Println("解密结果:", decryptCode)
  17. }
  18. func AesEncrypt(orig string, key string) string {
  19. // 转成字节数组
  20. origData := []byte(orig)
  21. k := []byte(key)
  22. // 分组秘钥
  23. // NewCipher该函数限制了输入k的长度必须为16, 24或者32
  24. block, _ := aes.NewCipher(k)
  25. // 获取秘钥块的长度
  26. blockSize := block.BlockSize()
  27. // 补全码
  28. origData = PKCS7Padding(origData, blockSize)
  29. // 加密模式
  30. blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
  31. // 创建数组
  32. cryted := make([]byte, len(origData))
  33. // 加密
  34. blockMode.CryptBlocks(cryted, origData)
  35. return base64.StdEncoding.EncodeToString(cryted)
  36. }
  37. func AesDecrypt(cryted string, key string) string {
  38. // 转成字节数组
  39. crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
  40. k := []byte(key)
  41. // 分组秘钥
  42. block, _ := aes.NewCipher(k)
  43. // 获取秘钥块的长度
  44. blockSize := block.BlockSize()
  45. // 加密模式
  46. blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
  47. // 创建数组
  48. orig := make([]byte, len(crytedByte))
  49. // 解密
  50. blockMode.CryptBlocks(orig, crytedByte)
  51. // 去补全码
  52. orig = PKCS7UnPadding(orig)
  53. return string(orig)
  54. }
  55. //补码
  56. //AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
  57. func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
  58. padding := blocksize - len(ciphertext)%blocksize
  59. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  60. return append(ciphertext, padtext...)
  61. }
  62. //去码
  63. func PKCS7UnPadding(origData []byte) []byte {
  64. length := len(origData)
  65. unpadding := int(origData[length-1])
  66. return origData[:(length - unpadding)]
  67. }

CRT模式

  1. package main
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "fmt"
  7. )
  8. //加密
  9. func aesCtrCrypt(plainText []byte, key []byte) ([]byte, error) {
  10. //1. 创建cipher.Block接口
  11. block, err := aes.NewCipher(key)
  12. if err != nil {
  13. return nil, err
  14. }
  15. //2. 创建分组模式,在crypto/cipher包中
  16. iv := bytes.Repeat([]byte("1"), block.BlockSize())
  17. stream := cipher.NewCTR(block, iv)
  18. //3. 加密
  19. dst := make([]byte, len(plainText))
  20. stream.XORKeyStream(dst, plainText)
  21. return dst, nil
  22. }
  23. func main() {
  24. source:="hello world"
  25. fmt.Println("原字符:",source)
  26. key:="1443flfsaWfdasds"
  27. encryptCode,_:=aesCtrCrypt([]byte(source),[]byte(key))
  28. fmt.Println("密文:",string(encryptCode))
  29. decryptCode,_:=aesCtrCrypt(encryptCode,[]byte(key))
  30. fmt.Println("解密:",string(decryptCode))
  31. }

CFB模式

  1. package main
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/rand"
  6. "encoding/hex"
  7. "fmt"
  8. "io"
  9. )
  10. func AesEncryptCFB(origData []byte, key []byte) (encrypted []byte) {
  11. block, err := aes.NewCipher(key)
  12. if err != nil {
  13. //panic(err)
  14. }
  15. encrypted = make([]byte, aes.BlockSize+len(origData))
  16. iv := encrypted[:aes.BlockSize]
  17. if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  18. //panic(err)
  19. }
  20. stream := cipher.NewCFBEncrypter(block, iv)
  21. stream.XORKeyStream(encrypted[aes.BlockSize:], origData)
  22. return encrypted
  23. }
  24. func AesDecryptCFB(encrypted []byte, key []byte) (decrypted []byte) {
  25. block, _ := aes.NewCipher(key)
  26. if len(encrypted) < aes.BlockSize {
  27. panic("ciphertext too short")
  28. }
  29. iv := encrypted[:aes.BlockSize]
  30. encrypted = encrypted[aes.BlockSize:]
  31. stream := cipher.NewCFBDecrypter(block, iv)
  32. stream.XORKeyStream(encrypted, encrypted)
  33. return encrypted
  34. }
  35. func main() {
  36. source:="hello world"
  37. fmt.Println("原字符:",source)
  38. key:="ABCDEFGHIJKLMNO1"//16位
  39. encryptCode:=AesEncryptCFB([]byte(source),[]byte(key))
  40. fmt.Println("密文:",hex.EncodeToString(encryptCode))
  41. decryptCode:=AesDecryptCFB(encryptCode,[]byte(key))
  42. fmt.Println("解密:",string(decryptCode))
  43. }

OFB模式

  1. package main
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/rand"
  7. "encoding/hex"
  8. "fmt"
  9. "io"
  10. )
  11. func aesEncryptOFB( data[]byte,key []byte) ([]byte, error) {
  12. data = PKCS7Padding(data, aes.BlockSize)
  13. block, _ := aes.NewCipher([]byte(key))
  14. out := make([]byte, aes.BlockSize + len(data))
  15. iv := out[:aes.BlockSize]
  16. if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  17. return nil, err
  18. }
  19. stream := cipher.NewOFB(block, iv)
  20. stream.XORKeyStream(out[aes.BlockSize:], data)
  21. return out, nil
  22. }
  23. func aesDecryptOFB( data[]byte,key []byte) ([]byte, error) {
  24. block, _ := aes.NewCipher([]byte(key))
  25. iv := data[:aes.BlockSize]
  26. data = data[aes.BlockSize:]
  27. if len(data) % aes.BlockSize != 0 {
  28. return nil, fmt.Errorf("data is not a multiple of the block size")
  29. }
  30. out := make([]byte, len(data))
  31. mode := cipher.NewOFB(block, iv)
  32. mode.XORKeyStream(out, data)
  33. out= PKCS7UnPadding(out)
  34. return out, nil
  35. }
  36. //补码
  37. //AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
  38. func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
  39. padding := blocksize - len(ciphertext)%blocksize
  40. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  41. return append(ciphertext, padtext...)
  42. }
  43. //去码
  44. func PKCS7UnPadding(origData []byte) []byte {
  45. length := len(origData)
  46. unpadding := int(origData[length-1])
  47. return origData[:(length - unpadding)]
  48. }
  49. func main() {
  50. source:="hello world"
  51. fmt.Println("原字符:",source)
  52. key:="1111111111111111"//16位 32位均可
  53. encryptCode,_:=aesEncryptOFB([]byte(source),[]byte(key))
  54. fmt.Println("密文:",hex.EncodeToString(encryptCode))
  55. decryptCode,_:=aesDecryptOFB(encryptCode,[]byte(key))
  56. fmt.Println("解密:",string(decryptCode))
  57. }

RSA加密

首先使用openssl生成公私钥

  1. package main
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/base64"
  7. "encoding/pem"
  8. "errors"
  9. "fmt"
  10. )
  11. // 私钥生成
  12. //openssl genrsa -out rsa_private_key.pem 1024
  13. var privateKey = []byte(`
  14. -----BEGIN RSA PRIVATE KEY-----
  15. MIICWwIBAAKBgQDcGsUIIAINHfRTdMmgGwLrjzfMNSrtgIf4EGsNaYwmC1GjF/bM
  16. h0Mcm10oLhNrKNYCTTQVGGIxuc5heKd1gOzb7bdTnCDPPZ7oV7p1B9Pud+6zPaco
  17. qDz2M24vHFWYY2FbIIJh8fHhKcfXNXOLovdVBE7Zy682X1+R1lRK8D+vmQIDAQAB
  18. AoGAeWAZvz1HZExca5k/hpbeqV+0+VtobMgwMs96+U53BpO/VRzl8Cu3CpNyb7HY
  19. 64L9YQ+J5QgpPhqkgIO0dMu/0RIXsmhvr2gcxmKObcqT3JQ6S4rjHTln49I2sYTz
  20. 7JEH4TcplKjSjHyq5MhHfA+CV2/AB2BO6G8limu7SheXuvECQQDwOpZrZDeTOOBk
  21. z1vercawd+J9ll/FZYttnrWYTI1sSF1sNfZ7dUXPyYPQFZ0LQ1bhZGmWBZ6a6wd9
  22. R+PKlmJvAkEA6o32c/WEXxW2zeh18sOO4wqUiBYq3L3hFObhcsUAY8jfykQefW8q
  23. yPuuL02jLIajFWd0itjvIrzWnVmoUuXydwJAXGLrvllIVkIlah+lATprkypH3Gyc
  24. YFnxCTNkOzIVoXMjGp6WMFylgIfLPZdSUiaPnxby1FNM7987fh7Lp/m12QJAK9iL
  25. 2JNtwkSR3p305oOuAz0oFORn8MnB+KFMRaMT9pNHWk0vke0lB1sc7ZTKyvkEJW0o
  26. eQgic9DvIYzwDUcU8wJAIkKROzuzLi9AvLnLUrSdI6998lmeYO9x7pwZPukz3era
  27. zncjRK3pbVkv0KrKfczuJiRlZ7dUzVO0b6QJr8TRAA==
  28. -----END RSA PRIVATE KEY-----
  29. `)
  30. // 公钥: 根据私钥生成
  31. //openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
  32. var publicKey = []byte(`
  33. -----BEGIN PUBLIC KEY-----
  34. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcGsUIIAINHfRTdMmgGwLrjzfM
  35. NSrtgIf4EGsNaYwmC1GjF/bMh0Mcm10oLhNrKNYCTTQVGGIxuc5heKd1gOzb7bdT
  36. nCDPPZ7oV7p1B9Pud+6zPacoqDz2M24vHFWYY2FbIIJh8fHhKcfXNXOLovdVBE7Z
  37. y682X1+R1lRK8D+vmQIDAQAB
  38. -----END PUBLIC KEY-----
  39. `)
  40. // 加密
  41. func RsaEncrypt(origData []byte) ([]byte, error) {
  42. //解密pem格式的公钥
  43. block, _ := pem.Decode(publicKey)
  44. if block == nil {
  45. return nil, errors.New("public key error")
  46. }
  47. // 解析公钥
  48. pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  49. if err != nil {
  50. return nil, err
  51. }
  52. // 类型断言
  53. pub := pubInterface.(*rsa.PublicKey)
  54. //加密
  55. return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
  56. }
  57. // 解密
  58. func RsaDecrypt(ciphertext []byte) ([]byte, error) {
  59. //解密
  60. block, _ := pem.Decode(privateKey)
  61. if block == nil {
  62. return nil, errors.New("private key error!")
  63. }
  64. //解析PKCS1格式的私钥
  65. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  66. if err != nil {
  67. return nil, err
  68. }
  69. // 解密
  70. return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
  71. }
  72. func main() {
  73. data, _ := RsaEncrypt([]byte("hello world"))
  74. fmt.Println(base64.StdEncoding.EncodeToString(data))
  75. origData, _ := RsaDecrypt(data)
  76. fmt.Println(string(origData))
  77. }

参考:

https://www.liaoxuefeng.com/wiki/1016959663602400/1183198304823296

https://studygolang.com/articles/15642?fr=sidebar

https://segmentfault.com/a/1190000004151272

links

  • 目录
  • 上一节:
  • 下一节: