请选择 进入手机版 | 继续访问电脑版

[Golang] Go中使用 加密算法的方法

[复制链接]
查看47 | 回复8 | 2021-9-15 01:12:32 | 显示全部楼层 |阅读模式
目次

哈希算法

 

  1. md5
复制代码

  1. 128bit,16字节
  2. 如:md5 (“hello world!”) = fc3ff98e8c6a0d3087d515c0473f8677 // 32位16进制数字
复制代码
  1. func Test(t *testing.T) {
  2. //方法一
  3. str := "hello world!"
  4. has := md5.Sum([]byte(str))
  5. md5str1 := fmt.Sprintf("%x", has) //将[]byte转成16进制
  6. t.Log(md5str1)
  7. //方法二
  8. w := md5.New()
  9. io.WriteString(w, str)
  10. md5str2 := fmt.Sprintf("%x", w.Sum(nil))
  11. t.Log(md5str2)
  12. }
复制代码

SHA1

  1. 160bit,20字节
  2. 如:SHA1 (“hello world!”) = 430ce34d020724ed75a196dfc2ad67c77772d169 // 40位16进制数字
复制代码
  1. func Test(t *testing.T) {
  2. str := "hello world!"
  3. //产生一个散列值得方式是 sha1.New(),sha1.Write(bytes),然后 sha1.Sum([]byte{})。
  4. h := sha1.New()
  5. //写入要处理的字节。
  6. h.Write([]byte(str))
  7. //SHA1 值经常以 16 进制输出,例如在 git commit 中。
  8. t.Log(hex.EncodeToString(h.Sum(nil)))
  9. }
复制代码

RIPEMD-160

  1. 160bit,20字节
  2. 如:RIPEMD-160 (“hello world!”) = dffd03137b3a333d5754813399a5f437acd694e5 // 40位16进制数字
复制代码
  1. func Test(t *testing.T) {
  2. str := "hello world!"
  3. h := ripemd160.New()
  4. h.Write([]byte(str))
  5. t.Log(hex.EncodeToString(h.Sum(nil)))
  6. }
复制代码

SHA256

  1. 256bit,32字节
  2. 如:SHA256 (“hello world!”) = 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9 // 64位16进制数字
复制代码
  1. func Test(t *testing.T) {
  2. str := "hello world!"
  3. // 第一种调用方法
  4. sum := sha256.Sum256([]byte(str))
  5. t.Logf("%x\n", sum)
  6. // 第二种调用方法
  7. h := sha256.New()
  8. io.WriteString(h,str)
  9. t.Log(hex.EncodeToString(h.Sum(nil)))
  10. }
复制代码
  1. SHA256实现原理
  2. SHA-256算法输⼊报⽂的最⼤⻓度不超过2^64 bit,输⼊按512bit分组进⾏处理,产⽣的输出是⼀个256bit的报⽂摘要。
  3. SHA256算法包括以下⼏步:
  4. 附加填充⽐特
  5. 对报⽂进⾏填充,使报⽂⻓度与448 模512 同余(⻓度=448 mod512),填充的⽐特数范围是1 到512,填充⽐特串的最⾼位为1,其余位为0。就是先在报⽂后⾯加⼀个 1,再加很多个0,直到⻓度满⾜mod512=448。为什么是448,因为448+64=512。第⼆步会加上⼀个64bit的原始报⽂的 ⻓度信息。附加⻓度值
  6. 将⽤64bit 表示的初始报⽂(填充前)的位⻓度附加在步骤1的结果后(低位字节优先)初始化缓存
  7. 使⽤⼀个256bit 的缓存来存放该散列函数的中间及最终结果。该缓存表示为:
  8. A=0x6A09E667
  9. B=0xBB67AE85
  10. C=0x3C6EF372
  11. D=0xA54FF53A
  12. E=0x510E527F
  13. F=0x9B05688C
  14. G=0x1F83D9AB
  15. H=0x5BE0CD19处理512bit(16 个字)报⽂分组序列
  16. 该算法使⽤了六种基本逻辑函数,由64 步迭代运算组成。每步都以256bit 缓存ABCDEFGH 为输⼊,然后更新缓存内容。每步使⽤⼀个32bit 常数值Kt 和⼀个32bit Wt。
复制代码

