基于golang常用加密解码的封装

mange · · 1822 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

> AES : 高级加密标准;AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特; ``` type AES interface { Encrypt(str, key []byte) ([]byte, error) Decrypt(str, key []byte) ([]byte, error) } ``` --- > DES : 数据加密标准,是一种使用密钥加密的块算法 ``` type DES interface { Encrypt(str, key []byte) ([]byte, error) Decrypt(str, key []byte) ([]byte, error) } ``` --- > AES&DES 支持的模式: CBC 密码分组链接模式(Cipher Block Chaining (CBC)) ``` // CBC : 密码分组链接模式(Cipher Block Chaining (CBC)) default type cbcObj struct { cryptoType string iv []byte } func (cbc *cbcObj) getBlock(key []byte) (block cipher.Block, err error) { if cbc.cryptoType == "aes" { block, err = aes.NewCipher(key) } if cbc.cryptoType == "des" { block, err = des.NewCipher(key) } return } // CBC Encrypt func (cbc *cbcObj) Encrypt(str, key []byte) ([]byte, error) { block, err := cbc.getBlock(key) if err != nil { Error("["+cbc.cryptoType+"-CBC] ERROR:" +err.Error()) return []byte(""), err } blockSize := block.BlockSize() originData := cbc.pkcs5Padding(str, blockSize) blockMode := cipher.NewCBCEncrypter(block,cbc.iv) cryptData := make([]byte,len(originData)) blockMode.CryptBlocks(cryptData,originData) P2E() return cryptData, nil } // CBC Decrypt func (cbc *cbcObj) Decrypt(str, key []byte) ([]byte, error) { block, err := cbc.getBlock(key) if err != nil { Error("["+cbc.cryptoType+"-CBC] ERROR:" +err.Error()) return []byte(""), err } blockMode := cipher.NewCBCDecrypter(block, cbc.iv) originStr := make([]byte,len(str)) blockMode.CryptBlocks(originStr,str) P2E() return cbc.pkcs5UnPadding(originStr), nil } func (cbc *cbcObj) pkcs5Padding(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padText...) } func (cbc *cbcObj) pkcs5UnPadding(origData []byte) []byte { length := len(origData) unpadDing := int(origData[length-1]) return origData[:(length - unpadDing)] } ``` --- > AES&DES 支持的模式: ECB 电码本模式(Electronic Codebook Book (ECB)) ``` // ECB : 电码本模式(Electronic Codebook Book (ECB)) type ecbObj struct { cryptoType string } func (ecb *ecbObj) getBlock(key []byte) (block cipher.Block, err error) { if ecb.cryptoType == "aes" { block, err = aes.NewCipher(ecb.generateKey(key)) } if ecb.cryptoType == "des" { block, err = des.NewCipher(key) } return } // ECB Encrypt func (ecb *ecbObj) Encrypt(str, key []byte) ([]byte, error) { block, err := ecb.getBlock(key) if err != nil { Error("["+ecb.cryptoType+"-ECB] ERROR:" +err.Error()) return []byte(""), err } blockSize := block.BlockSize() if ecb.cryptoType == "aes" { str = ecb.pkcs5PaddingAes(str, blockSize) } if ecb.cryptoType == "des" { str = ecb.pkcs5PaddingDes(str, blockSize) } //返回加密结果 encryptData := make([]byte, len(str)) //存储每次加密的数据 tmpData := make([]byte, blockSize) //分组分块加密 for index := 0; index < len(str); index += blockSize { block.Encrypt(tmpData, str[index:index+blockSize]) copy(encryptData, tmpData) } P2E() return encryptData, nil } func (ecb *ecbObj) pkcs5PaddingDes(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize padtext := bytes.Repeat([]byte{byte(padding)}, padding) return append(ciphertext, padtext...) } func (ecb *ecbObj) pkcs5PaddingAes(ciphertext []byte, blockSize int) []byte { padding := blockSize - len(ciphertext)%blockSize if padding != 0 { ciphertext = append(ciphertext, bytes.Repeat([]byte{byte(0)}, padding)...) } return ciphertext } // ECB Decrypt func (ecb *ecbObj) Decrypt(str, key []byte) ([]byte, error) { block, err := ecb.getBlock(key) if err != nil { Error("["+ecb.cryptoType+"-ECB] ERROR:" +err.Error()) return []byte(""), err } blockSize := block.BlockSize() //返回加密结果 decryptData := make([]byte, len(str)) //存储每次加密的数据 tmpData := make([]byte, blockSize) //分组分块加密 for index := 0; index < len(str); index += blockSize { block.Decrypt(tmpData, str[index:index+blockSize]) copy(decryptData, tmpData) } if ecb.cryptoType == "des" { return ecb.pkcs5UnPadding(decryptData), nil } P2E() return ecb.unPadding(decryptData), nil } func (ecb *ecbObj) generateKey(key []byte) (genKey []byte) { genKey = make([]byte, 16) copy(genKey, key) for i := 16; i < len(key); { for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 { genKey[j] ^= key[i] } } return genKey } func (ecb *ecbObj) unPadding(src []byte) []byte { for i := len(src) - 1; ; i-- { if src[i] != 0 { return src[:i+1] } } } func (ecb *ecbObj) pkcs5UnPadding(origData []byte) []byte { length := len(origData) unPadding := int(origData[length-1]) return origData[:(length - unPadding)] } ``` --- > AES&DES 支持的模式: CFB : 密码反馈模式(Cipher FeedBack (CFB)) ``` // 密码反馈模式(Cipher FeedBack (CFB)) type cfbObj struct { cryptoType string } func (cfb *cfbObj) getBlock(key []byte) (block cipher.Block, err error) { if cfb.cryptoType == "aes" { block, err = aes.NewCipher(key) } if cfb.cryptoType == "des" { block, err = des.NewCipher(key) } return } // CFB Encrypt func (cfb *cfbObj) Encrypt(str, key []byte) ([]byte, error) { P2E() block, err := cfb.getBlock(key) if err != nil { Error("["+cfb.cryptoType+"-CFB] ERROR:" +err.Error()) return nil, err } if cfb.cryptoType == "aes" { encrypted := make([]byte, aes.BlockSize+len(str)) iv := encrypted[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(encrypted[aes.BlockSize:], str) return encrypted, nil } if cfb.cryptoType == "des" { encrypted := make([]byte, des.BlockSize+len(str)) iv := encrypted[:des.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil, err } stream := cipher.NewCFBEncrypter(block, iv) stream.XORKeyStream(encrypted[des.BlockSize:], str) return encrypted, nil } return nil, nil } // CFB Decrypt func (cfb *cfbObj) Decrypt(str, key []byte) ([]byte, error) { P2E() block, err := cfb.getBlock(key) if err != nil { Error("["+cfb.cryptoType+"-CFB] ERROR:" +err.Error()) return nil, err } iv := []byte{} if cfb.cryptoType == "aes" { if len(str) < aes.BlockSize { return nil, errors.New("ciphertext too short") } iv = str[:aes.BlockSize] str = str[aes.BlockSize:] } if cfb.cryptoType == "des" { if len(str) < des.BlockSize { return nil, errors.New("ciphertext too short") } iv = str[:des.BlockSize] str = str[des.BlockSize:] } stream := cipher.NewCFBDecrypter(block, iv) stream.XORKeyStream(str, str) return str, nil } ``` --- > AES&DES 支持的模式: CTR 计算器模式(Counter (CTR)) ``` // 计算器模式(Counter (CTR)) type ctrObj struct { count []byte //指定计数器,长度必须等于block的块尺寸 cryptoType string } func (ctr *ctrObj) getBlock(key []byte) (block cipher.Block, err error) { if ctr.cryptoType == "aes" { block, err = aes.NewCipher(key) } if ctr.cryptoType == "des" { block, err = des.NewCipher(key) if len(ctr.count) > des.BlockSize { ctr.count = ctr.count[0:des.BlockSize] } } return } // CTR Encrypt func (ctr *ctrObj) Encrypt(str, key []byte) ([]byte, error) { return ctr.crypto(str, key) } // CTR Decrypt func (ctr *ctrObj) Decrypt(str, key []byte) ([]byte, error) { return ctr.crypto(str, key) } func (ctr *ctrObj) crypto(str, key []byte) ([]byte, error) { P2E() block,err:=ctr.getBlock(key) if err != nil { Error("[AES-CTR] ERROR:" +err.Error()) return []byte(""), err } //指定分组模式 blockMode:=cipher.NewCTR(block, ctr.count) //执行加密、解密操作 res:=make([]byte,len(str)) blockMode.XORKeyStream(res,str) //返回明文或密文 return res, nil } ``` --- > AES&DES 支持的模式: OFB : 输出反馈模式(Output FeedBack (OFB)) ``` // 输出反馈模式(Output FeedBack (OFB)) type ofbObj struct {} ``` --- > Hmac 是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。 ``` func hmacFunc(h func() hash.Hash, str, key []byte) string { mac := hmac.New(h, key) mac.Write(str) res := base64.StdEncoding.EncodeToString(mac.Sum(nil)) return res } // HmacMD5 func HmacMD5(str, key string) string { return hmacFunc(md5.New, []byte(str), []byte(key)) } // HmacSHA1 func HmacSHA1(str, key string) string { return hmacFunc(sha1.New, []byte(str), []byte(key)) } // HmacSHA256 func HmacSHA256(str, key string) string { return hmacFunc(sha256.New, []byte(str), []byte(key)) } // HmacSHA512 func HmacSHA512(str, key string) string { return hmacFunc(sha512.New, []byte(str), []byte(key)) } ``` --- > PBKDF2应用一个伪随机函数以导出密钥 ``` func pbkdf2Func(h func() hash.Hash, str, salt []byte, iterations, keySize int) []byte { return pbkdf2.Key(str, salt, iterations, keySize, h) } // PBKDF2 func PBKDF2(str, salt []byte, iterations, keySize int) ([]byte) { return pbkdf2Func(sha256.New, str, salt, iterations, keySize) } ``` --- > JWT: JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于 在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公 钥/私钥对来签名,防止被篡改。 ``` // jwtEncrypt func jwtEncrypt(token *jwt.Token, data map[string]interface{}, secret string) (string, error) { claims := make(jwt.MapClaims) for k, v := range data { claims[k] = v } token.Claims = claims return token.SignedString([]byte(secret)) } // JwtEncrypt func JwtEncrypt(data map[string]interface{}, secret, method string) (string, error){ switch method { case "256": return jwtEncrypt(jwt.New(jwt.SigningMethodHS256), data, secret) case "384": return jwtEncrypt(jwt.New(jwt.SigningMethodHS384), data, secret) case "512": return jwtEncrypt(jwt.New(jwt.SigningMethodHS512), data, secret) } return "",fmt.Errorf("未知method; method= 256 or 384 or 512 ") } // JwtEncrypt256 func JwtEncrypt256(data map[string]interface{}, secret string) (string, error){ token := jwt.New(jwt.SigningMethodHS256) return jwtEncrypt(token, data, secret) } // JwtEncrypt384 func JwtEncrypt384(data map[string]interface{}, secret string) (string, error){ token := jwt.New(jwt.SigningMethodHS384) return jwtEncrypt(token, data, secret) } // JwtEncrypt512 func JwtEncrypt512(data map[string]interface{}, secret string) (string, error){ token := jwt.New(jwt.SigningMethodHS512) return jwtEncrypt(token, data, secret) } // JwtDecrypt func JwtDecrypt(tokenString, secret string) (data map[string]interface{}, err error) { data = make(map[string]interface{}) var secretFunc = func() jwt.Keyfunc { //按照这样的规则解析 return func(t *jwt.Token) (interface{}, error) { return []byte(secret), nil } } token, err := jwt.Parse(tokenString, secretFunc()) if err != nil { err = fmt.Errorf("未知Token") return } claim, ok := token.Claims.(jwt.MapClaims) if !ok { return } if !token.Valid { // 令牌错误 return } for k, v := range claim { data[k] =v } return } ``` 其它: Rabbit, RC4, RIPEMD-160, DSA, RSA ### 源码传送门 https://github.com/mangenotwork/gathertool/blob/main/crypto.go

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1822 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传