美文网首页
加密编码总结

加密编码总结

作者: 吃猫的鱼0 | 来源:发表于2018-09-03 10:15 被阅读0次

    url编码

    import (
        "fmt"
        "net/url"
    )
    
    func main() {
        pathCode()
        queryCode()
    }
    // 不会对特殊字符进行特殊编码
    func pathCode()  {
        pathEncode:=url.PathEscape("!@#$%^&*()_+-= ")
        fmt.Println("pathEncode====="+pathEncode)
        // 不会吧+变成空格
        PathUnescape,_ := url.PathUnescape(pathEncode)
        fmt.Println("Pathdecode====="+PathUnescape)
    }
    // 会对特殊字符进行编码
    func queryCode()  {
        quryEncode:=url.QueryEscape("!@#$%^&*()_+-= ")
        fmt.Println("quryEncode====="+quryEncode)
        // 会将+转成空格
        quryUnescape,_ := url.QueryUnescape(quryEncode)
        fmt.Println("qurydecode====="+quryUnescape)
    }
    

    base64编码

    工作中碰到url与base64配合加解密的问题,base64编码后的字符串中可能含有特殊字符比如+,在url后的参数必然会经过url解码后会变成空格。解决方法为先将字符串url编码后再进行base64编码。
    可以参考的文档base64中文参考文档

    base64加解密

    // base64解密byte数组
    func DecodeToByte(data []byte) ([]byte, error) {
        enc := base64.StdEncoding
        dbuf := make([]byte, enc.DecodedLen(len(data)))
        n, err := enc.Decode(dbuf, data)
        return dbuf[:n], err
    }
    
    // base64解密字符串
    func DecodeToString(data []byte) (string, error) {
        enc := base64.StdEncoding
        dbuf := make([]byte, enc.DecodedLen(len(data)))
        n, err := enc.Decode(dbuf, data)
        return string(dbuf[:n]), err
    }
    
    // 加密为byte数组
    func EncodeToByte(src []byte) []byte {
        enc := base64.StdEncoding
        buf := make([]byte, enc.EncodedLen(len(src)))
        enc.Encode(buf, src)
        return buf
    }
    
    // base64加密为字符串
    func EncodeToString(data []byte) (string) {
        return base64.StdEncoding.EncodeToString(data)
    }
    

    文件处理

    base对文件的处理其实就是对文件的加解密处理,然后再使用相应的文件读写操作。

    根据base64字符串计算图片大小

    Base64编码要求把3个8位字节(38=24)转化为4个6位的字节(46=24),之后在6位的前面补两个0,形成8位一个字节的形式。 如果剩下的字符不足3个字节,则用0填充,输出字符使用’=’,因此编码后输出的文本末尾可能会出现1或2个’=’(相当于多了一个或两个字节)

    ff, _ := ioutil.ReadFile("image/19155559_E3nk.jpg")               //我还是喜欢用这个快速读文件
    fmt.Println("编码前图片大小=====",len(ff))
    buf_store:=EncodeToByte( ff)               // 文件转base64
    _ = ioutil.WriteFile("image/output2.jpg.txt", buf_store, 0666) //直接写入到文件就ok完活了。
    fmt.Println("编码后base64大小=====",len(buf_store))
    count:=strings.Count(string(buf_store), "=")
    noeq:=string(buf_store)[0:strings.Index(string(buf_store), "=")]
    fmt.Println("去掉等号后的大小=====",len(noeq))
    fmt.Println("两者相除=====",float32(len(noeq))/float32(len(ff)))
    fmt.Println("base64求得原图片大小=====",int(float32(len(buf_store))*3/4)-count)
    

    AES加解密

    
    import (
        "bytes"
        "crypto/aes"
        "crypto/cipher"
        "crypto/rand"
        "io"
    )
    
    /*CBC加密 按照golang标准库的例子代码
    不过里面没有填充的部分,所以补上
    */
    
    //使用PKCS7进行填充,IOS也是7
    func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
        padding := blockSize - len(ciphertext) % blockSize
        padtext := bytes.Repeat([]byte{byte(padding)}, padding)
        return append(ciphertext, padtext...)
    }
    
    func PKCS7UnPadding(origData []byte) []byte {
        length := len(origData)
        unpadding := int(origData[length-1])
        return origData[:(length - unpadding)]
    }
    
    //aes加密,填充秘钥key的16位,24,32分别对应AES-128, AES-192, or AES-256.
    func AesCBCEncrypt(rawData,key []byte) ([]byte, error) {
        block, err := aes.NewCipher(key)
        if err != nil {
            panic(err)
        }
    
        //填充原文
        blockSize := block.BlockSize()
        rawData = PKCS7Padding(rawData, blockSize)
        //初始向量IV必须是唯一,但不需要保密
        cipherText := make([]byte,blockSize+len(rawData))
        //block大小 16
        iv := cipherText[:blockSize]
        if _, err := io.ReadFull(rand.Reader,iv); err != nil {
            panic(err)
        }
    
        //block大小和初始向量大小一定要一致
        mode := cipher.NewCBCEncrypter(block,iv)
        mode.CryptBlocks(cipherText[blockSize:],rawData)
    
        return cipherText, nil
    }
    
    func AesCBCDncrypt(encryptData, key []byte) ([]byte,error) {
        block, err := aes.NewCipher(key)
        if err != nil {
            panic(err)
        }
    
        blockSize := block.BlockSize()
    
        if len(encryptData) < blockSize {
            panic("ciphertext too short")
        }
        iv := encryptData[:blockSize]
        encryptData = encryptData[blockSize:]
    
        // CBC mode always works in whole blocks.
        if len(encryptData)%blockSize != 0 {
            panic("ciphertext is not a multiple of the block size")
        }
    
        mode := cipher.NewCBCDecrypter(block, iv)
    
        // CryptBlocks can work in-place if the two arguments are the same.
        mode.CryptBlocks(encryptData, encryptData)
        //解填充
        encryptData = PKCS7UnPadding(encryptData)
        return encryptData,nil
    }
    
    
    func Encrypt(rawData,key []byte) ([]byte,error) {
        data, err:= AesCBCEncrypt(rawData,key)
        if err != nil {
            return nil,err
        }
        return data,nil
    }
    
    func Dncrypt(rawData ,key []byte) ([]byte,error) {
        dnData,err := AesCBCDncrypt(rawData,key)
        if err != nil {
            return nil,err
        }
        return dnData,nil
    }
    

    TEST

    import (
        "fmt"
        "testing"
    )
    
    func TestAesCBCDncrypt(t *testing.T) {
        // key : 长度为:16,24,32
        var aeskey = []byte("321423u9y8d2fwfl")
        pass := []byte("vdncloud123456")
        xpass, err := Encrypt(pass, aeskey)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println("xpass=====",string(xpass))
        tpass, err := Dncrypt(xpass, aeskey)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println("tpass=====",string(tpass))
        fmt.Printf("解密后:%s\n", tpass)
    }
    
    

    DES加解密

    
    import (
        "bytes"
        "crypto/cipher"
        "crypto/des"
    )
    
    //去除补码
    func PKCS5UnPadding(origData []byte) []byte {
        length := len(origData)
        // 去掉最后一个字节 unpadding 次
        unpadding := int(origData[length-1])
        //解密去补码时需取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文
        return origData[:(length - unpadding)]
    }
    
    //加密
    func DesEncrypt(origData, key []byte) ([]byte, error) {
        block, err := des.NewCipher(key)
        if err != nil {
            return nil, err
        }
        origData = PKCS5Padding(origData, block.BlockSize())
        // origData = ZeroPadding(origData, block.BlockSize())
        blockMode := cipher.NewCBCEncrypter(block, key)
        crypted := make([]byte, len(origData))
        // 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
        // crypted := origData
        blockMode.CryptBlocks(crypted, origData)
        return crypted, nil
    }
    
    // 解密
    func DesDecrypt(crypted, key []byte) ([]byte, error) {
        block, err := des.NewCipher(key)
        if err != nil {
            return nil, err
        }
        blockMode := cipher.NewCBCDecrypter(block, key)
        origData := make([]byte, len(crypted))
        // origData := crypted
        blockMode.CryptBlocks(origData, crypted)
        origData = PKCS5UnPadding(origData)
        // origData = ZeroUnPadding(origData)
        return origData, nil
    }
    
    //func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
    //  padding := blockSize - len(ciphertext)%blockSize
    //  padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    //  return append(ciphertext, padtext...)
    //}
    //实现明文的补码
    func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
        //计算出需要补多少位
        padding := blockSize - len(ciphertext)%blockSize
        //Repeat()函数的功能是把参数一 切片复制 参数二count个,然后合成一个新的字节切片返回
        // 需要补padding位的padding值
        padtext := bytes.Repeat([]byte{byte(padding)}, padding)
        //把补充的内容拼接到明文后面
        return append(ciphertext, padtext...)
    }
    
    // 3DES加密
    func TripleDesEncrypt(origData, key []byte) ([]byte, error) {
        block, err := des.NewTripleDESCipher(key)
        if err != nil {
            return nil, err
        }
        origData = PKCS5Padding(origData, block.BlockSize())
        // origData = ZeroPadding(origData, block.BlockSize())
        blockMode := cipher.NewCBCEncrypter(block, key[:8])
        crypted := make([]byte, len(origData))
        blockMode.CryptBlocks(crypted, origData)
        return crypted, nil
    }
    
    // 3DES解密
    func TripleDesDecrypt(crypted, key []byte) ([]byte, error) {
        block, err := des.NewTripleDESCipher(key)
        if err != nil {
            return nil, err
        }
        blockMode := cipher.NewCBCDecrypter(block, key[:8])
        origData := make([]byte, len(crypted))
        // origData := crypted
        blockMode.CryptBlocks(origData, crypted)
        origData = PKCS5UnPadding(origData)
        // origData = ZeroUnPadding(origData)
        return origData, nil
    }
    
    

    TEST

    import (
        "fmt"
        "testing"
    )
    
    func TestDesEncrypt(t *testing.T) {
        //定义明文
        data := []byte("hello world")
        //密钥 8位
        key := []byte("12345678")
    
        //加密
        des, err:=DesEncrypt(data, key)
        fmt.Println(string(des),err)
    
        //解密
        dec,err:=DesDecrypt(des, key)
        fmt.Println(string(dec),err)
    
    }
    func TestTripleDesEncrypt(t *testing.T) {
        //定义明文
        data := []byte("hello world")
        //密钥 24位
        key := []byte("012345678901234567891234")
    
        //加密
        des, err:=TripleDesEncrypt(data, key)
        fmt.Println(string(des),err)
    
        //解密
        dec,err:=TripleDesDecrypt(des, key)
        fmt.Println(string(dec),err)
    
    }
    

    相关文章

      网友评论

          本文标题:加密编码总结

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