前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >主流加密方式

主流加密方式

作者头像
酷走天涯
发布2019-05-26 16:19:13
1.2K0
发布2019-05-26 16:19:13
举报
文章被收录于专栏:每日一篇技术文章
  • cipher
  • aes
  • des
  • md5
  • sha256
  • dsa
  • ecdsa
  • elliptic
  • hmac
  • rand
  • rc4
  • rsa

aes

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),对称加密

如美国联邦信息处理标准出版物197中所定义的,aes实现 AES 加密(以前称为 Rijndael)。 这个包中的 AES 操作不是使用恒定时间算法实现的。在支持 AES 的硬件支持的系统上运行时会有一个例外,这些操作会使这些操作保持恒定时间。例子包括使用 AES-NI 扩展的 amd64 系统和使用 Message-Security-Assist 扩展的 s390x 系统。在这样的系统中,当 NewCipher 的结果传递给 cipher.NewGCM 时,GCM 使用的 GHASH 操作也是恒定的

我们来演示一下加密解密过程

代码语言:javascript
复制
package main

import (
  "bytes"
  "crypto/aes"
  "crypto/cipher"
  "encoding/base64"
  "fmt"
)

func main() {
  testAes()
}

func testAes() {
  // AES-128。key长度:16, 24, 32 bytes 对应 AES-128, AES-192, AES-256
  key := []byte("1234560123456789")
  result, err := AesEncrypt([]byte("123"), key)
  if err != nil {
    panic(err)
  }
  fmt.Println(base64.StdEncoding.EncodeToString(result))
  origData, err := AesDecrypt(result, key)
  if err != nil {
    panic(err)
  }
  fmt.Println(string(origData))
}

// 加密
func AesEncrypt(origData, key []byte) ([]byte, error) {
  // 1.创建密文变量

  block, err := aes.NewCipher(key)
  if err != nil {
    return nil, err
  }
  // 2.获取块的大小
  blockSize := block.BlockSize()
  // 3.使用算法填充数据使其程度成为key的整数倍
  origData = PKCS5Padding(origData, blockSize)
  // origData = ZeroPadding(origData, block.BlockSize())

  // 4.创建加密类型变量
  blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])

  // 5.
  crypted := make([]byte, len(origData))
  // 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
  // crypted := origData

  // 6.开始加密
  blockMode.CryptBlocks(crypted, origData)
  return crypted, nil
}


// 解密
func AesDecrypt(crypted, key []byte) ([]byte, error) {
  // 1.创建密文变量
  block, err := aes.NewCipher(key)
  if err != nil {
    return nil, err
  }
  // 2.获取加密块长度
  blockSize := block.BlockSize()
  
  //3.创建解密数据
  blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
  
  // 4.创建解密后存放数据的变量
  origData := make([]byte, len(crypted))
  // origData := crypted
  
  // 5.解密数据
  blockMode.CryptBlocks(origData, crypted)
  
  // 6.去掉填充
  origData = PKCS5UnPadding(origData)
  // origData = ZeroUnPadding(origData)
  return origData, nil
}

func ZeroPadding(ciphertext []byte, blockSize int) []byte {
  padding := blockSize - len(ciphertext)%blockSize
  padtext := bytes.Repeat([]byte{0}, padding)
  return append(ciphertext, padtext...)
}

func ZeroUnPadding(origData []byte) []byte {
  length := len(origData)
  unpadding := int(origData[length-1])
  return origData[:(length - unpadding)]
}

func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
  padding := blockSize - len(ciphertext)%blockSize
  padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  return append(ciphertext, padtext...)
}

func PKCS5UnPadding(origData []byte) []byte {
  length := len(origData)
  // 去掉最后一个字节 unpadding 次
  unpadding := int(origData[length-1])
  return origData[:(length - unpadding)]
}

image.png

上面演示把‘123’通过一个秘钥key加密和解密的过程1234560123456789

des