SHA512

  1. 512bit,64字节
  2. 如:SHA512 (“hello world!”) = db9b1cd3262dee37756a09b9064973589847caa8e53d31a9d142ea2701b1b28abd97838bb9a27068ba305dc8d04a45a1fcf079de54d607666996b3cc54f6b67c // 128位16进制数字
复制代码
  1. func Test(t *testing.T) {
  2. str := "hello world!"
  3. // 第一种调用方法
  4. sum := sha512.Sum512([]byte(str))
  5. t.Logf("%x\n", sum)
  6. // 第二种调用方法
  7. h := sha512.New()
  8. io.WriteString(h,str)
  9. t.Log(hex.EncodeToString(h.Sum(nil)))
  10. }
复制代码

加密模式

加密一样寻常 分为对称加密(Symmetric Key Encryption)和非对称加密(Asymmetric Key Encryption)。

对称加密又分为分组加密和序列暗码 。

分组暗码 ,也叫块加密(block cyphers),一次加密明文中的一个块。是将明文按肯定 的位长分组,明文组颠末 加密运算得到密文组,密文组颠末 解密运算(加密运算的逆运算),还原成明文组。

序列暗码 ,也叫流加密(stream cyphers),一次加密明文中的一个位。是教唆 用 少量的密钥(制乱元素)通过某种复杂的运算(暗码 算法)产生大量的伪随机位流,用于对明文位流的加密。

解密是指用同样的密钥和暗码 算法及与加密雷同 的伪随机位流,用以还原明文位流。

分组加密算法中,有ECB,CBC,CFB,OFB这几种算法模式。

加密模式 表明
ECB 最基本的加密模式,也就是通常明确 的加密,雷同 的明⽂将永世 加密成雷同 的密⽂,⽆初始向量,轻易 受到暗码 本重放攻击,⼀般环境 下很少⽤
CBC 明⽂被加密前要与前⾯的密⽂进⾏异或运算后再加密,因此只要选择不同的初始向量,雷同 的密⽂加密后会形成不同的密⽂,这是⽬前应⽤最⼴泛的模式。CBC加密后的密⽂是上下⽂相干 的,但明⽂的错误不会传递到后续分组,但假如 ⼀个分组丢失,后⾯的分组将全部取消 (同步错误)
CFB 雷同 于⾃同步序列暗码 ,分组加密后,按8位分组将密⽂和明⽂进⾏移位异或后得到输出同时反馈回移位寄存器,长处 最⼩可以按字节进⾏加解密,也可以是n位的,CFB也是上下⽂相干 的,CFB模式下,明⽂的⼀个错误会影响后⾯的密⽂(错误扩散)。
OFB 将分组暗码 作为同步序列暗码 运⾏,和CFB相似,不过OFB⽤的是前⼀个n位密⽂输出分组反馈回移位寄存器,OFB没有错误扩散标题

对称加密

最常用的对称加密算法DES、3DES(TripleDES)和AES,常采用的添补 ⽅式是NoPadding(不添补 )、Zeros添补 (0添补 )、PKCS5Padding添补 。

加密算法要求明文必要 按肯定 长度对齐,叫做块大小(BlockSize),比如8字节,那么对于一段恣意 的数据,加密前必要 对末了 一个块添补 到8 字节,解密后必要 删除掉添补 的数据。

添补 ⽅式 表明
ZeroPadding 数据长度不对齐时使用 0添补 ,否则不添补
PKCS7Padding 假设数据长度必要 添补 n(n>0)个字节才对齐,那么添补 n个字节,每个字节都是n;假如 数据本身就已经对齐了,则添补 一块长度为块大小的数据,每个字节都是块大小
PKCS5Padding PKCS7Padding的子集,块大小固定为8字节
  1. 由于使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据,而使用ZeroPadding填充时,没办法区分真实数据与填充数据,所以只适合以\0结尾的字符串加解密。
复制代码

对称加密必要 的添补 函数

  1. func PKCS5Padding(data []byte, blockSize int) []byte {
  2. padding := blockSize - len(data)%blockSize
  3. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  4. return append(data, padtext...)
  5. }
  6. func PKCS5UnPadding(data []byte) []byte {
  7. length := len(data)
  8. // 去掉最后⼀个字节 unpadding 次
  9. unpadding := int(data[length-1])
  10. return data[:(length - unpadding)]
  11. }
  12. func ZeroPadding(data []byte, blockSize int) []byte {
  13. padding := blockSize - len(data)%blockSize
  14. padtext := bytes.Repeat([]byte{0}, padding)
  15. return append(data, padtext...)
  16. }
  17. func ZeroUnPadding(data []byte) []byte {
  18. return bytes.TrimRightFunc(data, func(r rune) bool {
  19. return r == rune(0)
  20. })
  21. }
