1. 程式人生 > >GO語言入門9---AES、DES、RSA演算法

GO語言入門9---AES、DES、RSA演算法

目錄

AES演算法

package main // 固定
import (
    "bytes"
    "fmt"
    "crypto/aes"
    "crypto/cipher"
    "encoding/base32"
)

// 往字串後面填充0
func ZeroPadding(cipherText []byte, blocksize int) []byte {
    padding := blocksize - len(cipherText) % blocksize
    padText := bytes.Repeat([]byte{0}, padding)
    return
append(cipherText, padText...) // 往slice後新增元素 } // 刪除填充資料 func DeleZeroPadding(origData []byte) []byte { return bytes.TrimRightFunc(origData, func(r rune) bool { return r == rune(0) }) } // 使用加密演算法的步驟 // 1、根據密碼建立一個cipher // 2、得到加密塊的大小 // 3、按照塊的大小把填充原始資料 // 4、用block和key建立加密演算法 // 5、用CryptBlocks按照塊的大小進行加密
func AesEncrypt(origData, key []byte)([]byte, error) { block, err:=aes.NewCipher(key) // 根據key建立密碼 if err != nil { return nil, err } blockSize := block.BlockSize() // 得到加密塊的大小 origData = ZeroPadding(origData, blockSize) // 填充0 blockMode:=cipher.NewCBCEncrypter(block, key[:blockSize]) // 建立加密演算法
cryped:=make([]byte, len(origData)) // 生成存放加密資料的空間 blockMode.CryptBlocks(cryped, origData) // 按照塊大小加密 return cryped,nil } func AesDecrypt(cryptedData, key []byte)([]byte, error) { block, err:=aes.NewCipher(key) // 根據key建立密碼 if err != nil { return nil, err } blockSize := block.BlockSize() // 得到加密塊的大小 blockMode:=cipher.NewCBCDecrypter(block, key[:blockSize]) // 建立解密演算法 origData:=make([]byte, len(cryptedData)) // 建立存放解密串的空間 blockMode.CryptBlocks(origData, cryptedData) // 解密 cryptedData=DeleZeroPadding(origData) // 刪除填充資料 return cryptedData, nil } func main() { // 大括號的位置是固定的 ss := "zengraoli" // AES128 ,16,24,32,AES128,192,256 key:=[]byte("1234567891234567") // 加密 ssCryped, aesEncryptErr := AesEncrypt([]byte(ss), key) fmt.Println(string(ssCryped), aesEncryptErr) // 加密的資料用base64編碼 fmt.Println(base32.StdEncoding.EncodeToString(ssCryped)) origData, aesDecryptErr := AesDecrypt([]byte(ssCryped), key) fmt.Println(string(origData), aesDecryptErr) }

DES演算法

普通版的DES演算法

package main // 固定
import (
    "bytes"
    "fmt"
    "crypto/cipher"
    "encoding/base32"
    "crypto/des"
)

// 往字串後面填充0
func ZeroPadding(cipherText []byte, blocksize int) []byte {
    padding := blocksize - len(cipherText) % blocksize
    padText := bytes.Repeat([]byte{0}, padding)
    return append(cipherText, padText...) // 往slice後新增元素
}

// 刪除填充資料
func DeleZeroPadding(origData []byte) []byte {
    return bytes.TrimRightFunc(origData, func(r rune) bool {
        return r == rune(0)
    })
}

// 使用加密演算法的步驟
// 1、根據密碼建立一個cipher
// 2、得到加密塊的大小
// 3、按照塊的大小把填充原始資料
// 4、用block和key建立加密演算法
// 5、用CryptBlocks按照塊的大小進行加密
func DesEncrypt(origData, key []byte)([]byte, error) {
    block, err:=des.NewCipher(key) // 根據key建立密碼,和aes不同之處僅僅在這裡
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize() // 得到加密塊的大小
    origData = ZeroPadding(origData, blockSize) // 填充0
    blockMode:=cipher.NewCBCEncrypter(block, key[:blockSize]) // 建立加密演算法
    cryped:=make([]byte, len(origData)) // 生成存放加密資料的空間
    blockMode.CryptBlocks(cryped, origData) // 按照塊大小加密
    return cryped,nil
}

func DesDecrypt(cryptedData, key []byte)([]byte, error) {
    block, err:=des.NewCipher(key) // 根據key建立密碼
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize() // 得到加密塊的大小
    blockMode:=cipher.NewCBCDecrypter(block, key[:blockSize]) // 建立解密演算法
    origData:=make([]byte, len(cryptedData)) // 建立存放解密串的空間
    blockMode.CryptBlocks(origData, cryptedData) // 解密
    cryptedData=DeleZeroPadding(origData) // 刪除填充資料
    return cryptedData, nil
}

func main() { // 大括號的位置是固定的
    ss := "zengraoli"
    // DES key的長度為8
    key:=[]byte("12345678")
    // 加密
    ssCryped, aesEncryptErr := DesEncrypt([]byte(ss), key)
    fmt.Println(string(ssCryped), aesEncryptErr)
    // 加密的資料用base64編碼
    fmt.Println(base32.StdEncoding.EncodeToString(ssCryped))

    origData, aesDecryptErr := DesDecrypt([]byte(ssCryped), key)
    fmt.Println(string(origData), aesDecryptErr)
}

加強版的DES演算法

package main // 固定
import (
    "bytes"
    "fmt"
    "crypto/cipher"
    "encoding/base32"
    "crypto/des"
)

// 往字串後面填充0
func ZeroPadding(cipherText []byte, blocksize int) []byte {
    padding := blocksize - len(cipherText) % blocksize
    padText := bytes.Repeat([]byte{0}, padding)
    return append(cipherText, padText...) // 往slice後新增元素
}

// 刪除填充資料
func DeleZeroPadding(origData []byte) []byte {
    return bytes.TrimRightFunc(origData, func(r rune) bool {
        return r == rune(0)
    })
}

// 使用加密演算法的步驟
// 1、根據密碼建立一個cipher
// 2、得到加密塊的大小
// 3、按照塊的大小把填充原始資料
// 4、用block和key建立加密演算法
// 5、用CryptBlocks按照塊的大小進行加密
func DesEncrypt3(origData, key []byte)([]byte, error) {
    block, err:=des.NewTripleDESCipher(key) // 根據key建立密碼,NewTripleDESCipher和普通版本的強度不同
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize() // 得到加密塊的大小
    origData = ZeroPadding(origData, blockSize) // 填充0
    blockMode:=cipher.NewCBCEncrypter(block, key[:blockSize]) // 建立加密演算法
    cryped:=make([]byte, len(origData)) // 生成存放加密資料的空間
    blockMode.CryptBlocks(cryped, origData) // 按照塊大小加密
    return cryped,nil
}

func DesDecrypt3(cryptedData, key []byte)([]byte, error) {
    block, err:=des.NewTripleDESCipher(key) // 根據key建立密碼
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize() // 得到加密塊的大小
    blockMode:=cipher.NewCBCDecrypter(block, key[:blockSize]) // 建立解密演算法
    origData:=make([]byte, len(cryptedData)) // 建立存放解密串的空間
    blockMode.CryptBlocks(origData, cryptedData) // 解密
    cryptedData=DeleZeroPadding(origData) // 刪除填充資料
    return cryptedData, nil
}

func main() { // 大括號的位置是固定的
    ss := "zengraoli"
    // DES3 key的長度為24
    key:=[]byte("123456781234567812345678")
    // 加密
    ssCryped, aesEncryptErr := DesEncrypt3([]byte(ss), key)
    fmt.Println(string(ssCryped), aesEncryptErr)
    // 加密的資料用base64編碼
    fmt.Println(base32.StdEncoding.EncodeToString(ssCryped))

    origData, aesDecryptErr := DesDecrypt3([]byte(ssCryped), key)
    fmt.Println(string(origData), aesDecryptErr)
}

RSA演算法

RSA依賴於公鑰和私鑰,所以首先得到兩個函式用來生成公鑰和私鑰

package main // 固定
import (
    "fmt"
    "crypto/rsa"
    "crypto/rand"
    "crypto/x509"
    "encoding/pem"
    "os"
    "flag"
)

// 傳入生成key的種子
func GenRsaKey(bits int) error {
     // 傳入隨機數和種子
    privateKey, err := rsa.GenerateKey(rand.Reader, bits);
    if  err != nil {
        fmt.Println("私鑰生成失敗")
        return err
    }
    fmt.Println(privateKey)
    derStream:=x509.MarshalPKCS1PrivateKey(privateKey) // 處理privateKey
    block:=&pem.Block{
        Type:"RSA PRIVATE KEY",
        Bytes:derStream,
    }
    privateFile,err:=os.Create("myprivate.pem")
    if  err != nil {
        fmt.Println("私鑰生成失敗")
        return err
    }
    defer privateFile.Close()
    err = pem.Encode(privateFile, block) // 寫入到檔案
    if err != nil{
        fmt.Println("私鑰生成失敗")
        return err
    }

    // 生成公鑰
    publicKey:=&privateKey.PublicKey
    fmt.Println(publicKey)//列印公鑰
    //derpkix:=x509.MarshalPKCS1PublicKey(publicKey) // MarshalPKCS1PublicKey converts an RSA public key to PKCS#1, ASN.1 DER form.
    derpkix, err:=x509.MarshalPKIXPublicKey(publicKey) // 處理publicKey,MarshalPKIXPublicKey將公鑰序列化為 DER 編碼的 PKIX 格式。
    if err != nil{
        fmt.Println("公鑰生成失敗")
        return err
    }
    block=&pem.Block{
        Type:"RSA PUBLIC KEY",
        Bytes:derpkix,
    }
    publicFile, err:=os.Create("mypublic.pem")
    if  err != nil {
        fmt.Println("公鑰生成失敗")
        return err
    }
    defer publicFile.Close()
    err = pem.Encode(publicFile, block) // 寫入到檔案
    if err != nil{
        fmt.Println("公鑰生成失敗")
        return err
    }

    return nil
}

func main() { // 大括號的位置是固定的
    var bits int
    flag.IntVar(&bits, "b", 1024, "密碼長度預設為1024")
    if err := GenRsaKey(bits);err != nil {
        fmt.Println("金鑰檔案生成失敗")
    } else {
        fmt.Println("金鑰檔案生成成功")
    }
}

利用生成出來的公鑰和私鑰進行資料的加密

package main // 固定
import (
    "fmt"
    "crypto/rsa"
    "crypto/rand"
    "crypto/x509"
    "encoding/pem"
    "os"
    "errors"
    "encoding/base64"
)

var privateKey=[]byte(`
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDImW7UkM5QdNH1WTz1aGZw7uLJsdzQtzw6hWFfzcx1xCDS0u/Y
TRWWaA5cbitBXgFGzG9b8nAslISmKqyfhq+7QU/DykS7Jqy3Y6EsMlToiZhdGXkF
WWTBWZ2hz9gw+oh7H8cwnYjdB+pn0gol1wGFBkuxWqyitJYXSZE0MZXUjwIDAQAB
AoGBAJy6ZEFoMgnie/h5lIsY2pD50+9KLABWaZQ/iejUXh7U8eBGNmaFM4ykGDRX
TyxvSggKyibIsKPkFg/N37lz/e+nkx7eoABxVubm2gis3x5sJIyXzqSqY/EVWyLo
xY6fMk3fVQpRcrzvG9op3yWghM5cB3Mgrk/ZB0w/Rr0szuKBAkEA/iNuVuS8+ySY
55ykFbv4AhVY4OQVmds3mexdrBbzT0pHhyqQnhJ7ORcsdAaNIfxUNRHsGH7wTXwq
l023Gj4JsQJBAMoRmolb4LnDjaCCmqz8tx4VzSS/RVYaOrp944w0UJ+oxJOeHdsK
PRTgLz1UfiF/6B5pHG5ZDQTabFVgPn+TEj8CQEnqGixxqLlOop4yg9LCcdaBSPFX
xSSTiq9c/L2Ri0CTdQxOB/PBok8ve0FfqmqpDgDFbqqNOO0AYQ7Sjp+2TXECQHkL
4JImKtG9Fmsvsa6s2Jk6ICDCP6vbnJC49wW3FRD/jXqMfoAHex21SjcoFULGF2uY
NcLYr5bXrYvbUrUjigsCQQDIE8wU6vZtHFJx8eVWiTbHY4xwn0nLO0D6jrWcZJD4
E485YmBlqectmXhLkV7bPEMolgxlnpCOloxi6xC/zvSk
-----END RSA PRIVATE KEY-----
`)

var publicKey=[]byte(`
-----BEGIN RSA PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDImW7UkM5QdNH1WTz1aGZw7uLJ
sdzQtzw6hWFfzcx1xCDS0u/YTRWWaA5cbitBXgFGzG9b8nAslISmKqyfhq+7QU/D
ykS7Jqy3Y6EsMlToiZhdGXkFWWTBWZ2hz9gw+oh7H8cwnYjdB+pn0gol1wGFBkux
WqyitJYXSZE0MZXUjwIDAQAB
-----END RSA PUBLIC KEY-----
`)

// 傳入生成key的種子
func GenRsaKey(bits int) error {
     // 傳入隨機數和種子
    privateKey, err := rsa.GenerateKey(rand.Reader, bits);
    if  err != nil {
        fmt.Println("私鑰生成失敗")
        return err
    }
    fmt.Println(privateKey)
    derStream:=x509.MarshalPKCS1PrivateKey(privateKey) // 處理privateKey
    block:=&pem.Block{
        Type:"RSA PRIVATE KEY",
        Bytes:derStream,
    }
    privateFile,err:=os.Create("myprivate.pem")
    if  err != nil {
        fmt.Println("私鑰生成失敗")
        return err
    }
    defer privateFile.Close()
    err = pem.Encode(privateFile, block) // 寫入到檔案
    if err != nil{
        fmt.Println("私鑰生成失敗")
        return err
    }

    // 生成公鑰
    publicKey:=&privateKey.PublicKey
    fmt.Println(publicKey)//列印公鑰
    //derpkix:=x509.MarshalPKCS1PublicKey(publicKey) // MarshalPKCS1PublicKey converts an RSA public key to PKCS#1, ASN.1 DER form.
    derpkix, err:=x509.MarshalPKIXPublicKey(publicKey) // 處理publicKey,MarshalPKIXPublicKey將公鑰序列化為 DER 編碼的 PKIX 格式。
    if err != nil{
        fmt.Println("公鑰生成失敗")
        return err
    }
    block=&pem.Block{
        Type:"RSA PUBLIC KEY",
        Bytes:derpkix,
    }
    publicFile, err:=os.Create("mypublic.pem")
    if  err != nil {
        fmt.Println("公鑰生成失敗")
        return err
    }
    defer publicFile.Close()
    err = pem.Encode(publicFile, block) // 寫入到檔案
    if err != nil{
        fmt.Println("公鑰生成失敗")
        return err
    }

    return nil
}


// 用公鑰來加密
func RsaEncrypt(origData []byte)([]byte, error) {
    block, _:=pem.Decode(publicKey)
    if block == nil {
        return nil, errors.New("public key is bad.")
    }
    // 從公鑰的bytes中解析得到.PublicKey
    pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }
    pub:=pubInterface.(*rsa.PublicKey)
    return rsa.EncryptPKCS1v15(rand.Reader, pub, origData) // 加密
}

// 用私鑰來解密資料
func RsaDecrypt(ciphertext []byte)([]byte, error) {
    block, _:=pem.Decode(privateKey)
    if block == nil {
        return nil, errors.New("private key is bad.")
    }
    // 從私鑰的bytes中解析得到.PublicKey
    priInterface, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
        return nil, err
    }
    return rsa.DecryptPKCS1v15(rand.Reader, priInterface, ciphertext) // 加密
}

