知識(shí)分享之Golang——用于在Golang中的加解密工具類,包含MD5晦溪、RSA超長(zhǎng)字符串瀑粥、CBC、ECB等算法

知識(shí)分享之Golang——用于在Golang中的加解密工具類三圆,包含MD5狞换、RSA超長(zhǎng)字符串、CBC舟肉、ECB等算法

背景

知識(shí)分享之Golang篇是我在日常使用Golang時(shí)學(xué)習(xí)到的各種各樣的知識(shí)的記錄修噪,將其整理出來以文章的形式分享給大家,來進(jìn)行共同學(xué)習(xí)度气。歡迎大家進(jìn)行持續(xù)關(guān)注割按。

知識(shí)分享系列目前包含Java、Golang磷籍、Linux适荣、Docker等等。

開發(fā)環(huán)境

  • 系統(tǒng):windows10
  • 語(yǔ)言:Golang
  • 組件庫(kù):Bleve
  • golang版本:1.18

內(nèi)容

本節(jié)我們分享一個(gè)用于在Golang中的加解密工具類院领,包含MD5弛矛、RSA超長(zhǎng)字符串、CBC比然、ECB等算法

package util

import (
    "ApiManagement/src/base/errors"
    "bytes"
    "crypto/cipher"
    "crypto/des"
    "crypto/md5"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/hex"
    "encoding/pem"
    "fmt"
    "log"
    "os"
    "strings"
)

var SysConfigDir = ""

const (
    MD5_SALT = "cnhuashao"
)

var (
    publicKey  []byte
    privateKey []byte
)

//
//  InitEncrypt
//  @Description: 初始化秘鑰
//
func InitEncrypt(pubKey, priKey string) {
    publicKey = []byte(pubKey)
    privateKey = []byte(priKey)

    //GenerateRSAKey(1024 * 4)
}

//生成RSA私鑰和公鑰丈氓,保存到文件中
func GenerateRSAKey(bits int) {
    //GenerateKey函數(shù)使用隨機(jī)數(shù)據(jù)生成器random生成一對(duì)具有指定字位數(shù)的RSA密鑰
    //Reader是一個(gè)全局、共享的密碼用強(qiáng)隨機(jī)數(shù)生成器
    privateKey, err := rsa.GenerateKey(rand.Reader, bits)
    if err != nil {
        panic(err)
    }
    //保存私鑰
    //通過x509標(biāo)準(zhǔn)將得到的ras私鑰序列化為ASN.1 的 DER編碼字符串
    X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
    //使用pem格式對(duì)x509輸出的內(nèi)容進(jìn)行編碼
    //創(chuàng)建文件保存私鑰
    privateFile, err := os.Create(SysConfigDir + "private.pem")
    if err != nil {
        panic(err)
    }
    defer privateFile.Close()
    //構(gòu)建一個(gè)pem.Block結(jié)構(gòu)體對(duì)象
    privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey}
    //將數(shù)據(jù)保存到文件
    pem.Encode(privateFile, &privateBlock)
    //保存公鑰
    //獲取公鑰的數(shù)據(jù)
    publicKey := privateKey.PublicKey
    //X509對(duì)公鑰編碼
    X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
    if err != nil {
        panic(err)
    }
    //pem格式編碼
    //創(chuàng)建用于保存公鑰的文件
    publicFile, err := os.Create(SysConfigDir + "public.pem")
    if err != nil {
        panic(err)
    }
    defer publicFile.Close()
    //創(chuàng)建一個(gè)pem.Block結(jié)構(gòu)體對(duì)象
    publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey}
    //保存到文件
    pem.Encode(publicFile, &publicBlock)
}