复制代码

DES

  1. //DES加密字节数组,返回字节数组
  2. func DesEncrypt(originalBytes, key []byte) ([]byte, error) {
  3. block, err := des.NewCipher(key)
  4. if err != nil {
  5. return nil, err
  6. }
  7. originalBytes = PKCS5Padding(originalBytes, block.BlockSize())
  8. blockMode := cipher.NewCBCEncrypter(block, key)
  9. cipherArr := make([]byte, len(originalBytes))
  10. blockMode.CryptBlocks(cipherArr, originalBytes)
  11. return cipherArr, nil
  12. }
  13. //DES解密字节数组,返回字节数组
  14. func DesDecrypt(cipherBytes, key []byte) ([]byte, error) {
  15. block, err := des.NewCipher(key)
  16. if err != nil {
  17. return nil, err
  18. }
  19. blockMode := cipher.NewCBCDecrypter(block, key)
  20. originalText := make([]byte, len(cipherBytes))
  21. blockMode.CryptBlocks(originalText, cipherBytes)
  22. originalText = PKCS5UnPadding(originalText)
  23. return originalText, nil
  24. }
  25. //DES加密⽂本,返回加密后⽂本
  26. func DesEncryptString(originalText string, key []byte) (string, error) {
  27. cipherArr, err := DesEncrypt([]byte(originalText), key)
  28. if err != nil {
  29. return "", err
  30. }
  31. base64str := base64.StdEncoding.EncodeToString(cipherArr)
  32. return base64str, nil
  33. }
  34. //对加密⽂本进⾏DES解密,返回解密后明⽂
  35. func DesDecryptString(cipherText string, key []byte) (string, error) {
  36. cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)
  37. cipherArr, err := DesDecrypt(cipherArr, key)
  38. if err != nil {
  39. return "", err
  40. }
  41. return string(cipherArr), nil
  42. }
复制代码

3DES

  1. // 3DES加密字节数组,返回字节数组
  2. func TripleDesEncrypt(originalBytes, key []byte) ([]byte, error) {
  3. block, err := des.NewTripleDESCipher(key)
  4. if err != nil {
  5. return nil, err
  6. }
  7. originalBytes = PKCS5Padding(originalBytes, block.BlockSize())
  8. // originalBytes = ZeroPadding(originalBytes, block.BlockSize())
  9. blockMode := cipher.NewCBCEncrypter(block, key[:8])
  10. cipherArr := make([]byte, len(originalBytes))
  11. blockMode.CryptBlocks(cipherArr, originalBytes)
  12. return cipherArr, nil
  13. }
  14. // 3DES解密字节数组,返回字节数组
  15. func TripleDesDecrypt(cipherBytes, key []byte) ([]byte, error) {
  16. block, err := des.NewTripleDESCipher(key)
  17. if err != nil {
  18. return nil, err
  19. }
  20. blockMode := cipher.NewCBCDecrypter(block, key[:8])
  21. originalArr := make([]byte, len(cipherBytes))
  22. blockMode.CryptBlocks(originalArr, cipherBytes)
  23. originalArr = PKCS5UnPadding(originalArr)
  24. // origData = ZeroUnPadding(origData)
  25. return originalArr, nil
  26. }
  27. // 3DES加密字符串,返回base64处理后字符串
  28. func TripleDesEncrypt2Str(originalText string, key []byte) (string, error) {
  29. block, err := des.NewTripleDESCipher(key)
  30. if err != nil {
  31. return "", err
  32. }
  33. originalData := PKCS5Padding([]byte(originalText), block.BlockSize())
  34. // originalData = ZeroPadding(originalData, block.BlockSize())
  35. blockMode := cipher.NewCBCEncrypter(block, key[:8])
  36. cipherArr := make([]byte, len(originalData))
  37. blockMode.CryptBlocks(cipherArr, originalData)
  38. cipherText := base64.StdEncoding.EncodeToString(cipherArr)
  39. return cipherText, nil
  40. }
  41. // 3DES解密base64处理后的加密字符串,返回明⽂字符串
  42. func TripleDesDecrypt2Str(cipherText string, key []byte) (string, error) {
  43. cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)
  44. block, err := des.NewTripleDESCipher(key)
  45. if err != nil {
  46. return "", err
  47. }
  48. blockMode := cipher.NewCBCDecrypter(block, key[:8])
  49. originalArr := make([]byte, len(cipherArr))
  50. blockMode.CryptBlocks(originalArr, cipherArr)
  51. originalArr = PKCS5UnPadding(originalArr)
  52. // origData = ZeroUnPadding(origData)
  53. return string(originalArr), nil
  54. }
