當前位置:首頁 » 密碼管理 » go加密解密

go加密解密

發布時間: 2023-08-20 22:46:40

Ⅰ 7 Go密碼學(四) 非對稱加密之RSA

對稱加舉鉛密有非常好的安全性,其加解密計算的性能也較高,但其有兩個重要缺點:

在如今開放的信息社會,秘鑰的管理愈加困難,非公開的秘鑰機制雖然破解較難,但還是有遭到攻擊的可能性,由於對稱加密需要加解密雙方共同握有私鑰,所有生成秘鑰的一方必須分發給含轎另一方才能進行安全通行,這就難免秘鑰在網路中傳輸,網路是不可靠的,其有可能被攔截或篡改。於是就產生了公開秘鑰體制,即服務方根據特定演算法產生一對鑰匙串,自己持有私鑰小心保存,而公鑰公開分發,在通信中,由公鑰加密進行網路傳輸,而傳輸的信息只正老好能由私鑰解密,這就解決了秘鑰分發的問。公開秘鑰體制就是非對稱加密,非對稱加密一般有兩種用途:

如今的非對稱加密比較可靠的有RSA演算法和ECC演算法(橢圓曲線演算法),RSA的受眾最多,但近年來隨著比特幣、區塊鏈的興起,ECC加密演算法也越來越受到青睞。下面我們先介紹一下RSA加密演算法的使用,ECC我們下一講展開。

公鑰密碼體系都是要基於一個困難問題來保證其安全性的,RSA是基於大數分解,將一個即使是計算機也無能為力的數學問題作為安全壁壘是現代密碼學的實現原理。講述這類數學問題需要龐雜的數論基礎,此相關部分在此不再展開,感興趣的請出門右拐搜索歐幾里得證明、歐拉函數等數論部分知識。

Go標准庫中crypto/rsa包實現了RSA加解密演算法,並通過crypto/x509包實現私鑰序列化為ASN.1的DER編碼字元串的方法,我們還使用編解碼包encoding/pem(實現了PEM數據編碼,該格式源自保密增強郵件協議,目前PEM編碼主要用於TLS密鑰和證書。)將公私鑰數據編碼為pem格式的證書文件。

使用以上加解密方法:

Ⅱ 什麼是3DES對稱加密演算法

DES加密經過下面的步驟
1、提供明文和密鑰,將明文按照64bit分塊(對應8個位元組),不足8個位元組的可以進行填充(填充方式多種),密鑰必須為8個位元組共64bit
填充方式:

當明文長度不為分組長度的整數倍時,需要在最後一個分組中填充一些數據使其湊滿一個分組長度。
* NoPadding
API或演算法本身不對數據進行處理,加密數據由加密雙方約定填補演算法。例如若對字元串數據進行加解密,可以補充\0或者空格,然後trim

* PKCS5Padding
加密前:數據位元組長度對8取余,余數為m,若m>0,則補足8-m個位元組,位元組數值為8-m,即差幾個位元組就補幾個位元組,位元組數值即為補充的位元組數,若為0則補充8個位元組的8
解密後:取最後一個位元組,值為m,則從數據尾部刪除m個位元組,剩餘數據即為加密前的原文。
例如:加密字元串為為AAA,則補位為AAA55555;加密字元串為BBBBBB,則補位為BBBBBB22;加密字元串為CCCCCCCC,則補位為CCCCCCCC88888888。

* PKCS7Padding
PKCS7Padding 的填充方式和PKCS5Padding 填充方式一樣。只是加密塊的位元組數不同。PKCS5Padding明確定義了加密塊是8位元組,PKCS7Padding加密快可以是1-255之間。
2、選擇加密模式

**ECB模式** 全稱Electronic Codebook模式,譯為電子密碼本模式
**CBC模式** 全稱Cipher Block Chaining模式,譯為密文分組鏈接模式
**CFB模式** 全稱Cipher FeedBack模式,譯為密文反饋模式
**OFB模式** 全稱Output Feedback模式,譯為輸出反饋模式。
**CTR模式** 全稱Counter模式,譯為計數器模式。
3、開始加密明文(內部原理--加密步驟,加密演算法實現不做講解)

