加密算法之AES
2018-12-19 本文已影响5人
Carrism
AES
算法原理
AES采用分组密码体制,首先将明文分成以16个字节长度为基准字节段,如果最后不足16字节则同样使用填充。然后分组对每段字节段进行加密得到密文,再将最后得到的密文拼接在一起形成最终的密文。AES算法的密钥长度可以分为128位,256位,512位。
加密过程
-
字节替换变换
任何字节都对应着AES的S盒,S盒是一个映射表,在这个映射表中,任何元素都能够有相应的元素与之对应,并且映射过程是可逆的。
AES S盒.png
-
行移位变换
AES算法的明文分组要求是每组的字节长度为16,就是因为能够刚好转换成4x4矩阵。然后第一行保持不变,第二行循环左移1个字节,第三行循环左移2个字节,第四行循环左移3个字节
AES行移位变换.png
-
列混淆
列混淆变换将状态矩阵中的每一列视为系数在GF(2^8 )上的次数小于4的多项式与同一个固定的多项式a(x)进行模多项式m(x)=x^4 +1的乘法运算。在AES中,a(x)={03}x^3 +{01}x^2 +{01}x+{02}
-
轮加密
任何数和自身异或结果为0,所以在加密中明文与密钥异或之后,在解密重新与该密钥进行异或能够得到原来的输入
整个加密过程如下图所示:
实现过程
功能实现,在客户端中将明文进行AES加密后通过TCP链接发送至另一个客户端,另一端通过密钥对密文进行解密得到明文
- 客户端
- AES加密
//补码
func PKCS5Padding(orgData []byte,blockSize int) []byte {
padding := blockSize - len(orgData)%blockSize
paddingBytes := bytes.Repeat([]byte{byte(padding)},padding)
orgData = append(orgData,paddingBytes...)
return orgData
}
//AES加密
func AESEncrypt(org []byte,key []byte) []byte {
block,_ := aes.NewCipher(key)
//明文补码
org = PKCS5Padding(org,block.BlockSize())
//设置加密方式
blockMode := cipher.NewCBCEncrypter(block,key)
// 创建缓冲区
cypted := make([]byte,len(org))
//加密
blockMode.CryptBlocks(cypted,org)
return cypted
}
- 启动TCP链接并将数据发送出去
func main() {
//密钥
key := "1234567890123456"
//AES加密
data := AESEncrypt([]byte("hello World"),[]byte(key))
//建立TCP链接
tcp,_ := net.ResolveTCPAddr("tcp","127.0.0.1:1234")
tcpConn,_ := net.DialTCP("tcp",nil,tcp)
//发送数据
tcpConn.Write(data)
}
-
服务器
- AES解密
//AES解密
func AESDecrypt(cipherTxt []byte,key []byte) []byte {
block,_ := aes.NewCipher(key)
//设置解密模式
blockMode := cipher.NewCBCDecrypter(block,key)
//创建缓冲区
org := make([]byte,len(cipherTxt))
blockMode.CryptBlocks(org,cipherTxt)
//去码
return PKCS5UnPadding(org)
}
//去码
func PKCS5UnPadding(desData []byte) []byte {
length := len(desData)
padding := desData[length - 1]
sourceData := desData[:length - int(padding)]
return sourceData
}
- main函数当中对特定端口进行监听,当收到数据的时候才用特定的密钥进行解密
func main() {
listener,_ := net.Listen("tcp","127.0.0.1:1234")
defer listener.Close()
for {
//只有客户端连接成功才会向下执行
conn,_:=listener.Accept()
//创建缓存,存放客户端发送的数据
data:=make([]byte,1024)
for {
//接收客户端发送的数据,n数据的大小
n,_:=conn.Read(data)
//data[:n]就是接受到的密文
fmt.Println("密文为:",data[:n])
fmt.Println("名文为:",string(AESDecrypt(data[:n],[]byte("1234567890123456"))))
break
}
}
}