复制代码

AES

  1. //AES加密字节数组,返回字节数组
  2. func AesEncrypt(originalBytes, key []byte) ([]byte, error) {
  3. block, err := aes.NewCipher(key)
  4. if err != nil {
  5. return nil, err
  6. }
  7. blockSize := block.BlockSize()
  8. originalBytes = PKCS5Padding(originalBytes, blockSize)
  9. // originalBytes = ZeroPadding(originalBytes, block.BlockSize())
  10. blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
  11. cipherBytes := make([]byte, len(originalBytes))
  12. // 根据CryptBlocks⽅法的说明,如下⽅式初始化crypted也可以
  13. // crypted := originalBytes
  14. blockMode.CryptBlocks(cipherBytes, originalBytes)
  15. return cipherBytes, nil
  16. }
  17. //AES解密字节数组,返回字节数组
  18. func AesDecrypt(cipherBytes, key []byte) ([]byte, error) {
  19. block, err := aes.NewCipher(key)
  20. if err != nil {
  21. return nil, err
  22. }
  23. blockSize := block.BlockSize()
  24. blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
  25. originalBytes := make([]byte, len(cipherBytes))
  26. // origData := cipherBytes
  27. blockMode.CryptBlocks(originalBytes, cipherBytes)
  28. originalBytes = PKCS5UnPadding(originalBytes)
  29. // origData = ZeroUnPadding(origData)
  30. return originalBytes, nil
  31. }
  32. //AES加密⽂本,返回对加密后字节数组进⾏base64处理后字符串
  33. func AesEncryptString(originalText string, key []byte) (string, error) {
  34. cipherBytes, err := AesEncrypt([]byte(originalText), key)
  35. if err != nil {
  36. return "", err
  37. }
  38. base64str := base64.StdEncoding.EncodeToString(cipherBytes)
  39. return base64str, nil
  40. }
  41. //AES解密⽂本,对Base64处理后的加密⽂本进⾏AES解密,返回解密后明⽂
  42. func AesDecryptString(cipherText string, key []byte) (string, error) {
  43. cipherBytes, _ := base64.StdEncoding.DecodeString(cipherText)
  44. cipherBytes, err := AesDecrypt(cipherBytes, key)
  45. if err != nil {
  46. return "", err
  47. }
  48. return string(cipherBytes), nil
  49. }
复制代码

⾮对称加密

RSA算法也是一个块加密算法( block cipher algorithm),总是在一个固定长度的块上举行 操作。但跟AES等不同的是,block length是跟key length有关的。

每次RSA加密的明文的长度是受RSA添补 模式限定 的,但是RSA每次加密的块长度就是key length。

添补 ⽅式 密文长度
PKCS1Padding 必须 比 RSA 秘钥模长(modulus) 短至少11个字节, 也就是RSA_SIZE(rsa) – 11
OAEPPadding RSA_SIZE(rsa) – 41
NOPadding 可以和RSA钥模长一样长,假如 输入的明文过长,必须切割, 然后添补
  1. 在不同的padding模式下,使用相同长度的密钥可以加密的数据最大长度不同在不同密钥长度下,使用相同的padding模式可以加密的数据最大长度也不同
  2. 因此,脱离了密钥长度而讨论padding模式可以加密的最大长度是不严谨的。常用的密钥长度有1024bits,2048bits等,理论上1024bits的密钥可以加密的数据最大长度为1024bits(即1024/8 = 128bytes)。2048bits的密钥可以加密的数据最大长度为2048bits(2048/8 = 256bytes),但是RSA在实际应用中不可能使用这种“教科书式的RSA”系统。实际应用中RSA经常与填充技术(padding)一起使用,可以增加RSA的安全性。
复制代码