image
1、將分塊的64bit一組組加密,示列其中一組:將此組進行初始置換(IP置換),目的是將輸入的64位數據塊按位重新組合,並把輸出分為L0、R0兩部分,每部分各長32位。
2、開始Feistel結構的16次轉換,第一次轉換為:右側數據R0和子密鑰經過輪函數f生成用於加密左側數據的比特序列,與左側數據L0異或運算,
運算結果輸出為加密後的左側L0,右側數據則直接輸出為右側R0。由於一次Feistel輪並不會加密右側,因此需要將上一輪輸出後的左右兩側對調後才正式完成一次Feistel加密,
3、DES演算法共計進行16次Feistel輪,最後一輪輸出後左右兩側無需對調,每次加密的子密鑰不相同,子密鑰是通過秘鑰計算得到的。
4、末置換是初始置換的逆過程,DES最後一輪後,左、右兩半部分並未進行交換,而是兩部分合並形成一個分組做為末置換的輸入
DES解密經過下面的步驟
1、拿到密文和加密的密鑰
2、解密:DES加密和解密的過程一致,均使用Feistel網路實現,區別僅在於解密時,密文作為輸入,並逆序使用子密鑰。
3、講解密後的明文去填充 (padding)得到的即為明文
Golang實現DES加密解密
package main

import (
"fmt"
"crypto/des"
"bytes"
"crypto/cipher"
)

func main() {
var miwen,_= DESEncode([]byte("hello world"),[]byte("12345678"))
fmt.Println(miwen) // [11 42 146 232 31 180 156 225 164 50 102 170 202 234 123 129],密文:最後5位是補碼
var txt,_ = DESDecode(miwen,[]byte("12345678"))
fmt.Println(txt) // [104 101 108 108 111 32 119 111 114 108 100]明碼
fmt.Printf("%s",txt) // hello world
}
// 加密函數
func DESEncode(orignData, key []byte)([]byte,error){

// 建立密碼塊
block ,err:=des.NewCipher(key)
if err!=nil{ return nil,err}

// 明文分組,不足的部分加padding
txt := PKCS5Padding(orignData,block.BlockSize())

// 設定加密模式,為了方便,初始向量直接使用key充當了(實際項目中,最好別這么做)
blockMode := cipher.NewCBCEncrypter(block,key)

// 創建密文長度的切片,用來存放密文位元組
crypted :=make([]byte,len(txt))

// 開始加密,將txt作為源,crypted作為目的切片輸入
blockMode.CryptBlocks(crypted,txt)

// 將加密後的切片返回
return crypted,nil
}
// 加密所需padding
func PKCS5Padding(ciphertext []byte,size int)[]byte{
padding := size - len(ciphertext)%size
padTex := bytes.Repeat([]byte{byte(padding)},padding)
return append(ciphertext,padTex...)
}
// 解密函數
func DESDecode(cripter, key []byte) ([]byte,error) {
// 建立密碼塊
block ,err:=des.NewCipher(key)
if err!=nil{ return nil,err}

// 設置解密模式,加密模式和解密模式要一樣
blockMode := cipher.NewCBCDecrypter(block,key)

// 設置切片長度,用來存放明文位元組
originData := make([]byte,len(cripter))

// 使用解密模式解密,將解密後的明文位元組放入originData 切片中
blockMode.CryptBlocks(originData,cripter)

// 去除加密的padding部分
strByt := UnPKCS5Padding(origenData)

return strByt,nil
}
// 解密所需要的Unpadding
func UnPKCS5Padding(origin []byte) []byte{
// 獲取最後一位轉為整型,然後根據這個整型截取掉整型數量的長度
// 若此數為5,則減掉轉換明文後的最後5位,即為我們輸入的明文
var last = int(origin[len(origin)-1])
return origin[:len(origin)-last]
}
注意:在設置加密模式為CBC的時候,我們需要設置一個初始化向量,這個量的意思 在對稱加密演算法中,如果只有一個密鑰來加密數據的話,明文中的相同文字就會也會被加密成相同的密文,這樣密文和明文就有完全相同的結構,容易破解,如果給一個初始化向量,第一個明文使用初始化向量混合並加密,第二個明文用第一個明文的加密後的密文與第二個明文混合加密,這樣加密出來的密文的結構則完全與明文不同,更加安全可靠。CBC模式圖如下

