〇、前言

GO 语言的标准库 crypto 提供了一组用于加密和解密的包,包括对称加密、哈希函数、数字签名、随机数生成等功能。在日常开发中,通过使用这些库,可以确保数据的安全性和完整性。

对于使用频率比较高的东西,还是要汇总一下用来备查。

一、md5 加密

md5 包实现了 RFC 1321 中定义的 MD5 哈希算法。

需要注意的是,md5 是可以通过暴力碰撞破解的,因此不可用于安全性要求较高的场景。

  1. package main
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "fmt"
  6. "io"
  7. "strings"
  8. )
  9. func main() {
  10. h := md5.New()
  11. io.WriteString(h, "md5 加密测试!")
  12. fmt.Printf("%x\n", h.Sum(nil))
  13. fmt.Printf("%X\n", h.Sum(nil)) // 大写的 X,代表大写的十六进制字符串
  14. hh := md5.New()
  15. hh.Write([]byte("md5 加密测试!"))
  16. fmt.Print(hex.EncodeToString(hh.Sum(nil)) + "\n")
  17. fmt.Print(strings.ToTitle(hex.EncodeToString(hh.Sum(nil)))) // strings.ToTitle() 转大写
  18. }

二、sha256 字符串、文件加密

sha1 和 md5 类似,都是可以被暴力碰撞破解,因此首先推荐的就是本节主要介绍的 sha256,结果为 64 位十六进制的字符串。

其实 sha1、sha256、sha512 等等用法都是类似的,均适用如下代码实现方式:

  1. package main
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "fmt"
  6. "io"
  7. "log"
  8. "os"
  9. "strings"
  10. )
  11. func main() {
  12. // 对字符串加密,方式一
  13. h := sha256.New()
  14. h.Write([]byte("sha256 加密测试!"))
  15. fmt.Printf("%x\n", h.Sum(nil))
  16. fmt.Printf("%X\n", h.Sum(nil)) // 大写的 X,代表大写的十六进制字符串
  17. // 对字符串加密,方式二
  18. hh := sha256.New()
  19. hh.Write([]byte("sha256 加密测试!"))
  20. fmt.Print(hex.EncodeToString(hh.Sum(nil)) + "\n")
  21. fmt.Print(strings.ToTitle(hex.EncodeToString(hh.Sum(nil))) + "\n")
  22. // 对文件进行加密
  23. f, err := os.Open("file.txt")
  24. if err != nil {
  25. log.Fatal(err)
  26. }
  27. defer f.Close()
  28. h2 := sha256.New()
  29. if _, err := io.Copy(h2, f); err != nil {
  30. log.Fatal(err)
  31. }
  32. fmt.Printf("%x\n", h2.Sum(nil))
  33. fmt.Printf("%X", h2.Sum(nil))
  34. }

三、rsa 加密解密以及密钥生成

RSA 是一种非对称加密算法,它的名字是由它的三位开发者,即 Ron.Rivest、Adi.Shamir 和 Leonard.Adleman 的姓氏的首字母组成的(Rivest-Shamir-Adleman),可用于数据加密和数字签名。

用于数据加密时,消息发送方利用对方的公钥进行加密,消息接受方收到密文时使用自己的私钥进行解密。