PKCS1

  1. // 加密字节数组,返回字节数组
  2. func RsaEncrypt(publicKey, origData []byte) ([]byte, error) {
  3. block, _ := pem.Decode(publicKey)
  4. if block == nil {
  5. return nil, errors.New("public key error")
  6. }
  7. pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  8. if err != nil {
  9. return nil, err
  10. }
  11. pub := pubInterface.(*rsa.PublicKey)
  12. return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
  13. }
  14. // 解密字节数组,返回字节数组
  15. func RsaDecrypt(privateKey, ciphertext []byte) ([]byte, error) {
  16. block, _ := pem.Decode(privateKey)
  17. if block == nil {
  18. return nil, errors.New("private key error!")
  19. }
  20. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  21. if err != nil {
  22. return nil, err
  23. }
  24. return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
  25. }
  26. // 加密字符串,返回base64处理的字符串
  27. func RsaEncryptString(publicKey []byte, origData string) (string, error) {
  28. block, _ := pem.Decode(publicKey)
  29. if block == nil {
  30. return "", errors.New("public key error")
  31. }
  32. pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  33. if err != nil {
  34. return "", err
  35. }
  36. pub := pubInterface.(*rsa.PublicKey)
  37. cipherArr, err := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(origData))
  38. if err != nil {
  39. return "", err
  40. } else {
  41. return base64.StdEncoding.EncodeToString(cipherArr), nil
  42. }
  43. }
  44. // 解密经过base64处理的加密字符串,返回加密前的明⽂
  45. func RsaDecryptString(privateKey []byte, cipherText string) (string, error) {
  46. block, _ := pem.Decode(privateKey)
  47. if block == nil {
  48. return "", errors.New("private key error!")
  49. }
  50. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  51. if err != nil {
  52. return "", err
  53. }
  54. cipherArr, _ := base64.StdEncoding.DecodeString(cipherText)
  55. originalArr, err := rsa.DecryptPKCS1v15(rand.Reader, priv, cipherArr)
  56. if err != nil {
  57. return "", err
  58. } else {
  59. return string(originalArr), nil
  60. }
  61. }
复制代码

OAEP

  1. // 加密
  2. func EncryptOAEP(publicKey []byte, text string) (string, error) {
  3. block, _ := pem.Decode(publicKey)
  4. if block == nil {
  5. return "", errors.New("public key error")
  6. }
  7. pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
  8. if err != nil {
  9. return "", err
  10. }
  11. pub := pubInterface.(*rsa.PublicKey)
  12. secretMessage := []byte(text)
  13. rng := rand.Reader
  14. cipherdata, err := rsa.EncryptOAEP(sha1.New(), rng, pub, secretMessage, nil)
  15. if err != nil {
  16. return "", err
  17. }
  18. ciphertext := base64.StdEncoding.EncodeToString(cipherdata)
  19. return ciphertext, nil
  20. }
  21. // 解密
  22. func DecryptOAEP(privateKey []byte, ciphertext string) (string, error) {
  23. block, _ := pem.Decode(privateKey)
  24. if block == nil {
  25. return "", errors.New("private key error!")
  26. }
  27. priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  28. if err != nil {
  29. return "", err
  30. }
  31. cipherdata, _ := base64.StdEncoding.DecodeString(ciphertext)
  32. rng := rand.Reader
  33. plaintext, err := rsa.DecryptOAEP(sha1.New(), rng, priv, cipherdata, nil)
  34. if err != nil {
  35. return "", err
  36. }
  37. return string(plaintext), nil
  38. }
复制代码

椭圆曲线加密算法ECC

椭圆曲线暗码 学(Elliptic curve cryptography,缩写为 ECC),是基于椭圆曲线数学理论实现的⼀种⾮对称加密算法。

ECC与RSA算法的上风 对⽐

椭圆曲线公钥体系 是代替RSA的强有⼒的竞争者。

与经典的RSA、DSA等公钥暗码 体制相⽐,椭圆暗码 体制有以下长处 :

(1)安全性能更⾼(ECC可以使⽤更短的密钥):

160位ECC加密算法的安全强度相称 于1024位RSA加密;

210位ECC加密算法的安全强度相称 于2048位RSA加密。

(2)处理速率 快:计算量⼩,处理速率 快 在私钥的处理速率 上(解密和署名 ),ECC远 ⽐RSA、DSA快得多。