CBC
3DES
DES 的常見變體是三重 DES,使用 168 位的密鑰對資料進行三次加密的一種機制;它通常(但非始終)提供極其強大的安全性。如果三個 56 位的子元素都相同,則三重 DES 向後兼容 DES。
對比DES,發現只是換了NewTripleDESCipher。不過,需要注意的是,密鑰長度必須24byte,否則直接返回錯誤。關於這一點,PHP中卻不是這樣的,只要是8byte以上就行;而java中,要求必須是24byte以上,內部會取前24byte(相當於就是24byte)。另外,初始化向量長度是8byte(目前各個語言都是如此,不是8byte會有問題)

Ⅲ 對稱加密演算法以及使用方法

加密的原因:保證數據安全

加密必備要素:1、明文/密文    2、秘鑰    3、演算法

秘鑰:在密碼學中是一個定長的字元串、需要根據加密演算法確定其長度

加密演算法解密演算法一般互逆、也可能相同

常用的兩種加密方式:

對稱加密:秘鑰:加密解密使用同一個密鑰、數據的機密性雙向保證、加密效率高、適合加密於大數據大文件、加密強度不高(相對於非對稱加密)

非對稱加密:秘鑰:加密解密使用的不同秘鑰、有兩個密鑰、需要使用密鑰生成演算法生成兩個秘鑰、數據的機密性只能單向加密、如果想解決這個問題、雙向都需要各自有一對秘鑰、加密效率低、加密強度高

                    公鑰:可以公開出來的密鑰、公鑰加密私鑰解密

                    私鑰:需要自己妥善保管、不能公開、私鑰加密公鑰解密

安全程度高:多次加密

按位異或運算

凱撒密碼:加密方式    通過將銘文所使用的字母表按照一定的字數平移來進行加密

mod:取余

加密三要素:明文/密文(字母)、秘鑰(3)、演算法(向右平移3/-3)

安全常識:不要使用自己研發的演算法、不要鑽牛角尖、沒必要研究底層實現、了解怎麼應用;低強度的密碼比不進行任何加密更危險;任何密碼都會被破解;密碼只是信息安全的一部分

保證數據的機密性、完整性、認證、不可否認性

計算機操作對象不是文字、而是由0或1排列而成的比特序列、程序存儲在磁碟是二進制的字元串、為比特序列、將現實的東西映射為比特序列的操作稱為編碼、加密又稱之為編碼、解密稱之為解碼、根據ASCII對照表找到對應的數字、轉換成二進制

三種對稱加密演算法:DES\3DES\ AES  

DES:已經被破解、除了用它來解密以前的明文、不再使用

密鑰長度為56bit/8、為7byte、每隔7個bit會設置一個用於錯誤檢查的比特、因此實際上是64bit

分組密碼(以組為單位進行處理):加密時是按照一個單位進行加密(8個位元組/64bit為一組)、每一組結合秘鑰通過加密演算法得到密文、加密後的長度不變

3DES:三重DES為了增加DES的強度、將DES重復三次所得到的一種加密演算法   密鑰長度24byte、分成三份  加密--解密--加密 目的:為了兼容DES、秘鑰1秘鑰2相同==三個秘鑰相同  ---加密一次        密鑰1秘鑰3相同--加密三次    三個密鑰不相同最好、此時解密相當於加密、中間的一次解密是為了有三個密鑰相同的情況

此時的解密操作與加密操作互逆,安全、效率低

數據先解密後加密可以么?可以、解密相當於加密、加密解密說的是演算法