如下代码,包含了生成密钥和加解密:(其中包含了 byte 类型和 base64 类型互相转换的操作)

  1. package main
  2. import (
  3. "crypto/rand"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/base64"
  7. "encoding/pem"
  8. "fmt"
  9. "os"
  10. )
  11. func main() {
  12. // 生成密钥对,保存到文件
  13. GenerateRSAKey(2048)
  14. message := []byte("rsa 加密解密测试!")
  15. // 加密
  16. cipherText := RSA_Encrypt(message, "public.pem")
  17. cipherText_base64 := base64.StdEncoding.EncodeToString(cipherText) // 将 []byte 类型的密文转换为 base64 字符串
  18. fmt.Println("加密后为(base64):", cipherText_base64)
  19. fmt.Println("加密后为([]byte):", cipherText)
  20. // 解密
  21. cipherText, _ = base64.StdEncoding.DecodeString(cipherText_base64) // 若转换为输入为 base64 字符串,则需先解码为 []byte
  22. plainText := RSA_Decrypt(cipherText, "private.pem")
  23. fmt.Println("解密后为([]byte):", plainText)
  24. fmt.Println("解密后为(string):", string(plainText))
  25. }
  26. // 生成 RSA 私钥和公钥,保存到文件中
  27. func GenerateRSAKey(bits int) {
  28. // GenerateKey 函数使用随机数据生成器 random 生成一对具有指定字位数的 RSA 密钥
  29. // Reader 是一个全局、共享的密码用强随机数生成器
  30. privateKey, err := rsa.GenerateKey(rand.Reader, bits)
  31. if err != nil {
  32. panic(err)
  33. }
  34. // 保存私钥
  35. // 通过 x509 标准将得到的 ras 私钥序列化为 ASN.1 的 DER 编码字符串
  36. X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
  37. // 使用 pem 格式对 x509 输出的内容进行编码
  38. // 创建文件保存私钥
  39. privateFile, err := os.Create("private.pem")
  40. if err != nil {
  41. panic(err)
  42. }
  43. defer privateFile.Close()
  44. // 构建一个 pem.Block 结构体对象
  45. privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey}
  46. // 将数据保存到文件
  47. pem.Encode(privateFile, &privateBlock)
  48. // 保存公钥
  49. // 获取公钥的数据
  50. publicKey := privateKey.PublicKey
  51. // X509 对公钥编码
  52. X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
  53. if err != nil {
  54. panic(err)
  55. }
  56. // pem 格式编码
  57. // 创建用于保存公钥的文件
  58. publicFile, err := os.Create("public.pem")
  59. if err != nil {
  60. panic(err)
  61. }
  62. defer publicFile.Close()
  63. // 创建一个 pem.Block 结构体对象
  64. publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey}
  65. // 保存到文件
  66. pem.Encode(publicFile, &publicBlock)
  67. }
  68. // RSA 加密
  69. func RSA_Encrypt(plainText []byte, path string) []byte {
  70. // 打开文件
  71. file, err := os.Open(path)
  72. if err != nil {
  73. panic(err)
  74. }
  75. defer file.Close()
  76. // 读取文件的内容
  77. info, _ := file.Stat()
  78. buf := make([]byte, info.Size())
  79. file.Read(buf)
  80. // pem 解码
  81. block, _ := pem.Decode(buf)
  82. // x509 解码
  83. publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  84. if err != nil {
  85. panic(err)
  86. }
  87. // 类型断言
  88. publicKey := publicKeyInterface.(*rsa.PublicKey)
  89. // 对明文进行加密
  90. cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
  91. if err != nil {
  92. panic(err)
  93. }
  94. // 返回 []byte 密文
  95. return cipherText
  96. }
  97. // RSA 解密
  98. func RSA_Decrypt(cipherText []byte, path string) []byte {
  99. // 打开文件
  100. file, err := os.Open(path)
  101. if err != nil {
  102. panic(err)
  103. }
  104. defer file.Close()
  105. // 获取文件内容
  106. info, _ := file.Stat()
  107. buf := make([]byte, info.Size())
  108. file.Read(buf)
  109. // pem 解码
  110. block, _ := pem.Decode(buf)
  111. // X509 解码
  112. privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  113. if err != nil {
  114. panic(err)
  115. }
  116. // 对密文进行解密
  117. plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
  118. // 返回明文
  119. return plainText
  120. }

运行生成密钥方法后,main.go 的同级目录下,回自动生成两个 .pem 后缀的密钥文件:

下面是加解密输出的结果:

 参考:https://blog.csdn.net/chenxing1230/article/details/83757638