func RSA_DecryptLong(cipherText []byte, paths ...string) ([]byte, error) {
    path := SysConfigDir + "private.pem"
    if len(paths) > 0 {
        path = paths[0]
    }
    //打開文件
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()
    //獲取文件內(nèi)容
    info, err := file.Stat()
    if err != nil {
        return nil, err
    }
    buf := make([]byte, info.Size())
    file.Read(buf)
    //pem解碼
    block, _ := pem.Decode(buf)
    //X509解碼
    priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    path2 := SysConfigDir + "public.pem"
    if len(paths) > 0 {
        path2 = paths[0]
    }
    //打開文件
    file2, err := os.Open(path2)
    if err != nil {
        panic(err)
    }
    defer file2.Close()
    //讀取文件的內(nèi)容
    info2, _ := file2.Stat()
    buf2 := make([]byte, info2.Size())
    file2.Read(buf2)
    //pem解碼
    block2, _ := pem.Decode(buf2)
    //x509解碼
    publicKeyInterface, err := x509.ParsePKIXPublicKey(block2.Bytes)
    if err != nil {
        panic(err)
    }
    //類型斷言
    pubKey := publicKeyInterface.(*rsa.PublicKey)

    partLen := pubKey.N.BitLen() / 8
    chunks := split(cipherText, partLen)
    buffer := bytes.NewBufferString("")
    for _, chunk := range chunks {
        //對(duì)密文進(jìn)行解密
        plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, chunk)
        if err != nil {
            return nil, err
        }
        buffer.Write(plainText)
    }
    //返回明文
    return []byte(buffer.String()), nil
}
func split(buf []byte, lim int) [][]byte {
    var chunk []byte
    chunks := make([][]byte, 0, len(buf)/lim+1)
    for len(buf) >= lim {
        chunk, buf = buf[:lim], buf[lim:]
        chunks = append(chunks, chunk)
    }
    if len(buf) > 0 {
        chunks = append(chunks, buf[:len(buf)])
    }
    return chunks
}

//
//  RSA_Encrypt
//  @Description: RSA加密强法,當(dāng)前端傳過來時(shí)需要使用
//  @param plainText
//  @param path
//  @return []byte
//
func RSA_Encrypt(plainText []byte, paths ...string) []byte {
    path := SysConfigDir + "public.pem"
    if len(paths) > 0 {
        path = paths[0]
    }
    //打開文件
    file, err := os.Open(path)
    if err != nil {
        panic(err)
    }
    defer file.Close()
    //讀取文件的內(nèi)容
    info, _ := file.Stat()
    buf := make([]byte, info.Size())
    file.Read(buf)
    log.Println(string(buf))
    //pem解碼
    block, _ := pem.Decode(buf)
    //x509解碼
    publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    //類型斷言
    pubKey := publicKeyInterface.(*rsa.PublicKey)
    //對(duì)明文進(jìn)行加密
    cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, plainText)
    if err != nil {
        panic(err)
    }
    //返回密文
    return cipherText
}

//
//  RSA_Decrypt
//  @Description: RSA解密
//  @param cipherText
//  @param paths
//  @return []byte
//  @return error
//
func RSA_Decrypt(cipherText []byte, paths ...string) ([]byte, error) {
    path := SysConfigDir + "private.pem"
    if len(paths) > 0 {
        path = paths[0]
    }
    //打開文件
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()
    //獲取文件內(nèi)容
    info, err := file.Stat()
    if err != nil {
        return nil, err
    }
    buf := make([]byte, info.Size())
    file.Read(buf)
    //pem解碼
    block, _ := pem.Decode(buf)
    //X509解碼
    priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return nil, err
    }
    //對(duì)密文進(jìn)行解密
    plainText, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, cipherText)
    if err != nil {
        return nil, err
    }
    //返回明文
    return plainText, nil
}

// Md5Crypt 加鹽MD5加密
//@params str 需要加密的字符串
//@params salt interface{} 加密的鹽
//@return str 返回md5碼
func Md5Crypt(str string, salt ...interface{}) (CryptStr string) {
    if l := len(salt); l > 0 {
        slice := make([]string, l+1)
        str = fmt.Sprintf(str+strings.Join(slice, "%v"), salt...)
    }
    return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}

// MD5Bytes 數(shù)據(jù)塊MD5計(jì)算函數(shù)
func MD5Bytes(s []byte) string {
    ret := md5.Sum(s)
    return fmt.Sprintf("%x", ret)
}

// MD5 計(jì)算字符串MD5值
func MD5(s string) string {
    return MD5Bytes([]byte(s))
}

// EncryptDES_CBC CBC加密
func EncryptDES_CBC(src, key string) string {
    data := []byte(src)
    keyByte := []byte(key)
    block, err := des.NewCipher(keyByte)
    if err != nil {
        panic(err)
    }
    data = PKCS5Padding(data, block.BlockSize())
    //獲取CBC加密模式
    iv := keyByte //用密鑰作為向量(不建議這樣使用)
    mode := cipher.NewCBCEncrypter(block, iv)
    out := make([]byte, len(data))
    mode.CryptBlocks(out, data)
    return fmt.Sprintf("%X", out)
}

//CBC解密
func DecryptDES_CBC(src, key string) string {
    keyByte := []byte(key)
    data, err := hex.DecodeString(src)
    if err != nil {
        panic(err)
    }
    block, err := des.NewCipher(keyByte)
    if err != nil {
        panic(err)
    }
    iv := keyByte //用密鑰作為向量(不建議這樣使用)
    mode := cipher.NewCBCDecrypter(block, iv)
    plaintext := make([]byte, len(data))
    mode.CryptBlocks(plaintext, data)
    plaintext = PKCS5UnPadding(plaintext)
    return string(plaintext)
}

