美文网首页
主流加密方式

主流加密方式

作者: 酷走天涯 | 来源:发表于2018-12-28 08:58 被阅读57次
    • 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 操作也是恒定的

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

    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的工作方式,有两种:加密或解密

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

    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的签名过程

    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运算,然后与用户发送的结果比较,如果结果一致则验证用户合法

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

    相关文章

      网友评论

          本文标题:主流加密方式

          本文链接:https://www.haomeiwen.com/subject/apbpqqtx.html