加密编码总结

2018-09-03  本文已影响0人  吃猫的鱼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)

}
上一篇下一篇

猜你喜欢

热点阅读