密码技术###
1. 介绍
1.1 加密/解密三要素: 明文/ 密文, 秘钥, 密码算法
-
明文/密文:
加密之前的消息称为明文(plaintext),加密之后的消息称为密文(cipher-text)。 -
秘钥 :
密码算法中需要密钥(key)。现实世界中的“钥'',是像 :key: 这样的形状微妙而复杂的小金属片。然而,密码算法中的密钥,则是像203554728568477650354673080689430768这样的一串非常大的数字。
-
密码算法 :
用于解决复杂问题的步骤,通常称为算法(algorithm)。从明文生成密文的步骤,也就是加密的步骤,称为“加密算法",而解密的步骤则称为“解密算法"。加密、解密的算法合在一起统称为密码算法。
1.2密码信息威胁
我们将信息安全所面临的威胁与用来用对这些威胁的密码技术直接的关系用一张图标来表示出来。
2. 对称加密
对称加密: 也称为对称密码, 是指在加密和解码时使用同一秘钥的加密方式
2.1 DES:
DES(Data Encryption Standard)是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46.3)。DES一直以来被美国以及其他国家的政府和银行等广泛使用。然而,随着计算机的进步,现在DES已经能够被暴力破解,强度大不如前了(不建议使用)
-
DES加密解密
DES是一种将64比特的明文加密成64比特的密文的对称密码算法,==它的密钥长度是56比特==。尽管从规格上来说,DES的密钥长度是64比特,但由于每隔7比特会设置一个用于错误检查的比特,因此实质上其密钥长度是56比特。
DES是以64比特的明文(比特序列)为一个单位来进行加密的,这个64比特的单位称为分组。一般来说,以分组为单位进行处理的密码算法称为分组密码(blockcipher),DES就是分组密码的一种。
DES每次只能加密64比特的数据,如果要加密的明文比较长,就需要对DES加密进行迭代(反复),而迭代的具体方式就称为模式(mode)。
秘钥长度(56bit + 8bit)/8 = 8byte
-
三重DES加密
现在DES已经可以在现实的时间内被暴力破解,三重DES(triple-DES)是为了增加DES的强度,==将DES重复3次所得到的一种密码算法==,通常缩写为3DES
明文经过三次DES处理才能变成最后的密文,由于DES密钥的长度实质上是56比特,因此三重DES的密钥长度就是56×3=168比特, 加上用于错误检测的标志位8x3, 共192bit。
从上图我们可以发现,三重DES并不是进行三次DES加密(加密-->加密-->加密),而是加密-->解密-->加密的过程。在加密算法中加人解密操作让人感觉很不可思议,实际上这个方法是IBM公司设计出来的,目的是为了让三重DES能够兼容普通的DES。
当三重DES中所有的密钥都相同时,三重DES也就等同于普通的DES了。这是因为在前两步加密-->解密之后,得到的就是最初的明文。因此,以前用DES加密的密文,就可以通过这种方式用三重DES来进行解密。也就是说,三重DES对DES具备向下兼容性。
如果密钥1和密钥3使用相同的密钥,而密钥2使用不同的密钥(也就是只使用两个DES密钥),这种三重DES就称为DES-EDE2。EDE表示的是加密(Encryption) -->解密(Decryption)-->加密(Encryption)这个流程。
密钥1、密钥2、密钥3全部使用不同的比特序列的三重DES称为DES-EDE3。
尽管三重DES目前还被银行等机构使用,但其处理速度不高,而且在安全性方面也逐渐显现出了一些问题
2. Go实现对称加密
2.1 DES 实现:
-
CBC 分组模式:
加密:
- 创建并返回一个使用DES算法的cipher.Block接口 秘钥长度为64bit, 即 64/8 = 8字节(byte)
- 对最后一个明文分组进行数据填充
DES是以64比特的明文(比特序列)为一个单位来进行加密的
最后一组不够64bit, 则需要进行数据填充( 参考第三章)- 创建一个密码分组为链接模式的, 底层使用DES加密的BlockMode接口
- 加密连续的数据块
解密:
- 创建并返回一个使用DES算法的cipher.Block接口
- 创建一个密码分组为链接模式的, 底层使用DES解密的BlockMode接口
- 数据块解密
- 去掉最后一组的填充数据
代码实现:
1.明文/密文分组填充与移除
// 分组填充--填充对应长度的相同数字(1, 22, 333....)
//data: 待分组数据, blockSize: 每组的长度
func PKCS7Padding(date []byte, blockSize int)(PaddingResult[]byte){
// 获取数据长度
length:=len(date)
// 获取待填充数据长度
count:=length%blockSize
PaddingCount:=blockSize-count
// 在数据后填充数据
PaddingDate:=bytes.Repeat([]byte{byte(PaddingCount)},PaddingCount)
PaddingResult=append(date,PaddingDate...)
return
}
// 分组移除
func PKCS7Unpadding(date []byte, blockSize int)(UnpaddingResult[]byte){
length:=len(date)
temp:=int(date[length-1])
UnpaddingResult=date[:length-temp]
return
}
- DES加密与解密:
//src: --明文/密文,需要分组填充,每组8byte
//key: --秘钥 8byte
//iv: --初始化向量 8byte 长度必须与key相同
--------------------------------------------------------------
//加密
func Des_CBC_Encrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用DES算法的cipher.Block接口
block, err := des.NewCipher(key)
// 判断是否创建成功
if err != nil {
panic(err)
}
// 明文组数据填充
paddingText := PKCS7Padding_Unpadding.PKCS7Padding(src, block.BlockSize())
// 创建一个密码分组为链接模式的, 底层使用DES加密的BlockMode接口
blockMode := cipher.NewCBCEncrypter(block, iv)
// 加密
dst := make([]byte, len(paddingText))
blockMode.CryptBlocks(dst, paddingText)
return dst
}
---------------------------------------------------------
// 解密:
func Des_CBC_Decrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用DES算法的cipher.Block接口
block, err := des.NewCipher(key)
if err != nil {
panic(err)
}
// 创建一个密码分组为链接模式的, 底层使用DES解密的BlockMode接口
blockMode := cipher.NewCBCDecrypter(block, iv)
// 解密
dst := make([]byte, len(src))
blockMode.CryptBlocks(dst, src)
// 分组移除
dst = PKCS7Padding_Unpadding.PKCS7Unpadding(dst, block.BlockSize())
return dst
}
-
CTR 分组模式:
加密:
- 创建并返回一个使用DES算法的cipher.Block接口 秘钥长度为64bit, 即 64/8 = 8字节(byte)
- 创建一个CTR密码分组为链接模式的, 底层使用DES加密的BlockMode接口
- 加密连续的数据块
解密:
与加密算法完全一致
代码实现:
/*
DES CTR 加密解密函数
参数:
src: --明文/密文 分组不需要填充
key: --秘钥 8byte
iv: --初始化向量 8byte 长度必须与key相同
*/
//加密
func Des_CTR_Encrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用DES算法的cipher.Block接口
block, err := des.NewCipher(key)
// 判断是否创建成功
if err != nil {
panic(err)
}
// 创建一个密码分组为链接模式的, 底层使用DES加密的stream接口
stream := cipher.NewCTR(block,iv)
// 加密
dst := make([]byte, len(src))
stream.XORKeyStream(dst,src)
return dst
}
// 解密 直接调用加密函数
func Des_CTR_Decrypt(src []byte, key []byte, iv []byte) []byte {
return Des_CTR_Encrypt(src,key,iv)
}
2.2 3DES 实现:
与DES 基本一致, 唯一不同点:
key 长度:3*8=24byte
代码实现:
/*
3DES CBC 加密解密函数
Des3_CBC_Encrypt() --加密
Des3_CBC_Decrypt() --解密
参数:
src: --明文/密文,需要分组填充,每组8byte
key: --秘钥 3*8=24byte
iv: --初始化向量 8byte
*/
func Des3_CBC_Encrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用3DES算法的cipher.Block接口
block, err := des.NewTripleDESCipher(key)
// 判断是否创建成功
if err != nil {
panic(err)
}
// 明文组数据填充
paddingText := PKCS7Padding_Unpadding.PKCS7Padding(src, block.BlockSize())
// 创建一个密码分组为链接模式的, 底层使用DES加密的BlockMode接口
blockMode := cipher.NewCBCEncrypter(block, iv)
// 加密
dst := make([]byte, len(paddingText))
blockMode.CryptBlocks(dst, paddingText)
return dst
}
func Des3_CBC_Decrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用3DES算法的cipher.Block接口
block, err := des.NewTripleDESCipher(key)
if err != nil {
panic(err)
}
// 创建一个密码分组为链接模式的, 底层使用3DES解密的BlockMode接口
blockMode := cipher.NewCBCDecrypter(block, iv)
// 解密
dst := make([]byte, len(src))
blockMode.CryptBlocks(dst, src)
// 分组移除
dst = PKCS7Padding_Unpadding.PKCS7Unpadding(dst, block.BlockSize())
return dst
}
--------------------------------------------------------------
/*
3DES CTR 加密解密函数
Des3_CTR_Encrypt() --加密
Des3_CTR_Decrypt() --解密
参数:
src: --明文/密文 分组不需要填充
key: --秘钥 3*8=24byte
iv: --初始化向量 8byte
*/
func Des3_CTR_Encrypt(src []byte, key []byte, iv []byte) []byte {
// 创建并返回一个使用3DES算法的cipher.Block接口
block, err := des.NewTripleDESCipher(key)
// 判断是否创建成功
if err != nil {
panic(err)
}
// 创建一个密码分组为链接模式的, 底层使用DES加密的stream接口
stream := cipher.NewCTR(block,iv)
// 加密
dst := make([]byte, len(src))
stream.XORKeyStream(dst,src)
return dst
}
func Des3_CTR_Decrypt(src []byte, key []byte, iv []byte) []byte {
return Des3_CTR_Encrypt(src,key,iv)
}