AES:(首選推薦)底層演算法為Rijndael   分組長度為128bit、密鑰長度為128bit到256bit范圍內就可以   但是在AES中、密鑰長度只有128bit\192bit\256bit     在go提供的介面中、只能是16位元組(128bit)、其他語言中秘鑰可以選擇

目前為止最安全的、效率高

底層演算法

分組密碼的模式:

按位異或、對數據進行位運算、先將數據轉換成二進制、按位異或操作符^、相同為真、不同為假、非0為假    按位異或一次為加密操作、按位異或兩次為解密操作:a和b按位異或一次、結果再和b按位異或

ECB : 如果明文有規律、加密後的密文有規律不安全、go里不提供該介面、明文分組分成固定大小的塊、如果最後一個分組不滿足分組長度、則需要補位

CBC:密碼鏈

問題:如何對字元串進行按位異或?解決了ECB的規律可查缺點、但是他不能並行處理、最後一個明文分組也需要填充 、初始化向量長度與分組長度相同

CFB:密文反饋模式

不需要填充最後一個分組、對密文進行加密

OFB:

不需要對最後一組進行填充

CTR計數器:

不需要對最後一組進行填充、不需要初始化向量     

Go中的實現

官方文檔中:

在創建aes或者是des介面時都是調用如下的方法、返回的block為一個介面

func NewCipher(key [] byte ) ( cipher . Block , error )

type Block interface {

    // 返回加密位元組塊的大小

    BlockSize() int

    // 加密src的第一塊數據並寫入dst,src和dst可指向同一內存地址

    Encrypt(dst, src []byte)

    // 解密src的第一塊數據並寫入dst,src和dst可指向同一內存地址

    Decrypt(dst, src []byte)

}

Block介面代表一個使用特定密鑰的底層塊加/解密器。它提供了加密和解密獨立數據塊的能力。

Block的Encrypt/Decrypt也能進行加密、但是只能加密第一組、因為aes的密鑰長度為16、所以進行操作的第一組數據長度也是16

如果分組模式選擇的是cbc

func NewCBCEncrypter(b Block, iv []byte) BlockMode    加密

func NewCBCDecrypter(b Block, iv []byte) BlockMode    解密

加密解密都調用同一個方法CryptBlocks()

並且cbc分組模式都會遇到明文最後一個分組的補充、所以會用到加密位元組的大小

返回一個密碼分組鏈接模式的、底層用b加密的BlockMode介面,初始向量iv的長度必須等於b的塊尺寸。iv自己定義

返回的BlockMode同樣也是一個介面類型

type BlockMode interface {

    // 返回加密位元組塊的大小

    BlockSize() int

    // 加密或解密連續的數據塊,src的尺寸必須是塊大小的整數倍,src和dst可指向同一內存地址

    CryptBlocks(dst, src []byte)

}

BlockMode介面代表一個工作在塊模式(如CBC、ECB等)的加/解密器

返回的BlockMode其實是一個cbc的指針類型中的b和iv

# 加密流程: 

1. 創建一個底層使用des/3des/aes的密碼介面 "crypto/des" func NewCipher(key []byte) (cipher.Block, error) # -- des func NewTripleDESCipher(key []byte) (cipher.Block, error) # -- 3des "crypto/aes" func NewCipher(key []byte) (cipher.Block, error) # == aes 

2. 如果使用的是cbc/ecb分組模式需要對明文分組進行填充

3. 創建一個密碼分組模式的介面對象 - cbc func NewCBCEncrypter(b Block, iv []byte) BlockMode # 加密 - cfb func NewCFBEncrypter(block Block, iv []byte) Stream # 加密 - ofb - ctr

 4. 加密, 得到密文

流程:

填充明文:

先求出最後一組中的位元組數、創建新切片、長度為新切片、值也為切片的長度、然後利用bytes.Reapet將長度換成位元組切片、追加到原明文中

//明文補充

func padPlaintText(plaintText []byte,blockSize int)[]byte{

    //1、求出需要填充的個數

    padNum := blockSize-len(plaintText) % blockSize

    //2、對填充的個數進行操作、與原明文進行合並

    newPadding := []byte{byte(padNum)}

    newPlain := bytes.Repeat(newPadding,padNum)

    plaintText = append(plaintText,newPlain...)

    return plaintText

}