(3)存储空间占⽤⼩: ECC的密钥尺⼨和体系 参数与RSA、DSA相⽐要⼩得多, 以是 占⽤的存储空间⼩得多。

(4)带宽要求低使得ECC具有⼴泛的应⽤远景 。ECC的这些特点使它必将代替 RSA,成为通⽤的公钥加密算法。

  1. //生成ECC椭圆曲线密钥对
  2. func GenerateECCKey() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) {
  3. privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
  4. if err != nil {
  5. return nil, nil, err
  6. }
  7. publicKey := &privateKey.PublicKey
  8. return publicKey, privateKey, nil
  9. }
  10. //对消息的散列值生成数字签名
  11. func SignECC(msg []byte) ([]byte, []byte) {
  12. //取得私钥
  13. _, privateKey, err := GenerateECCKey()
  14. if err != nil {
  15. panic(err)
  16. }
  17. //计算哈希值
  18. hash := sha256.New()
  19. //填入数据
  20. hash.Write(msg)
  21. b := hash.Sum(nil)
  22. //对哈希值生成数字签名
  23. r, s, err := ecdsa.Sign(rand.Reader, privateKey, b)
  24. if err != nil {
  25. panic(err)
  26. }
  27. rtext, _ := r.MarshalText()
  28. stext, _ := s.MarshalText()
  29. return rtext, stext
  30. }
  31. //验证数字签名
  32. func VerifySignECC(msg []byte, rtext, stext []byte) bool {
  33. //取得公钥
  34. publicKey, _, err := GenerateECCKey()
  35. if err != nil {
  36. panic(err)
  37. }
  38. //计算哈希值
  39. hash := sha256.New()
  40. hash.Write(msg)
  41. b := hash.Sum(nil)
  42. //验证数字签名
  43. var r, s big.Int
  44. if err := r.UnmarshalText(rtext); err != nil {
  45. panic(err)
  46. }
  47. if err := s.UnmarshalText(stext); err != nil {
  48. panic(err)
  49. }
  50. verify := ecdsa.Verify(publicKey, b, &r, &s)
  51. return verify
  52. }
  53. //测试
  54. func Test(t *testing.T) {
  55. //模拟发送者
  56. //要发送的消息
  57. msg := []byte("hello world")
  58. //生成数字签名
  59. rtext, stext := SignECC(msg)
  60. //模拟接受者
  61. //接受到的消息
  62. acceptmsg := []byte("hello world")
  63. //接收到的签名
  64. acceptrtext := rtext
  65. acceptstext := stext
  66. //验证签名
  67. verifySignECC := VerifySignECC(acceptmsg, acceptrtext, acceptstext)
  68. fmt.Println("验证结果:", verifySignECC)
  69. }
复制代码

数字署名

数字署名 的概念

1、署名 不可伪造性;
2、署名 不可抵赖的;
3、署名 可信性,署名 的辨认 和应⽤相对轻易 ,任何⼈都可以验证署名 的有用
性;
4、署名 是不可复制的,署名 与原⽂是不可分割的团体 ;
5、署名 消息不可篡改,由于 恣意 ⽐特数据被篡改,其署名 便被随之改变,那么
任何⼈可以验证⽽拒绝担当 此署名 。