DES算法的入口参数有三个:Key、Data、Mode。其中Key为7个字节共56位,是DES算法的工作密钥;Data为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密

代码语言:javascript
复制
package main

import (
"bytes"
"crypto/cipher" //cipher密码
"crypto/des"
"encoding/base64" //将对象转换成字符串
"fmt"
)

/**
 * DES加密方法
 */
func MyDesEncrypt(orig, key string) string{

// 1.将加密内容和秘钥转成字节数组
origData := []byte(orig)
k := []byte(key)

// 2.创建一个加密器
block, _ := des.NewCipher(k)

//3.将明文按秘钥的长度做补全操作
origData = PKCS5Padding(origData, block.BlockSize())

//4.返回一个解密接口-CBC
blockMode := cipher.NewCBCEncrypter(block, k)

//5.创建明文长度的字节数组
crypted := make([]byte, len(origData))

// 6.加密明文
blockMode.CryptBlocks(crypted, origData)

//将字节数组转换成字符串,base64编码
return base64.StdEncoding.EncodeToString(crypted)

}

/**
 * DES解密方法
 */
func MyDESDecrypt(data string, key string) string {

k := []byte(key)

//将加密字符串用base64转换成字节数组
crypted, _ := base64.StdEncoding.DecodeString(data)

//将字节秘钥转换成block快
block, _ := des.NewCipher(k)

//设置解密方式-CBC
blockMode := cipher.NewCBCDecrypter(block, k)

//创建密文大小的数组变量
origData := make([]byte, len(crypted))

//解密密文到数组origData中
blockMode.CryptBlocks(origData, crypted)

//去掉加密时补全的部分
origData = PKCS5UnPadding(origData)

return string(origData)
}

/**
 * 实现明文的补全
 * 如果ciphertext的长度为blockSize的整数倍,则不需要补全
 * 否则差几个则被几个,例:差5个则补5个5
 */
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}

/**
 * 实现去补码,PKCS5Padding的反函数
 */
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

func main() {

orig := "Hello World!"
fmt.Println("原文:", orig)

//声明秘钥,利用此秘钥实现明文的加密和密文的解密,长度必须为8
key := "12345678"

//加密
encyptCode := MyDesEncrypt(orig, key)
fmt.Println("密文:", encyptCode)

//解密
decyptCode := MyDESDecrypt(encyptCode, key)
fmt.Println("解密结果:", decyptCode)
}
md5

image.png

代码语言:javascript
复制
package main
import (
"crypto/md5"
  "fmt"
  "encoding/base64"
)

func main() {
s:= []byte("123456789")
result := md5.Sum(s)
fmt.Println(base64.StdEncoding.EncodeToString(result[:]))
}

image.png

sha256
代码语言:javascript
复制
package main

import (
"fmt"
  "encoding/base64"
  "crypto/sha256"
)


func main() {
s:= []byte("123456789")
result := sha256.Sum256(s)
fmt.Println(base64.StdEncoding.EncodeToString(result[:]))
}

image.png

rsa

下面我们看一下dsa的签名过程

代码语言:javascript
复制
package main
import (
  "crypto/rand"
  "crypto/rsa"
  "crypto/x509"
  "encoding/pem"
  "os"
)

func main() {
  //rsa 密钥文件产生
  GenRsaKey(1024)
}
//RSA公钥私钥产生
func GenRsaKey(bits int) error {

  // 生成私钥文件
  privateKey, err := rsa.GenerateKey(rand.Reader, bits)
  if err != nil {
    return err
  }
  derStream := x509.MarshalPKCS1PrivateKey(privateKey)
  // 构造pem 结构
  block := &pem.Block{
    Type:  "RSA PRIVATE KEY",
    Bytes: derStream,
  }
  file, err := os.Create("private.pem")
  if err != nil {
    return err
  }
  
  // 将block 结构块 写入文件中
  err = pem.Encode(file, block)
  if err != nil {
    return err
  }

  // 生成公钥文件
  publicKey := &privateKey.PublicKey
  
  // 将公钥转换为 DER-encoded PKIX 格式
  derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
  if err != nil {
    return err
  }
  
  // 生成证书格式
  block = &pem.Block{
    Type:  "PUBLIC KEY",
    Bytes: derPkix,
  }
  file, err = os.Create("public.pem")
  if err != nil {
    return err
  }
  // 生成证书文件
  err = pem.Encode(file, block)
  if err != nil {
    return err
  }
  return nil
}
hmac