四、sm2 加解密以及签名验证

加密库 crypto 中其实是不包含 sm2 的,但是它毕竟是国家公钥密码算法的标准,有很广的使用度,因此必须安排。

国密 SM2 为非对称加密,也称为公钥密码。它是我国在吸收国际先进成果基础上研发出来的具有自主知识产权的 ECC(椭圆曲线公钥密码算法),它在安全性和实现效率方面相当于或略优于国际上同类的 ECC 算法,能取代 RSA 以满足各种应用对公钥密码算法安全性和实现效率的更高要求,这也是国家主推此加密方法的原因。

以下示例一开源库 https://github.com/tjfoc/gmsm 为基础实现:

  1. // 安装必要的模块
  2. go get github.com/tjfoc/gmsm/sm2
  3. go get github.com/tjfoc/gmsm/x509
  4. // 整理全部模块
  5. go mod tidy
  1. package main
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "fmt"
  6. "os"
  7. "github.com/tjfoc/gmsm/sm2"
  8. "github.com/tjfoc/gmsm/x509"
  9. )
  10. type GMCrypt struct {
  11. PublicFile string
  12. PrivateFile string
  13. }
  14. var (
  15. path = "./"
  16. privateFile = "sm2private.pem" // 私钥文件
  17. publicFile = "sm2public.pem" // 公钥文件
  18. data = "hello 国密"
  19. )
  20. // 测试一下
  21. func main() {
  22. GenerateSM2Key() // 密钥生成并保存在文件中
  23. crypt := GMCrypt{
  24. PublicFile: path + publicFile,
  25. PrivateFile: path + privateFile,
  26. }
  27. encryptText, _ := crypt.Encrypt(data) // 加密
  28. fmt.Println(encryptText)
  29. decryptText, _ := crypt.Decrypt(encryptText) // 解密
  30. fmt.Println(decryptText)
  31. msg := []byte("hello 国密")
  32. sig, key, _ := CreateSm2Sig(msg) // 签名
  33. fmt.Printf("签名结果:%x\n公钥:%v, \n", sig, key)
  34. verSm2Sig := VerSm2Sig(key, msg, sig) // 验证签名
  35. fmt.Println("验证结果为:", verSm2Sig)
  36. }
  37. // 生成公钥、私钥
  38. func GenerateSM2Key() {
  39. // 生成私钥、公钥
  40. priKey, err := sm2.GenerateKey(rand.Reader)
  41. if err != nil {
  42. fmt.Println("秘钥产生失败:", err)
  43. os.Exit(1)
  44. }
  45. pubKey := &priKey.PublicKey
  46. // 生成文件 保存私钥、公钥
  47. // x509 编码
  48. pemPrivKey, _ := x509.WritePrivateKeyToPem(priKey, nil)
  49. privateFile, _ := os.Create(path + privateFile)
  50. defer privateFile.Close()
  51. privateFile.Write(pemPrivKey)
  52. pemPublicKey, _ := x509.WritePublicKeyToPem(pubKey)
  53. publicFile, _ := os.Create(path + publicFile)
  54. defer publicFile.Close()
  55. publicFile.Write(pemPublicKey)
  56. }
  57. // 读取密钥文件
  58. func readPemCxt(path string) ([]byte, error) {
  59. file, err := os.Open(path)
  60. if err != nil {
  61. return []byte{}, err
  62. }
  63. defer file.Close()
  64. fileInfo, err := file.Stat()
  65. if err != nil {
  66. return []byte{}, err
  67. }
  68. buf := make([]byte, fileInfo.Size())
  69. _, err = file.Read(buf)
  70. if err != nil {
  71. return []byte{}, err
  72. }
  73. return buf, err
  74. }
  75. // 加密
  76. func (s *GMCrypt) Encrypt(data string) (string, error) {
  77. pub, err := readPemCxt(s.PublicFile)
  78. if err != nil {
  79. return "", err
  80. }
  81. // read public key
  82. publicKeyFromPem, err := x509.ReadPublicKeyFromPem(pub)
  83. if err != nil {
  84. fmt.Println(err)
  85. return "", err
  86. }
  87. ciphertxt, err := publicKeyFromPem.EncryptAsn1([]byte(data), rand.Reader)
  88. if err != nil {
  89. return "", err
  90. }
  91. return base64.StdEncoding.EncodeToString(ciphertxt), nil
  92. }
  93. // 解密
  94. func (s *GMCrypt) Decrypt(data string) (string, error) {
  95. pri, err := readPemCxt(s.PrivateFile)
  96. if err != nil {
  97. return "", err
  98. }
  99. privateKeyFromPem, err := x509.ReadPrivateKeyFromPem(pri, nil)
  100. if err != nil {
  101. return "", err
  102. }
  103. ciphertxt, err := base64.StdEncoding.DecodeString(data)
  104. if err != nil {
  105. return "", err
  106. }
  107. plaintxt, err := privateKeyFromPem.DecryptAsn1(ciphertxt)
  108. if err != nil {
  109. return "", err
  110. }
  111. return string(plaintxt), nil
  112. }
  113. // 使用私钥创建签名
  114. func CreateSm2Sig(msg []byte) ([]byte, *sm2.PublicKey, error) {
  115. // 读取密钥
  116. pri, _ := readPemCxt(path + privateFile)
  117. privateKey, _ := x509.ReadPrivateKeyFromPem(pri, nil)
  118. c := sm2.P256Sm2() // 椭圆曲线
  119. priv := new(sm2.PrivateKey)
  120. priv.PublicKey.Curve = c
  121. priv.D = privateKey.D
  122. priv.PublicKey.X = privateKey.X
  123. priv.PublicKey.Y = privateKey.Y
  124. sign, err := priv.Sign(rand.Reader, msg, nil) // sm2签名
  125. if err != nil {
  126. return nil, nil, err
  127. }
  128. return sign, &priv.PublicKey, err
  129. }
  130. // 验证签名
  131. func VerSm2Sig(pub *sm2.PublicKey, msg []byte, sign []byte) bool {
  132. isok := pub.Verify(msg, sign)
  133. return isok
  134. }

