乐趣区

关于密码学:密码技术对称加密算法及Go语言应用

对称加密算法

DES

Data Encryption Standard(数据加密规范)是 1977 年美国联邦信息处理规范(FIPS)中所采纳的一种对称明码。DES 始终以来被美国以及其余国家的政府和银行等广泛应用,然而,随着计算机的提高,当初 DES 曾经可能本暴力破解,强度大不如以前了。

RSA 公司举办过破译 DES 密钥的较量(DESChallenge),较量的后果为:

  • 1977 年较量中用了 96 天破解
  • 1998 年第一次较量用了 41 天破解
  • 1998 年第二次较量用了 56 小时
  • 1999 年第三次较量中只用了 22 小时 15 分钟就被破解了

因为 DES 的密文能够在短时间内被破解,因而除了它来解密以前的密文外,当初咱们不应该应用该算法了,不平安。

DES 的加密解密

DES 时一种将 64 比特的明文加密成 64 比特的密文的对称明码算法,它的密钥长度是 56 比特,只管从规格上来说,DES 的密钥长度是 64 比特,但因为每隔 7 比特会设置一个用于谬误查看的比特,因而本质上其密钥长度是 56 比特。

总结:

  • 当初应用 DES 形式加密,数据还平安吗?

    • 不平安,曾经被破解
  • 是不是分组明码?

    • 是,先对数据进行分组,而后再加密或解密
  • DES 的分组长度?

    • 8byte==64bit
  • DES 的秘钥长度?

    • 56bit 秘钥长度 +8bit 谬误查看标记位 =64bit==8byte

3DES

Triple-DES,三重 DES– 应用 DES 三次加密

总结:

  • 3DES 平安吗?

    • 平安,然而效率低
  • 算法形容?

    • 进行了三次 DES 加密
  • 是不是分组算法?

  • 3DES 分组长度?

    • 8byte
  • 3DES 秘钥长度?

    • 24byte,在算法外部会被均匀分成 3 份,目标是兼容 DES
  • 3DES 加密过程?

    • 秘钥 1 -> 加密 ->,秘钥 2 -> 解密,秘钥 3 -> 加密
  • 3DES 解密过程?

    • 秘钥 1 -> 解密 ->,秘钥 2 -> 加密,秘钥 3 -> 解密

DES-CBC 模式加解密 Go 实现

package main

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

// 明文数据填充
func paddingLastGroup(plainText []byte, blockSize int) []byte {
    //1. 计算最初一个分组中明文后须要填充的字节数
    padNum := blockSize - len(plainText)%blockSize
    //2. 将字节数转换为 byte 类型
    char := []byte{byte(padNum)}
    //3. 创立切片并初始化
    newPlain := bytes.Repeat(char, padNum)
    //4. 将填充数据追加到原始数据后
    newText := append(plainText, newPlain...)

    return newText
}

// 去掉明文前面的填充数据
func unpaddingLastGroup(plainText []byte) []byte {
    //1. 拿到切片中的最初一个字节
    length := len(plainText)
    lastChar := plainText[length-1]
    //2. 将最初一个数据转换为整数
    number := int(lastChar)
    return plainText[:length-number]
}

//des 加密
func desEncrypt(plainText, key []byte) []byte {
    //1. 建设一个底层应用的 des 明码接口
    block, err := des.NewCipher(key)
    if err != nil {panic(err)
    }
    //2. 填充明文数据 (这里必须填充,不论原始明文是否能被块长度整除)
    groupData := paddingLastGroup(plainText, block.BlockSize())
    //3. 抉择加密模式
    iv := []byte("12345678")
    blockMode := cipher.NewCBCEncrypter(block, iv)
    //4. 加密
    cipherText := make([]byte, len(groupData))
    blockMode.CryptBlocks(cipherText, groupData)
    //blockMode.CryptBlocks(groupData, groupData) // 这样也能够,官网文档中阐明传入传出参数可指向同一地址
    return cipherText
}