椭圆曲线数字署名 算法ECDSA

  1. //⽣成私钥和公钥,⽣成的私钥为结构体ecdsa.PrivateKey的指针
  2. func NewKeyPair() (ecdsa.PrivateKey, []byte) {
  3. //⽣成secp256椭圆曲线
  4. curve := elliptic.P256()
  5. //产⽣的是⼀个结构体指针,结构体类型为ecdsa.PrivateKey
  6. private, err := ecdsa.GenerateKey(curve, rand.Reader)
  7. if err != nil {
  8. log.Panic(err)
  9. }
  10. fmt.Printf("私钥:%x\n", private)
  11. fmt.Printf("私钥X:%x\n", private.X.Bytes())
  12. fmt.Printf("私钥Y:%x\n", private.Y.Bytes())
  13. fmt.Printf("私钥D:%x\n", private.D.Bytes())
  14. //x坐标与y坐标拼接在⼀起,⽣成公钥
  15. pubKey := append(private.X.Bytes(), private.Y.Bytes()...)
  16. //打印公钥,公钥⽤16进制打印出来⻓度为128,包含了x轴坐标与y轴坐标。
  17. fmt.Printf("公钥:%x \n", pubKey)
  18. return *private, pubKey
  19. }
  20. //⽣成签名的DER格式
  21. func MakeSignatureDerString(r, s string) string {
  22. // 获取R和S的⻓度
  23. lenSigR := len(r) / 2
  24. lenSigS := len(s) / 2
  25. // 计算DER序列的总⻓度
  26. lenSequence := lenSigR + lenSigS + 4
  27. // 将10进制⻓度转16进制字符串
  28. strLenSigR := DecimalToHex(int64(lenSigR))
  29. strLenSigS := DecimalToHex(int64(lenSigS))
  30. strLenSequence := DecimalToHex(int64(lenSequence))
  31. // 拼凑DER编码
  32. derString := "30" + strLenSequence
  33. derString = derString + "02" + strLenSigR + r
  34. derString = derString + "02" + strLenSigS + s
  35. derString = derString + "01"
  36. return derString
  37. }
  38. func DecimalToHex(n int64) string {
  39. if n < 0 {
  40. log.Println("Decimal to hexadecimal error: the argument must be greater than zero.")
  41. return ""
  42. }
  43. if n == 0 {
  44. return "0"
  45. }
  46. hex := map[int64]int64{10: 65, 11: 66, 12: 67, 13: 68, 14: 69, 15: 70}
  47. s := ""
  48. for q := n; q > 0; q = q / 16 {
  49. m := q % 16
  50. if m > 9 && m < 16 {
  51. m = hex[m]
  52. s = fmt.Sprintf("%v%v", string(m), s)
  53. continue
  54. }
  55. s = fmt.Sprintf("%v%v", m, s)
  56. }
  57. return s
  58. }
  59. //验证签名1
  60. func VerifySig(pubKey, message []byte, r, s *big.Int) bool {
  61. curve := elliptic.P256()
  62. //公钥的⻓度
  63. keyLen := len(pubKey)
  64. //前⼀半为x轴坐标,后⼀半为y轴坐标
  65. x := big.Int{}
  66. y := big.Int{}
  67. x.SetBytes(pubKey[:(keyLen / 2)])
  68. y.SetBytes(pubKey[(keyLen / 2):])
  69. rawPubKey := ecdsa.PublicKey{curve, &x, &y}
  70. //根据交易哈希、公钥、数字签名验证成功。ecdsa.Verify func Verify(pub *PublicKey, hash[] byte, r * big.Int, s * big.Int) bool
  71. res := ecdsa.Verify(&rawPubKey, message, r, s)
  72. return res
  73. }
  74. //验证签名2
  75. func VerifySignature(pubKey, message []byte, r, s string) bool {
  76. curve := elliptic.P256()
  77. //公钥的⻓度
  78. keyLen := len(pubKey)
  79. //前⼀半为x轴坐标,后⼀半为y轴坐标
  80. x := big.Int{}
  81. y := big.Int{}
  82. x.SetBytes(pubKey[:(keyLen / 2)])
  83. y.SetBytes(pubKey[(keyLen / 2):])
  84. rawPubKey := ecdsa.PublicKey{curve, &x, &y}
  85. //根据交易哈希、公钥、数字签名验证成功。ecdsa.Verify func Verify(pub *PublicKey, hash[] byte, r * big.Int, s * big.Int) bool
  86. rint := big.Int{}
  87. sint := big.Int{}
  88. rByte, _ := hex.DecodeString(r)
  89. sByte, _ := hex.DecodeString(s)
  90. rint.SetBytes(rByte)
  91. sint.SetBytes(sByte)
  92. //fmt.Println("------", rint.SetBytes(rByte))
  93. //fmt.Println("------", sint.SetBytes(sByte))
  94. res := ecdsa.Verify(&rawPubKey, message, &rint, &sint)
  95. return res
  96. }
  97. //验证过程
  98. func Test(t *testing.T) {
  99. //1、⽣成签名
  100. fmt.Println("1、⽣成签名-------------------------------")
  101. //调⽤函数⽣成私钥与公钥
  102. privKey, pubKey := NewKeyPair()
  103. //信息的哈希
  104. msg := sha256.Sum256([]byte("hello world"))
  105. //根据私钥和信息的哈希进⾏数字签名,产⽣r和s
  106. r, s, _ := ecdsa.Sign(rand.Reader, &privKey, msg[:])
  107. //⽣成r、s字符串
  108. fmt.Println("-------------------------------")
  109. strSigR := fmt.Sprintf("%x", r)
  110. strSigS := fmt.Sprintf("%x", s)
  111. fmt.Println("r、s的10进制分别为:", r, s)
  112. fmt.Println("r、s的16进制分别为:", strSigR, strSigS)
  113. //r和s拼接在⼀起,形成数字签名的der格式
  114. signatureDer := MakeSignatureDerString(strSigR, strSigS)
  115. //打印数字签名的16进制显示
  116. fmt.Println("数字签名DER格式为:", signatureDer)
  117. fmt.Println()
  118. //2、签名验证过程
  119. fmt.Println("2、签名验证过程-------------------------------")
  120. res := VerifySig(pubKey, msg[:], r, s)
  121. fmt.Println("签名验证结果:", res)
  122. res = VerifySignature(pubKey, msg[:], strSigR, strSigS)
  123. fmt.Println("签名验证结果:", res)
  124. }