hmac包实现了U.S. Federal Information Processing Standards Publication 198规定的HMAC(加密哈希信息认证码)。

HMAC是使用key标记信息的加密hash。接收者使用相同的key逆运算来认证hash。

hmac主要应用在身份验证中,它的使用方法是这样的: (1) 客户端发出登录请求(假设是浏览器的GET请求) (2) 服务器返回一个随机值,并在会话中记录这个随机值 (3) 客户端将该随机值作为密钥,用户密码进行hmac运算,然后提交给服务器 (4) 服务器读取用户数据库中的用户密码和步骤2中发送的随机值做与客户端一样的hmac运算,然后与用户发送的结果比较,如果结果一致则验证用户合法

代码语言:javascript
复制
package main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/json"
  "fmt"
  "encoding/base64"
)

const key = "asdfasdfasdfasdf"
func main() {
   // 1.服务端发送一个token 给客户端
    serverSendKeyToClient(key)
}

func serverSendKeyToClient(key string){
  // 2.服务器将数据进行hmac 运算,
  keyHash := hmac.New(sha256.New,[]byte(key))
  data := map[string]string{"username":"xujie"}
  s,_:= json.Marshal(data)
  keyHash.Write([]byte(string(s)))

  expectedMAC := keyHash.Sum(nil)
  fmt.Println("客户端计算的hmac:")
  fmt.Println(base64.StdEncoding.EncodeToString(expectedMAC))

  // 3.将运算后的hash 值和数据发送给服务端 服务器
  clientSendMessageToServer(string(s),string(expectedMAC))

}

func clientSendMessageToServer(message,messageMac string){

  // 服务端接受数据后进行hmac 运算 如果结果和客户端传递过来的一致 就表示数据没有被篡改
  fmt.Println(CheckMAC([]byte(message),[]byte(messageMac),[]byte(key)))
  data := map[string]string{}
  json.Unmarshal([]byte(message),data)
  fmt.Println(message)
}

// 如果messageMAC是message的合法HMAC标签,函数返回真
func CheckMAC(message, messageMAC, key []byte) bool {
  mac := hmac.New(sha256.New, key)
  mac.Write(message)
  expectedMAC := mac.Sum(nil)
  fmt.Println("服务器计算的hmac:")
  fmt.Println(base64.StdEncoding.EncodeToString(expectedMAC))
  return hmac.Equal(messageMAC, expectedMAC)
}

image.png

rand
  • func Read(b []byte) (n int, err error)
代码语言:javascript
复制
package main

import (
    "fmt"
  "crypto/rand"
  "bytes"
)


func main() {

  c := 10
  b := make([]byte, c)
  
  // 生成随机数填满切片b
  _, err := rand.Read(b)
  if err != nil {
    fmt.Println("error:", err)
    return
  }
  fmt.Println(b)
  // 切片现在应该包含随机字节而不是仅包含零。
  fmt.Println(bytes.Equal(b, make([]byte, c)))
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.12.28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • aes
  • des
  • md5
  • sha256
  • rsa
  • hmac
  • rand
相关产品与服务
全站加速网络
全站加速网络(Enterprise Content Delivery Network,以下简称 ECDN)为您提供稳定高效的网络加速服务,适用于动静混合、纯动态、跨国、上传等多种加速场景。ECDN 网络资源丰富,同时融合静态缓存、智能路由、协议优化、多路传输、抗抖动等自研技术,加速效果更加显著;接入便捷,功能配置灵活多样,可满足您个性化的业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档