//des 解密
func desDecrypt(cipherText, key []byte) []byte {
    //1. 创立一个 des 底层明码接口
    block, err := des.NewCipher(key)
    if err != nil {panic(err)
    }
    //2. 抉择解密模式
    iv := []byte("12345678") // 初始化向量必须和加密时的一样
    blockMode := cipher.NewCBCDecrypter(block, iv)
    //3. 解密
    padText := make([]byte, len(cipherText))
    blockMode.CryptBlocks(padText, cipherText)
    //4. 去填充数据
    plainText := unpaddingLastGroup(padText)
    return plainText
}

func main(){fmt.Println("des 加解密")
    key := []byte("1q2w3e4r")
    src := []byte("DES  --Data Encryption Standard(数据加密规范)是 1977 年美国联邦信息处理规范(FIPS)中所采纳的一种对称明码。DES 始终以来被美国以及其余国家的政府和银行等广泛应用,然而,随着计算机的提高,当初 DES 曾经可能本暴力破解,强度大不如以前了。因为 DES 的密文能够在短时间内被破解,因而除了它来解密以前的密文外,当初咱们不应该应用该算法了,不平安。")
    cipherText := desEncrypt(src, key)
    plainText := desDecrypt(cipherText, key)
    fmt.Println("解密后的数据为:", string(plainText))
}

AES

Advanced Encryption Standard(高级加密规范),AES 是取代 DES 的一种对称明码算法,底层算法为 Rijndael,该底层算法是有比利时明码学家设计的分组明码算法。

Rijndael 的分组长度为 128 比特,密钥长度能够以 32 比特为单位在 128 比特到 256 比特的范畴内进行抉择,在 AES 的规格中,密钥长度只有 128、192、256 比特三种

128bit = 16 字节

192bit = 24 字节

256bit = 32 字节

在 go 提供的接口中只反对 16 字节长度的密钥长度

总结:

  • AES 平安吗?

    • 平安,效率高,举荐应用
  • 是不是分组明码?

  • AES 分组长度?

    • 128bit = 16 字节
  • AES 密钥长度?

    • 128bit = 16 字节
    • 192bit = 24 字节
    • 256bit = 32 字节
    • 在 go 提供的接口中只反对 16 字节

AES-CTR 模式加解密 Go 实现

package main

import (
    "crypto/aes"
    "crypto/cipher"
)

//aes 加密
func aesEncrypt(plainText, key []byte) []byte {
    //1. 建设一个底层应用的 aes 明码接口
    block, err := aes.NewCipher(key)
    if err != nil {panic(err)
    }
    //2.ctr 模式不须要数据填充
    //3. 抉择加密模式
    iv := []byte("12345678qwertyui")  // 不须要初始化向量,go 接口中的 iv 能够了解为随机数种子,iv 的长度等于明文分组长度,并不是真正的初始化向量
    stream := cipher.NewCTR(block, iv)
    //4. 加密
    stream.XORKeyStream(plainText, plainText)
    return plainText
}

//aes 解密
func aesDecrypt(cipherText, key []byte) []byte {
    //1. 创立一个 aes 底层明码接口
    block, err := aes.NewCipher(key)
    if err != nil {panic(err)
    }
    //2. 抉择解密模式
    iv := []byte("12345678qwertyui") // 随机数种子, 长度为 16 位
    stream := cipher.NewCTR(block, iv)
    //3. 解密
    padText := make([]byte, len(cipherText))
    stream.XORKeyStream(padText, cipherText)
    return padText
}

func main(){fmt.Println("aes 加解密")
    key := []byte("1q2w3e4r")
    src := []byte("AES  --Advanced Encryption Standard( 高级加密规范)\nAES 是取代 DES 的一种对称明码算法,底层算法为 Rijndael,该底层算法是有比利时明码学家设计的分组明码算法。\nRijndael 的分组长度为 128 比特,密钥长度能够以 32 比特为单位在 128 比特到 256 比特的范畴内进行抉择,在 AES 的规格中,密钥长度只有 128、192、256 比特三种, 在 go 提供的接口中只反对 16 字节长度的密钥长度,加密和解密的函数接口是一个,起因是异或一次就是加密,异或两次就是解密,因而没必要实现为两个接口")
    cipherText := desEncrypt(src, key)
    plainText := desDecrypt(cipherText, key)
    fmt.Println("解密后的数据为:", string(plainText))
}
退出移动版