去掉填充數據:

拿去切片中的最後一個位元組、得到尾部填充的位元組個數、截取返回

//解密後的明文曲調補充的地方

func createPlaintText(plaintText []byte,blockSize int)[]byte{

    //1、得到最後一個位元組、並將位元組轉換成數字、去掉明文中此數字大小的位元組

    padNum := int(plaintText[len(plaintText)-1])

    newPadding := plaintText[:len(plaintText)-padNum]

    return newPadding

}

des加密:

1、創建一個底層使用des的密碼介面、參數為秘鑰、返回一個介面

2、對明文進行填充

3、創建一個cbc模式的介面、需要創建iv初始化向量、返回一個blockmode對象

4、加密、調用blockmode中的cryptBlock函數進行加密、參數為目標參數和源參數

//des利用分組模式cbc進行加密

func EncryptoText(plaintText []byte,key []byte)[]byte{

    //1、創建des對象

    cipherBlock,err := des.NewCipher(key)

    if err != nil {

        panic(err)

    }

    //2、對明文進行填充

    newText := padPlaintText(plaintText,cipherBlock.BlockSize())

    //3、選擇分組模式、其中向量的長度必須與分組長度相同

    iv := make([]byte,cipherBlock.BlockSize())

    blockMode := cipher.NewCBCEncrypter(cipherBlock,iv)

    //4、加密

    blockMode.CryptBlocks(newText,newText)

    return newText

}

des解密:

1、創建一個底層使用des的密碼介面、參數為秘鑰、返回一個介面

2、創建一個cbc模式的介面、需要創建iv初始化向量,返回一個blockmode對象

3、加密、調用blockmode中的cryptBlock函數進行解密、參數為目標參數和源參數

4、調用去掉填充數據的方法

//des利用分組模式cbc進行解密

func DecryptoText(cipherText []byte, key []byte)[]byte{

    //1、創建des對象

    cipherBlock,err := des.NewCipher(key)

    if err != nil {

        panic(err)

    }

    //2、創建cbc分組模式介面

    iv := []byte("12345678")

    blockMode := cipher.NewCBCDecrypter(cipherBlock,iv)

    //3、解密

    blockMode.CryptBlocks(cipherText,cipherText)

    //4、將解密後的數據進行去除填充的數據

    newText := clearPlaintText(cipherText,cipherBlock.BlockSize())

    return newText

}

Main函數調用

func main(){

    //需要進行加密的明文

    plaintText := []byte("CBC--密文沒有規律、經常使用的加密方式,最後一個分組需要填充,需要初始化向量" +

        "(一個數組、數組的長度與明文分組相等、數據來源:負責加密的人提供,加解密使用的初始化向量必須相同)")

    //密鑰Key的長度需要與分組長度相同、且加密解密的密鑰相同

    key := []byte("1234abcd")

    //調用加密函數

    cipherText := EncryptoText(plaintText,key)

    newPlaintText := DecryptoText(cipherText,key)

    fmt.Println(string(newPlaintText))

}

AES加密解密相同、所以只需要調用一次方法就可以加密、調用兩次則解密

推薦是用分組模式:cbc、ctr

aes利用分組模式cbc進行加密

//對明文進行補充

func paddingPlaintText(plaintText []byte , blockSize int ) []byte {

    //1、求出分組余數

    padNum := blockSize - len(plaintText) % blockSize

    //2、將余數轉換為位元組切片、然後利用bytes.Repeat得出有該余數的大小的位元組切片

    padByte := bytes.Repeat([]byte{byte(padNum)},padNum)

    //3、將補充的位元組切片添加到原明文中

    plaintText = append(plaintText,padByte...)

    return plaintText

}

//aes加密