func main() { // 大括號的位置是固定的
    //var bits int
    //flag.IntVar(&bits, "b", 1024, "密碼長度預設為1024")
    //if err := GenRsaKey(bits);err != nil {
    //  fmt.Println("金鑰檔案生成失敗")
    //} else {
    //  fmt.Println("金鑰檔案生成成功")
    //}
    ss := "zengraoli"
    var encryptData, decryptData []byte
    var err error
    encryptData, err = RsaEncrypt([]byte(ss))
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("加密後的資料", base64.StdEncoding.EncodeToString(encryptData))

    decryptData, err = RsaDecrypt([]byte(encryptData))
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("解密後的資料", string(decryptData))
}


相關推薦

GO語言入門9---AESDESRSA演算法

目錄 AES演算法 package main // 固定 import ( "bytes" "fmt" "crypto/aes" "crypto/cipher" "encoding/base32" )

Go語言入門(一)特性安裝環境搭建第一個程序等

以及 rec 推出 eas log tell run 線程 package Go語言是谷歌推出的一種全新的編程語言,可以在不損失應用程序性能的情況下降低代碼的復雜性。谷歌首席軟件工程師羅布派克(Rob Pike)說:我們之所以開發Go,是因為過去10多年間軟件開發的難度令人

Crypto++入門學習筆記(DESAESRSASHA-256)

