江湖“密”事——对称加密

Posted BlockchainGo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了江湖“密”事——对称加密相关的知识,希望对你有一定的参考价值。


对称加密,即对一组数据采用相同的密钥进行加密和解密。常用的对称加密有DES、3DES、AES,下面分别来实现(实际使用注意加如err处理)。

DES对称加密,密钥长度必须为8字节,CBC模式

package mainimport (    
   "crypto/des"    "bytes"    "crypto/cipher"    "fmt"

)
//DES
func main()  {    
   //原文数据    data:=[]byte("hello world")    
   //密钥,8位    key:=[]byte("12345678")    
   //调用DES加密获取加密后数据    encryptoData := DesEncrypto(data, key)    
   //对加密数据进行DES解密获取原文    originData := DesDecrypto(encryptoData, key)    
   //验证是否成功解密出原文    fmt.Println(string(originData)) }
 
//DES加密
func DesEncrypto(data,key []byte) []byte{    
//获取密钥块    block, _ := des.NewCipher(key)    
//设置加密方式(CBC模式),获取加密器    encrypter := cipher.NewCBCEncrypter(block, key)    
//填充补码    paddingData := PKCS5Padding(data, block.BlockSize())    
//创建填充后的明文长度的字节数组    bs := make([]byte, len(paddingData))    encrypter.CryptBlocks(bs,paddingData)    return bs }

//补码
func PKCS5Padding(data []byte,blockSize int)[]byte  {    dataLen := len(data)
   //补多少位数    padding:=blockSize-dataLen%blockSize  
    //补x位,就得到x个元素的切片[x,x,x...]    paddingBytes:=bytes.Repeat([]byte{byte(padding)},padding)    
    return append(data,paddingBytes...) }
    
//DES解密
func DesDecrypto(data,key []byte)[]byte {    block, _ := des.NewCipher(key)    
//设置解密方式(5种选1种),获取解密器    decrypter := cipher.NewCBCDecrypter(block, key)    bs := make([]byte, len(data))    decrypter.CryptBlocks(bs,data)    
//去除补码    bs=PKCS5Unpadding(bs)    return bs }
//去补码
func PKCS5Unpadding(data []byte)[]byte {    length := len(data)    lastByte := int(data[length-1])    return data[:(length-lastByte)] }

3DES对称加密,密钥长度必须为24字节,CBC模式

package mainimport (    
   "bytes"    "crypto/des"    "crypto/cipher"    "fmt"

)
   
   func main() {    
   //明文数据    data:=[]byte("hello world")    
   //声明密钥,24位    key:=[]byte("123456781234567812345678")    encryptoData := TripleDesEncrypto(data, key)    originData := TripleDesDecrypto(encryptoData, key)    fmt.Println(string(originData)) }
   
//3DES加密
func TripleDesEncrypto(data, key []byte) []byte {    block, _ := des.NewTripleDESCipher(key)    
//设置加密模式(CBC模式),获取加密器    encrypter := cipher.NewCBCEncrypter(block, key[:8])    
//填充补码    paddingData := DES3PKCS5Padding(data, block.BlockSize())    
//创建填充后的数据长度的数组    bs := make([]byte, len(paddingData))    encrypter.CryptBlocks(bs,paddingData)    
   return bs }
   
//填充补码
func DES3PKCS5Padding(data []byte, blocksize int) []byte {    
   len := len(data)    paddingLen:=blocksize-len%blocksize    repeat := bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)    
   return append(data,repeat...) }
   
//3DES解密
func TripleDesDecrypto(data, key []byte) []byte {    block, _ := des.NewTripleDESCipher(key)    
//设置解密模式(CBC),获取解密器    decrypter := cipher.NewCBCDecrypter(block, key[:8])    
//创建密文数组    bs := make([]byte, len(data))    decrypter.CryptBlocks(bs,data)    
//去补码    unPadding := DES3PKCS5Unpadding(bs)    
   return unPadding }

//去补码
func DES3PKCS5Unpadding(data []byte)[]byte  {    dataLen := len(data)    last:=data[dataLen-1]    
   return data[:dataLen-int(last)] }

AES对称加密,密钥长度可以取8、24、32字节

由于DES和3DES破解难度不足,所以DES、3DES几乎完全被AES取代,所以一般
直接使用AES即可。
package mainimport (    
   "bytes"    "crypto/aes"    "crypto/cipher"    "fmt"

)

func main() {    data := []byte("abcde")    
//密钥超度8、24、32位皆可    key:=[]byte("12345678abcdefgh")    encryptoData := AesEncrypto(data,key)    originData := AesDecrypto(encryptoData, key)    fmt.Println(string(originData)) }

//加密
func AesEncrypto(data, key []byte) []byte {    
//获取秘钥块    block, _ := aes.NewCipher(key)    blockSize := block.BlockSize()  
//获取加密器    encrypter := cipher.NewCBCEncrypter(block, key[:blockSize])  
 //填充补码    paddingData := PKCS7Padding(data, blockSize)    bs := make([]byte, len(paddingData))    
 //加密    encrypter.CryptBlocks(bs,paddingData)    
 return bs }
 
 //补码
func PKCS7Padding(data []byte,blocksize int)[]byte {    length := len(data)    paddingLen:=blocksize-length%blocksize    paddingBytes := bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)    
     return append(data,paddingBytes...) }
     
     //解密
func AesDecrypto(data, key []byte) []byte {    block, _ := aes.NewCipher(key)    blockSize := block.BlockSize()    decrypter := cipher.NewCBCDecrypter(block, key[:blockSize])    bs := make([]byte, len(data))  
      //先解密    decrypter.CryptBlocks(bs,data)
       //再去补码    unPaddingData := PKCS7UnPadding(bs)  
        return unPaddingData }
        
        //去补码
func PKCS7UnPadding(data []byte) []byte  {    length := len(data)    lastByte := int(data[length-1])  
   return data[:length-lastByte] }

AES加密,CFB模式

package mainimport (  
 "crypto/aes"    "crypto/cipher"    "crypto/rand"    "io"    "fmt"

)
 
 //通过CFB模式,进行AES加密func main() {    data := []byte("abcd")    key:=[]byte("123456789abcdefg")    
 var encryptocode = AesEncrypto(data,key)    
 var decryptocode = AesDecrypto(encryptocode, key)    fmt.Print(string(decryptocode)) }
 
 //加密
func AesEncrypto(data,key []byte) []byte {  
  //分组秘钥    block, _ := aes.NewCipher(key)  
   //创建数组    bs := make([]byte, aes.BlockSize+len(data))    
   //设置内存空间可读    bytes := bs[:aes.BlockSize]    io.ReadFull(rand.Reader, bytes)  
    //设置加密模式    encrypter := cipher.NewCFBEncrypter(block, bytes)  
     //加密    encrypter.XORKeyStream(bs[aes.BlockSize:], data)    
     return bs }
     
     //解密
func AesDecrypto(data []byte, key []byte) []byte {    block, _ := aes.NewCipher(key)    bytes := data[:aes.BlockSize]    data = data[aes.BlockSize:]  
      //设置解密方式    stream := cipher.NewCFBDecrypter(block, bytes)  
        //解密    stream.XORKeyStream(data, data)    return data }

AES加密,OFB模式

package mainimport (    
   "io"    "crypto/cipher"    "crypto/aes"    "crypto/rand"    "fmt"
)
 
   func main() {    data:=[]byte("hello world")    key := []byte("6368616e676520746869732070617374")    
   // 加密    result, _ := AesEncrypt(data, key)    
   // 解密    originData, _ := AesDecrypt(result, key)    fmt.Println(string(originData)) }
   
   // 加密函数
func AesEncrypt(data, key []byte) ([]byte, error) {    block, err := aes.NewCipher(key)  
   if err != nil {      
    return nil, err    }    ciphertext := make([]byte, aes.BlockSize+len(data))    iv := ciphertext[:aes.BlockSize]    
    if _, err := io.ReadFull(rand.Reader, iv);
    err != nil {        
    panic(err)    }    
    
    // NewOFB返回一个在输出反馈模式下使用分组密码b进行加密或解密的Stream。初始化矢量iv的长度必须等于b的块大小。    stream := cipher.NewOFB(block, iv)    stream.XORKeyStream(ciphertext[aes.BlockSize:], data)  
     return ciphertext, nil

}
     
     // 解密函数
func AesDecrypt(ciphertext, key []byte) ([]byte, error) {    block, err := aes.NewCipher(key)  
      if err != nil {      
       return nil, err    }  
        // The IV needs to be unique, but not secure. Therefore it's common to    // include it at the beginning of the ciphertext.    iv := ciphertext[:aes.BlockSize]    
        if len(ciphertext) < aes.BlockSize {      
         panic("ciphertext too short")    }    plaintext2 := make([]byte, len(ciphertext))    stream := cipher.NewOFB(block, iv)    stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])    
         return plaintext2, nil
}

AES加密,CTR模式

package mainimport (    
   "io"    "crypto/cipher"    "crypto/aes"    "crypto/rand"    "fmt"

)
   func main() {    key := []byte("6368616e676520746869732070617374")    data:=[]byte("hello world")
      // 加密    result, _ := AesEncrypt(data, key)  
       // 解密    origData, _ := AesDecrypt(result, key)    fmt.Println(string(origData)) }
       
       // 加密函数
func AesEncrypt(plaintext, key []byte) ([]byte, error) {    
       
       // 申明初始化获取一个新的密钥块。关键参数应该是AES密钥,16,24或32个字节来选择AES-128,AES-192或AES-256。    block, err := aes.NewCipher(key)    if err != nil {      
       return nil, err    }  
        // 切片处理申明初始化一个较大长度的新字符串变量    ciphertext := make([]byte, aes.BlockSize+len(plaintext))    iv := ciphertext[:aes.BlockSize]  
         if _, err := io.ReadFull(rand.Reader, iv); err != nil {        
         panic(err)    }  
          // 申明初始化,同时调用加密函数得到流接口    stream := cipher.NewCTR(block, iv)    
          // 流处理    stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)    
          return ciphertext, nil

}
          // 解密函数func AesDecrypt(ciphertext, key []byte) ([]byte, error) {    block, err := aes.NewCipher(key)    
          if err != nil {      
           return nil, err    }    
           // The IV needs to be unique, but not secure. Therefore it's common to    // include it at the beginning of the ciphertext.    iv := ciphertext[:aes.BlockSize]    
           if len(ciphertext) < aes.BlockSize {        
           panic("ciphertext too short")    }    plaintext2 := make([]byte, len(ciphertext))  
            // 申明初始化,同时调用加密函数得到流接口    stream := cipher.NewCTR(block, iv)    stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:])
   return plaintext2, nil

}



以上是关于江湖“密”事——对称加密的主要内容,如果未能解决你的问题,请参考以下文章

加密算法

003 国密算法【技术】

互联网安全加密

非对称加密和ssh免密登陆验证邮件发送接收网站CA证书验证

深入浅出非对称加密

加密解密