参考:https://blog.csdn.net/weixin_42117918/article/details/130558002

五、aes 加解密

AES 密码与分组密码 Rijndael 基本上完全一致,Rijndael 分组大小和密钥大小都可以为 128 位、192 位和256 位。然而 AES 只要求分组大小为 128 位,因此只有分组长度为 128Bit 的 Rijndael 才称为 AES 算法。但这并不妨碍三种密码的相同使用环境。

5.1 对字符串加解密

  1. package main
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "encoding/base64"
  7. "errors"
  8. "fmt"
  9. )
  10. // 测试一下
  11. func main() {
  12. data := "aes 加密测试!"
  13. // 加密
  14. enstr, _ := EncryptByAes([]byte(data))
  15. // 解密
  16. destr, _ := DecryptByAes(enstr)
  17. // 打印
  18. fmt.Printf(" 加密:%v\n 解密:%s", enstr, destr)
  19. }
  20. var PwdKey = []byte("ABCDABCDABCDABCD") // 三种密码标准:128 位、192 位和 256 位,对应字符串位数 16、32、64
  21. // EncryptByAes Aes加密 后 base64 再加
  22. func EncryptByAes(data []byte) (string, error) {
  23. res, err := AesEncrypt(data, PwdKey)
  24. if err != nil {
  25. return "", err
  26. }
  27. return base64.StdEncoding.EncodeToString(res), nil
  28. }
  29. // DecryptByAes Aes 解密
  30. func DecryptByAes(data string) ([]byte, error) {
  31. dataByte, err := base64.StdEncoding.DecodeString(data)
  32. if err != nil {
  33. return nil, err
  34. }
  35. return AesDecrypt(dataByte, PwdKey)
  36. }
  37. // 加密
  38. func AesEncrypt(data []byte, key []byte) ([]byte, error) {
  39. // 创建加密实例
  40. block, err := aes.NewCipher(key)
  41. if err != nil {
  42. return nil, err
  43. }
  44. // 判断加密快的大小
  45. blockSize := block.BlockSize()
  46. // 填充
  47. encryptBytes := pkcs7Padding(data, blockSize)
  48. // 初始化加密数据接收切片
  49. crypted := make([]byte, len(encryptBytes))
  50. // 使用cbc加密模式
  51. blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // Cipher Block Chaining:加密块链
  52. // 执行加密
  53. blockMode.CryptBlocks(crypted, encryptBytes)
  54. return crypted, nil
  55. }
  56. // 解密
  57. func AesDecrypt(data []byte, key []byte) ([]byte, error) {
  58. // 创建实例
  59. block, err := aes.NewCipher(key)
  60. if err != nil {
  61. return nil, err
  62. }
  63. // 获取块的大小
  64. blockSize := block.BlockSize()
  65. // 使用cbc
  66. blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // Cipher Block Chaining:加密块链
  67. // 初始化解密数据接收切片
  68. crypted := make([]byte, len(data))
  69. // 执行解密
  70. blockMode.CryptBlocks(crypted, data)
  71. // 去除填充
  72. crypted, err = pkcs7UnPadding(crypted)
  73. if err != nil {
  74. return nil, err
  75. }
  76. return crypted, nil
  77. }
  78. // pkcs7Padding 填充
  79. func pkcs7Padding(data []byte, blockSize int) []byte {
  80. // 判断缺少几位长度。最少1,最多 blockSize
  81. padding := blockSize - len(data)%blockSize
  82. // 补足位数。把切片[]byte{byte(padding)}复制padding个
  83. padText := bytes.Repeat([]byte{byte(padding)}, padding)
  84. return append(data, padText...)
  85. }
  86. // pkcs7UnPadding 填充的反向操作
  87. func pkcs7UnPadding(data []byte) ([]byte, error) {
  88. length := len(data)
  89. if length == 0 {
  90. return nil, errors.New("加密字符串错误!")
  91. }
  92. // 获取填充的个数
  93. unPadding := int(data[length-1])
  94. return data[:(length - unPadding)], nil
  95. }