复制代码

字符编码/解码

Base64

Base64就是⼀种基于64个可打印字符来表示⼆进制数据的⽅法。Base64使⽤了26个⼩写字⺟、26个⼤写字⺟、10个数字以及两个符号(比方 “+”和“/”),⽤于在电⼦邮件如许 的基于⽂本的前言 中传输⼆进制数据。

  1. Base64字符集:
  2. ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
  3. <img alt="在这里插入图片描述" src="https://img.jbzj.com/file_images/article/202108/202108141430017.png" />
  4. Base64的步骤
  5. 将每个字符转成ASCII编码(10进制)将10进制编码转成2进制编码将2进制编码按照6位⼀组进⾏平分将6位⼀组的2进制数⾼位补零,然后转成10进制数将10进制数作为索引,从Base64编码表中查找字符每3个字符的⽂本将编码为4个字符⻓度(3<em>8=4</em>6)
  6. a. 若⽂本为3个字符,则正好编码为4个字符⻓度;
  7. b. 若⽂本为2个字符,则编码为3个字符,由于不⾜4个字符,则在尾部⽤⼀个“=”补⻬;
  8. c. 若⽂本为1个字符,则编码为2个字符,由于不⾜4个字符,则在尾部⽤两个“=”补⻬。
复制代码

巨人的肩膀

  1. 从他人的工作中汲取经验来避免自己的错误重复,正如我们是站在巨人的肩膀上才能做出更好的成绩。
复制代码

https://github.com/rubyhan1314/Golang-100-Days
https://blog.csdn.net/luckydog612/article/details/80547758
https://www.cnblogs.com/yanzi-meng/p/9640578.html
https://www.cnblogs.com/starwolf/p/3365834.html
https://blog.csdn.net/u013073067/article/details/87086562
https://www.cnblogs.com/Terry-Wu/p/10314315.html
http://blog.studygolang.com/2013/01/go%E5%8A%A0%E5%AF%86%E8%A7%A3%E5%AF%86%E4%B9%8Bdes/
https://blog.csdn.net/kikajack/article/details/78329567

到此这篇关于Go中使用 加密算法的方法的文章就先容 到这了,更多相干 go 加密算法内容请搜刮 脚本之家从前 的文章或继续欣赏 下面的相干 文章盼望 大家以后多多支持脚本之家!


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

avatar 嘴边反复的话普 | 2021-9-15 08:55:23 | 显示全部楼层
关注一下!
回复

使用道具 举报

avatar 嫣冉 | 2021-9-23 06:46:57 | 显示全部楼层
最近压力山大啊!
回复

使用道具 举报

avatar 绘粹凭 | 2021-10-4 10:08:28 | 显示全部楼层
admin楼主的文笔不错!
回复

使用道具 举报

avatar 无热天龙中 | 2021-10-6 15:26:06 | 显示全部楼层
顶顶更健康!
回复

使用道具 举报

avatar gui57 | 6 天前 | 显示全部楼层
admin楼主主机很热情啊!
回复

使用道具 举报

avatar dw3995 | 5 天前 | 显示全部楼层
今天上网不回帖,回帖就回精华帖!
回复

使用道具 举报

admin楼主的帖子越来越有深度了!
回复

使用道具 举报

帖子好乱!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则