//ECB加密
func EncryptDES_ECB(src, key string) string {
    data := []byte(src)
    keyByte := []byte(key)
    block, err := des.NewCipher(keyByte)
    if err != nil {
        panic(err)
    }
    bs := block.BlockSize()
    //對(duì)明文數(shù)據(jù)進(jìn)行補(bǔ)碼
    data = PKCS5Padding(data, bs)
    if len(data)%bs != 0 {
        panic("Need a multiple of the blocksize")
    }
    out := make([]byte, len(data))
    dst := out
    for len(data) > 0 {
        //對(duì)明文按照blocksize進(jìn)行分塊加密
        //必要時(shí)可以使用go關(guān)鍵字進(jìn)行并行加密
        block.Encrypt(dst, data[:bs])
        data = data[bs:]
        dst = dst[bs:]
    }
    return fmt.Sprintf("%X", out)
}

//ECB解密
func DecryptDES_ECB(src, key string) string {
    data, err := hex.DecodeString(src)
    if err != nil {
        panic(err)
    }
    keyByte := []byte(key)
    block, err := des.NewCipher(keyByte)
    if err != nil {
        panic(err)
    }
    bs := block.BlockSize()
    if len(data)%bs != 0 {
        panic("crypto/cipher: input not full blocks")
    }
    out := make([]byte, len(data))
    dst := out
    for len(data) > 0 {
        block.Decrypt(dst, data[:bs])
        data = data[bs:]
        dst = dst[bs:]
    }
    out = PKCS5UnPadding(out)
    return string(out)
}

//明文補(bǔ)碼算法
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 := int(origData[length-1])
    return origData[:(length - unpadding)]
}

// RsaEncrypt Rsa加密
func RsaEncrypt(origData []byte) ([]byte, error) {
    block, _ := pem.Decode(publicKey)
    publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        panic(err)
    }
    //類型斷言
    pubKey := publicKeyInterface.(*rsa.PublicKey)

    encryptedBytes, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, origData)
    return encryptedBytes, err
}

// RsaDecrypt Rsa解密
func RsaDecrypt(cipherText []byte) ([]byte, error) {
    //解密
    block, _ := pem.Decode(privateKey)
    if block == nil {
        return nil, errors.New("private key error!")
    }
    //解析PKCS1格式的私鑰
    priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return nil, err
    }
    //解密密文
    return rsa.DecryptPKCS1v15(rand.Reader, priv, cipherText)
}
本文聲明:

88x31.png

知識(shí)共享許可協(xié)議
本作品由 cn華少 采用 知識(shí)共享署名-非商業(yè)性使用 4.0 國(guó)際許可協(xié)議 進(jìn)行許可万俗。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市饮怯,隨后出現(xiàn)的幾起案子闰歪,更是在濱河造成了極大的恐慌,老刑警劉巖蓖墅,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件库倘,死亡現(xiàn)場(chǎng)離奇詭異临扮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)教翩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門杆勇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饱亿,你說我怎么就攤上這事蚜退。” “怎么了路捧?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵关霸,是天一觀的道長(zhǎng)传黄。 經(jīng)常有香客問我杰扫,道長(zhǎng),這世上最難降的妖魔是什么膘掰? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任章姓,我火速辦了婚禮,結(jié)果婚禮上识埋,老公的妹妹穿的比我還像新娘凡伊。我一直安慰自己,他們只是感情好窒舟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布系忙。 她就那樣靜靜地躺著,像睡著了一般惠豺。 火紅的嫁衣襯著肌膚如雪银还。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天洁墙,我揣著相機(jī)與錄音蛹疯,去河邊找鬼。 笑死热监,一個(gè)胖子當(dāng)著我的面吹牛捺弦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播孝扛,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼列吼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了苦始?” 一聲冷哼從身側(cè)響起寞钥,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盈简,沒想到半個(gè)月后凑耻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體太示,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年香浩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了类缤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邻吭,死狀恐怖餐弱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情囱晴,我是刑警寧澤膏蚓,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站畸写,受9級(jí)特大地震影響驮瞧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枯芬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一论笔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧千所,春花似錦狂魔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至待错,卻和暖如春籽孙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朗鸠。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工蚯撩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烛占。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓胎挎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親忆家。 傳聞我的和親對(duì)象是個(gè)殘疾皇子犹菇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容