func encryptionText(plaintText []byte, key []byte) []byte {

    //1、創建aes對象

    block,err := aes.NewCipher(key)

    if err != nil {

        panic(err)

    }

    //2、明文補充

    newText := paddingPlaintText(plaintText,block.BlockSize())

    //3、創建cbc對象

    iv := []byte("12345678abcdefgh")

    blockMode := cipher.NewCBCEncrypter(block,iv)

    //4、加密

    blockMode.CryptBlocks(newText,newText)

    return newText

}

//解密後的去尾

func clearplaintText(plaintText []byte, blockSize int) []byte {

    //1、得到最後一個位元組、並轉換成整型數據

    padNum := int(plaintText[len(plaintText)-1])

    //2、截取明文位元組中去掉得到的整型數據之前的數據、此處出錯、沒有用len-padNum

    newText := plaintText[:len(plaintText)-padNum]

    return newText

}

//aes解密

func deCryptionText(crypherText []byte, key []byte ) []byte {

    //1、創建aes對象

    block, err := aes.NewCipher(key)

    if err != nil {

        panic(err)

    }

    //2、創建cbc對象

    iv := []byte("12345678abcdefgh")

    blockMode := cipher.NewCBCDecrypter(block,iv)

    //3、解密

    blockMode.CryptBlocks(crypherText,crypherText)

    //4、去尾

    newText := clearplaintText(crypherText,block.BlockSize())

    return newText

}

func main(){

    //需要進行加密的明文

    plaintText := []byte("CBC--密文沒有規律、經常使用的加密方式,最後一個分組需要填充,需要初始化向量")

    //密鑰Key的長度需要與分組長度相同、且加密解密的密鑰相同

    key := []byte("12345678abcdefgh")

    //調用加密函數

    cipherText := encryptionText(plaintText,key)

    //調用解密函數

    newPlaintText := deCryptionText(cipherText,key)

    fmt.Println("解密後",string(newPlaintText))

}

//aes--ctr加密

func encryptionCtrText(plaintText []byte, key []byte) []byte {

    //1、創建aes對象

    block,err := aes.NewCipher(key)

    if err != nil {

        panic(err)

    }

    //2、創建ctr對象,雖然ctr模式不需要iv,但是go中使用ctr時還是需要iv

    iv := []byte("12345678abcdefgh")

    stream := cipher.NewCTR(block,iv)

    stream.XORKeyStream(plaintText,plaintText)

    return plaintText

}

func main() {

//aes--ctr加密解密、調用兩次即為解密、因為加密解密函數相同stream.XORKeyStream

    ctrcipherText := encryptionCtrText(plaintText, key)

    ctrPlaintText := encryptionCtrText(ctrcipherText,key)

    fmt.Println("aes解密後", string(ctrPlaintText))

}

英文單詞:

明文:plaintext     密文:ciphertext   填充:padding/fill    去掉clear  加密Encryption  解密Decryption

Ⅳ java 生成的私鑰 go語言為什麼不能用來解密對應Java公鑰加密過的數據

跟語言無關,跟加密演算法有關。你如果調用公開的演算法,用同樣的運算元去加密解密,那用哪種需要都一樣,關鍵就是很多演算法都有你不了解的細節,有些運算元是編程語言自己用了默認值,而他們彼此不同

熱點內容
ip跨網段訪問 發布:2025-01-31 02:44:42 瀏覽:708
演算法帶頭人 發布:2025-01-31 02:42:25 瀏覽:551
方舟上傳數據 發布:2025-01-31 02:42:25 瀏覽:835
鈴木uy比uu多了什麼配置 發布:2025-01-31 02:34:11 瀏覽:676
蝦米音樂緩存文件夾 發布:2025-01-31 02:34:04 瀏覽:886
主播用什麼我的世界啟動器玩伺服器 發布:2025-01-31 02:32:37 瀏覽:643
做電腦硬體需要哪些配置 發布:2025-01-31 02:30:53 瀏覽:439
小米智能門鎖驗證密碼是多少 發布:2025-01-31 02:30:50 瀏覽:533
oracle和sql區別 發布:2025-01-31 02:27:40 瀏覽:241
汽車網源碼下載 發布:2025-01-31 01:58:30 瀏覽:100