背景(只是個人感想,技術上不對後面的內容構成知識性障礙,可以skip): 最近,基於某些原因和需要,筆者需要去了解一下Crypto++庫,然後對一些資料進行一些加密解密的操作。 筆者之前沒接觸過任何加密解密方面的知識(當然,把每個字元的ASCII值加1之流對明文進行加密的“

Go語言入門——陣列切片和對映

## Go語言入門——陣列、切片和Map 按照以往開一些專題的風格,第一篇一般都是“從HelloWorld開始” 但是對於Go,思來想去,感覺真的從“HelloWorld”說起,壓根撐不住一篇的篇幅,因為Go的HelloWorld太簡

Go語言入門——陣列切片和對映(下)

上篇主要介紹了Go語言裡面常見的複合資料型別的宣告和初始化。 這篇主要針對陣列、切片和對映這些複合資料型別從其他幾個方面介紹比較下。 1、遍歷   不管是陣列、切片還是對映結構,都是一種集合型別,要從這些集合取出元素就要查詢或者遍歷。   對於從其他語言轉到Go語言,在遍歷這邊還是有稍稍不同的。 陣

Go語言入門教程系列——函式迴圈與分支

本文始發於個人公眾號:**TechFlow**,原創不易,求個關注 今天是Golang專題的第四篇,這一篇文章將會介紹golang當中的函式、迴圈以及選擇判斷的具體用法。 函式 在之前的文章當中其實我們已經接觸過函數了,因為我們寫的main函式本質上也是一個函式。只不過由於main函式沒有返回值,也

go語言sync包的學習(MutexWaitGroupCond)

pri lee 拷貝 light 等待 runt broadcast 計算 混亂 package main; import ( "fmt" "sync" "runtime" "time" ) //加鎖,註意鎖要以指針的形式傳進來,不然只是拷

Go語言高級特性總結——StructMap與JSON之間的轉化

err bsp make 特性 clas 高級 string comm tag Struct與Map之間互相轉換 1 // Struct2Map convert struct to map 2 func Struct2Map(st interface{}) map[s

Go語言開發(十二)Go語言常用標準庫二

after 更新 use har 相等 文件的 環境變量 its 內核 Go語言開發(十二)、Go語言常用標準庫二 一、os 1、os簡介 os 包提供了不依賴平臺的操作系統函數接口,設計像Unix風格,但錯誤處理是go風格,當os包使用時,如果失敗後返回錯誤類型而不是錯誤

Go語言開發(十一)Go語言常用標準庫一

lena unix doc 計算 cmd.run ner rem 信息 前綴 Go語言開發(十一)、Go語言常用標準庫一 一、log 1、log模塊簡介 Go語言中log模塊用於在程序中輸出日誌。log模塊提供了三類日誌輸出接口,Print、Fatal和Panic。Prin

go語言初體驗(流程控制range遍歷函式結構體面向物件)

一、流程控制 // main package main import ( "fmt" ) func main() { x := 2 switch x { case 1: fmt.Print("beifeng 1") case 2:

go語言初體驗(流程控制range遍歷函數結構體面向對象)

需要 3.3 fmt float compute 捕獲異常 value 地址 異常處理 一、流程控制 // main package main import ( "fmt" ) func main() { x := 2 switch x {

go語言函式傳遞問題(map切片介面chan)

一句話總結:map、切片、介面、函式型別、chan都是引用型別,作為函式引數傳遞不會複製一個副本。 package main import (     "fmt" ) func change(a int) {     a = 10 } func changeMap(m ma

golang常用加密解密演算法總結(AESDESRSASha1MD5)

在專案開發過程中,當操作一些使用者的隱私資訊,諸如密碼、帳戶金鑰等資料時,往往需要加密後可以在網上傳輸。這時,需要一些高效地、簡單易用的加密演算法加密資料,然後把加密後的資料存入資料庫或進行其他操作;當需要讀取資料時,把加密後的資料取出來,再通過演算法解密。 關於加密解密 當前我們專案中常用

程式猿之---C語言細節9(巨集定義max(a,b)巨集定義細節大小端判斷(int&)a什麼意思)

主要內容:巨集定義、max(a,b)巨集定義細節、大小端判斷、(int&)a什麼意思 #if 1 #include <stdio.h> // 注意空格 #define F (x) ((x) - 1) // F代表後面 #define F(x)

C語言入門(4)——常量變數與賦值

對於基本資料型別量,按其取值是否可改變又分為常量和變數兩種。在程式執行過程中,其值不發生改變的量稱為常量,其值可變的量稱為變數。它們可與資料型別結合起來分類。常量常量有字元常量(CharacterConstant)、數字常量和列舉常量。列舉常量以後再介紹,現在我們看看如何使用

Go語言開發(十四)Go語言常用標準庫四

[] remove current heap ++ hba 指針 遊戲 lec Go語言開發(十四)、Go語言常用標準庫四 一、heap 1、heap簡介 heap僅僅提供了最小堆的操作,沒有提供堆的數據結構,堆的數據結構必須由開發者自己實現。heap提供了一個heap.I

Go語言開發(十五)Go語言常用標準庫五

x509 ges elements header 安全系統 保存 sha1 三人 數字證書 Go語言開發(十五)、Go語言常用標準庫五 一、md5 1、md5簡介 md5在crypto/md5包中,md5包提供了New和Sum方法。 func New() hash.Hash

Go語言開發(十八)Go語言MySQL數據庫操作

har fail sid 內部 分析 face ack rgs 釋放 Go語言開發(十八)、Go語言MySQL數據庫操作 一、MySQL數據庫驅動 1、MySQL數據庫驅動簡介 Go語言官方沒有實現MySQL數據庫驅動,常用的開源MySQL數據庫驅動實現如下:(1)Go M

Go語言開發(二十)GoStub測試框架

str urn ... art 有一個 進行 single 單元測試框架 gost Go語言開發(二十)、GoStub測試框架 一、GoStub簡介 GoStub是一款輕量級的單元測試框架,接口友好,可以對全局變量、函數或過程進行打樁。GoStub安裝:go get git