5.2 对文件加解密

此部分是在字符串加解密基础上,先读取文件内容,然后和加密字符串一样,将 []byte 类型的数据加密即可。

对于单行超大文本文件,加密时就需要分片去读,加密后字符串写入文件中,每次加密写入一行,一定要换行,不然解密的时候区分不出来。非单行的可以逐行加密,密文也是逐行写入文本中。解密时,逐行读取解密文件,每一行为一个密文字串,将其解密,写入到文本中。

  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/aes"
  6. "crypto/cipher"
  7. "encoding/base64"
  8. "errors"
  9. "fmt"
  10. "os"
  11. "time"
  12. )
  13. func main() {
  14. startTime := time.Now()
  15. // EncryptFile("file.txt", "secuityfile.txt")
  16. DecryptFile("encryptFile_secuityfile.txt", "file_new.txt")
  17. fmt.Printf("耗时:%v", time.Since(startTime))
  18. }
  19. var PwdKey = []byte("ABCDABCDABCDABCD") // 三种密码标准:128 位、192 位和 256 位,对应字符串位数 16、32、64
  20. // EncryptByAes Aes加密 后 base64 再加
  21. func EncryptByAes(data []byte) (string, error) {
  22. res, err := AesEncrypt(data, PwdKey)
  23. if err != nil {
  24. return "", err
  25. }
  26. return base64.StdEncoding.EncodeToString(res), nil
  27. }
  28. // DecryptByAes Aes 解密
  29. func DecryptByAes(data string) ([]byte, error) {
  30. dataByte, err := base64.StdEncoding.DecodeString(data)
  31. if err != nil {
  32. return nil, err
  33. }
  34. return AesDecrypt(dataByte, PwdKey)
  35. }
  36. // 加密
  37. func AesEncrypt(data []byte, key []byte) ([]byte, error) {
  38. // 创建加密实例
  39. block, err := aes.NewCipher(key)
  40. if err != nil {
  41. return nil, err
  42. }
  43. // 判断加密快的大小
  44. blockSize := block.BlockSize()
  45. // 填充
  46. encryptBytes := pkcs7Padding(data, blockSize)
  47. // 初始化加密数据接收切片
  48. crypted := make([]byte, len(encryptBytes))
  49. // 使用cbc加密模式
  50. blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // Cipher Block Chaining:加密块链
  51. // 执行加密
  52. blockMode.CryptBlocks(crypted, encryptBytes)
  53. return crypted, nil
  54. }
  55. // 解密
  56. func AesDecrypt(data []byte, key []byte) ([]byte, error) {
  57. // 创建实例
  58. block, err := aes.NewCipher(key)
  59. if err != nil {
  60. return nil, err
  61. }
  62. // 获取块的大小
  63. blockSize := block.BlockSize()
  64. // 使用cbc
  65. blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) // Cipher Block Chaining:加密块链
  66. // 初始化解密数据接收切片
  67. crypted := make([]byte, len(data))
  68. // 执行解密
  69. blockMode.CryptBlocks(crypted, data)
  70. // 去除填充
  71. crypted, err = pkcs7UnPadding(crypted)
  72. if err != nil {
  73. return nil, err
  74. }
  75. return crypted, nil
  76. }
  77. // pkcs7Padding 填充
  78. func pkcs7Padding(data []byte, blockSize int) []byte {
  79. // 判断缺少几位长度。最少1,最多 blockSize
  80. padding := blockSize - len(data)%blockSize
  81. // 补足位数。把切片[]byte{byte(padding)}复制padding个
  82. padText := bytes.Repeat([]byte{byte(padding)}, padding)
  83. return append(data, padText...)
  84. }
  85. // pkcs7UnPadding 填充的反向操作
  86. func pkcs7UnPadding(data []byte) ([]byte, error) {
  87. length := len(data)
  88. if length == 0 {
  89. return nil, errors.New("加密字符串错误!")
  90. }
  91. // 获取填充的个数
  92. unPadding := int(data[length-1])
  93. return data[:(length - unPadding)], nil
  94. }
  95. // EncryptFile 文件加密,filePath 需要加密的文件路径 ,fName加密后文件名
  96. func EncryptFile(filePath, fName string) (err error) {
  97. f, err := os.Open(filePath)
  98. if err != nil {
  99. fmt.Println("未找到文件")
  100. return
  101. }
  102. defer f.Close()
  103. fInfo, _ := f.Stat()
  104. fLen := fInfo.Size()
  105. fmt.Println("待处理文件大小:", fLen)
  106. maxLen := 1024 * 1024 * 100 // 100mb 每 100mb 进行加密一次
  107. var forNum int64 = 0
  108. getLen := fLen
  109. if fLen > int64(maxLen) {
  110. getLen = int64(maxLen)
  111. forNum = fLen / int64(maxLen)
  112. fmt.Println("需要加密次数:", forNum+1)
  113. }
  114. // 加密后存储的文件
  115. ff, err := os.OpenFile("encryptFile_"+fName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
  116. if err != nil {
  117. fmt.Println("文件写入错误")
  118. return err
  119. }
  120. defer ff.Close()
  121. // 循环加密,并写入文件
  122. for i := 0; i < int(forNum+1); i++ {
  123. a := make([]byte, getLen)
  124. n, err := f.Read(a)
  125. if err != nil {
  126. fmt.Println("文件读取错误")
  127. return err
  128. }
  129. getByte, err := EncryptByAes(a[:n])
  130. if err != nil {
  131. fmt.Println("加密错误")
  132. return err
  133. }
  134. // 换行处理,有点乱了,想到更好的再改
  135. getBytes := append([]byte(getByte), []byte("\n")...)
  136. // 写入
  137. buf := bufio.NewWriter(ff)
  138. buf.WriteString(string(getBytes[:]))
  139. buf.Flush()
  140. }
  141. ffInfo, _ := ff.Stat()
  142. fmt.Printf("文件加密成功,生成文件名为:%s,文件大小为:%v Byte \n", ffInfo.Name(), ffInfo.Size())
  143. return nil
  144. }
  145. // DecryptFile 文件解密
  146. func DecryptFile(filePath, fName string) (err error) {
  147. f, err := os.Open(filePath)
  148. if err != nil {
  149. fmt.Println("未找到文件")
  150. return
  151. }
  152. defer f.Close()
  153. fInfo, _ := f.Stat()
  154. fmt.Println("待处理文件大小:", fInfo.Size())
  155. br := bufio.NewReader(f)
  156. ff, err := os.OpenFile("decryptFile_"+fName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
  157. if err != nil {
  158. fmt.Println("文件写入错误")
  159. return err
  160. }
  161. defer ff.Close()
  162. num := 0
  163. // 逐行读取密文,进行解密,写入文件
  164. for {
  165. num = num + 1
  166. a, err := br.ReadString('\n')
  167. if err != nil {
  168. break
  169. }
  170. getByte, err := DecryptByAes(a)
  171. if err != nil {
  172. fmt.Println("解密错误")
  173. return err
  174. }
  175. buf := bufio.NewWriter(ff)
  176. buf.Write(getByte)
  177. buf.Flush()
  178. }
  179. fmt.Println("解密次数:", num)
  180. ffInfo, _ := ff.Stat()
  181. fmt.Printf("文件解密成功,生成文件名为:%s,文件大小为:%v Byte \n", ffInfo.Name(), ffInfo.Size())
  182. return
  183. }

5.3 明文长度与密文长度关系

n 明文长度 密文长度
1 0~15 24
2 16~31 44
3 32~47 64
4 48~63 88
5 64~79 108
6 80~95 128
7 96~111 152
... ... ...
n 16(n-1) ~ (16n-1) 20n+(n/3+1)x4     (/ :除法取整)

参考:https://www.jianshu.com/p/0caab60fea9f   https://cloud.tencent.com/developer/section/1140756

crypto 加解密库简介与测试【GO 常用的库】的更多相关文章

  1. RSA加解密用途简介及java示例

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...

  2. KingbaseES R6 集群备库网卡down测试案例

    数据库版本: test=# select version(); version ------------------------------------------------------------ ...

  3. C#调用Crypto++库AES ECB CBC加解密

    本文章使用上一篇<C#调用C++类库例子>的项目代码作为Demo.本文中,C#将调用C++的Crypto++库,实现AES的ECB和CBC加解密. 一.下载Crypto 1.进入Crypt ...

  4. Crypto++入门学习笔记(DES、AES、RSA、SHA-256)(加解密)

    转自http://www.cppblog.com/ArthasLee/archive/2010/12/01/135186.html 最近,基于某些原因和需要,笔者需要去了解一下Crypto++库,然后 ...

  5. [dev][dpdk][crypto] dpdk加解密设备与IPSEC

    概述 分三部分,加解密框架(crypto framework),加解密设备(crypto dev),安全协议(Security Framework) ×  API,设计思路等,都在加解密框架里:见文档 ...

  6. 加解密 3DES AES RSA 简介 示例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. 介绍一个很好用的Rsa加解密的.Net库 Kalix.ApiCrypto

    Rsa非对称加密技术 这个就不说了,大家上网搜索都知道,公钥加密,私钥解密.当然大家也可以自己实现.这里就懒了,就去找一个现成的库,Nuget上搜索,GitHub上搜索,发现.Net的加解密库,下载量 ...

  8. POCO库——Foundation组件之加解密Crypt

    加解密Crypt:内部提供多种加解密方式.信息摘要提取.随机数产生等,具体的算法内部实现不做研究学习: DigestEngine.h :DigestEngine类作为各种摘要提取的基类,提供必要的接口 ...

  9. RSA加解密 私钥加密公钥解密 私加公解 && C++ 调用openssl库 的代码实例

    前提:秘钥长度=1024 ============================================== 对一片(117字节)明文加密  私加 ===================== ...

  10. DES加解密 cbc模式 的简单讲解 && C++用openssl库来实现的注意事项

    DES cbc是基于数据块加密的.数据块的长度为8字节64bit.以数据块为单位循环加密,再拼接.每个数据块加密的秘钥一样,IV向量不同.第一个数据快所需的IV向量,需要我们提供,从第二个数据块开始, ...

随机推荐

  1. elment UI + EasyExcel 实现 导入

    前端组件 <hd-flex> <el-dialog v-model="isUploadDialog" width="50%" lock-scr ...

  2. Road

    首先进行端口扫描22 80 使用nmap进行vuln nmap -sS --script=vuln 10.10.236.244 10.10.236.244/v2/admin/login.html 随便 ...

  3. ChatGPT 时代,程序员的生存之道 | 人工智能 AI

    前言 ChatGPT 近期炙手可热,仿佛没有什么问题是它不能解决的.出于对 ChatGPT 的好奇,我们决定探索下它对于前端开发人员来讲,是作为辅助工具多一些,还是主力工具更多一些? 2D 能力测试 ...

  4. WPF实现新手引导

    1. 半透明灰的遮罩层 新建一个遮盖的window窗体 canvas是后期可以在思显示高亮区域 //定义一个window将它的样式设置透明等可以覆盖到其他窗体上,其中遮罩层使用border控件 //原 ...

  5. 全同态(Fully Homomorphic Encryption, FHE)和半同态(Partially Homomorphic Encryption, PHE)介绍

    全同态(Fully Homomorphic Encryption, FHE)和半同态(Partially Homomorphic Encryption, PHE) 全同态加密(FHE)是指一种加密方案 ...

  6. 关于SQL SERVER 字段类型char(n) , nchar(n) , varchar(n) , nvarchar(n)

    对于很多新手来说,经常被字段类型搞得晕头转向,今天我用通俗易懂的解释帮大家理解这些类型. 在数据库字段类型定义中,可以分为两大类,一类为Unicode类型,另一种就是非Unicode. Unicode ...

  7. Sentieon实战:NGS肿瘤变异检测流程

    肿瘤基因突变检测是NGS的一个重要应用,其分析难点主要在于低频变异的准确性.不同于遗传病检测,肿瘤样本类型多样,测序方法和参数复杂,且缺乏对应各种场景的公共标准真集.再加上常用开源软件经常遇到的准确性 ...

  8. Unity中的RegisterPlugins:深入解析与实用案例

    Unity中的RegisterPlugins:深入解析与实用案例 在Unity游戏开发中,我们经常需要使用第三方插件来实现一些特定的功能.为了让这些插件能够在Unity中正常工作,我们需要对它们进行注 ...

  9. Qt源码阅读(五)-deleteLater

    Qt deleteLater作用及源码分析 个人经验总结,如有错误或遗漏,欢迎各位大佬指正 在本篇文章中,我们将深入分析源码,探讨deleteLater的原理. deleteLater是Qt框架提供的 ...

  10. 现代C++(Modern C++)基本用法实践:三、移动语义

    概述 移动 移动(move)语义C++引入了一种新的内存优化,以避免不必要的拷贝.在构造或者赋值的时候,如果实参是右值(或者左值由std::move转换成右值),便会匹配移动语义的函数调用如下述举例的 ...