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---AES、DES、RSA演算法
目錄 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++入門學習筆記(DES、AES、RSA、SHA-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包的學習(Mutex、WaitGroup、Cond)
pri lee 拷貝 light 等待 runt broadcast 計算 混亂 package main; import ( "fmt" "sync" "runtime" "time" ) //加鎖,註意鎖要以指針的形式傳進來,不然只是拷
Go語言高級特性總結——Struct、Map與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常用加密解密演算法總結(AES、DES、RSA、Sha1MD5)
在專案開發過程中,當操作一些使用者的隱私資訊,諸如密碼、帳戶金鑰等資料時,往往需要加密後可以在網上傳輸。這時,需要一些高效地、簡單易用的加密演算法加密資料,然後把加密後的資料存入資料庫或進行其他操作;當需要讀取資料時,把加密後的資料取出來,再通過演算法解密。 關於加密解密 當前我們專案中常用
程式猿之---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