100行代码手把手带你实现Feisitel加密算法

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: Feistel 加密算法,或者叫做 Feistel 网络,是一种块加密(block cipher)模型,很多常见的加密算法都具有 Feistel 结构,如 DES、blowfish 等。Feistel 将明文分割成固定大小(block size)的块(如 32bit、64bit),然后对于每个块进行若干轮操作,每轮操作需要用到一个 key,因此总计需要循环轮数个 key。解密时需要用相同的 keys,因此这是一种对称加密算法。

简介

Feistel 加密算法,或者叫做 Feistel 网络,是一种块加密(block cipher)模型,很多常见的加密算法都具有 Feistel 结构,如 DES、blowfish 等。


Feistel 将明文分割成固定大小(block size)的块(如 32bit、64bit),然后对于每个块进行若干轮操作,每轮操作需要用到一个 key,因此总计需要循环轮数个 key。解密时需要用相同的 keys,因此这是一种对称加密算法。

加密步骤

  1. 将明文转换为 8-bit 二进制形式
  2. 根据块大小(block size)分割成若干个数据块,不足整数块时需要加 padding
  3. 生成轮数(rounds)个 key 的 keys 数组
  4. 对于每个数据块进行若干轮操作,具体如下:
  • 在每轮操作中都将数据块分成相等的左右两部分(L1, R1)
  • 将右半部分(R1)与keys[n]进行加密函数f运算,记为f1
  • 然后将f1与左半部分进行异或(XOR)操作的结果作为下一轮输入的左半部分(L2)
  • 将本轮左半部分(L1)作为下一轮输入的右半部分(R2)
  • 下一轮的输入为L2 + R2, 再进行下一轮操作
  • 在最后一轮结束后将左半部分(Ln)和右半部分(Rn)对调(这样可以使用同一个循环进行加密和解密)

解密步骤

  1. 将密文使用相同的 keys 进行与加密过程相同的循环,不过 key 的顺序与加密时相反(加密时使用 key[1], key[2], ..., key[n], 解密时使用 key[n], key[n-1], ..., key[1])
  2. 组合数据块并按照 8bit 进行分割
  3. 根据 ASCII 码转换为明文

Python 实现

首先定义一些变量

plain_text = 'Hello world!'
# 为了便于取整,选择8bit
block_size = 8
rounds = 16
keys = []

生成随机的 keys

def rand_key(n):
  res = ''
  for i in range(n):
    bit = random.randint(0, 1)
    res += str(bit)
  return res
# length 是key的长度,可以根据需要调整
def generate_keys(length, rounds):
  for i in range (rounds):
    keys.append(rand_key(length))
  return res

定义每一轮循环的操作

def exor(a, b):
  n = len(a)
  res = ''
  for i in range(n):
    if a[i] == b[i]: res += '0'
    else: res += '1'
  return res
def round(str, key):
  n = len(str) // 2
  L1 = str[0:n]
  R1 = str[n:]
  # 这里的f函数选择exor操作
  # 可以替换为其他的加密函数
  f1 = exor(R1, key)
  R2 = exor(f1, L1)
  L2 = R1
  return L2 + R2

加密过程

def feistel_encode(s, rounds):
  res = ''
  # 将密文转为8bit二进制表示
  str_ascii = [ord(x) for x in s]
  str_bin = [format(x, '08b') for x in str_ascii]
  str_bin = ''.join(str_bin)
  # 选择block size的一半最为key length是因为将f函数定义为xor操作
  # 保证长度和block size的一半相等,在执行时就不需要补padding
  # 实际的key length会更长,一般不会少于128bit避免被快速爆破
  key_length = block_size // 2
  generate_keys(key_length, rounds)
  res_bin = ''
  for n in range(0, len(str_bin), block_size):
    temp = str_bin[n:n + block_size]
    for i in range(rounds):
      temp = round(temp, keys[i])
    # 最后一轮循环后交换左右部分
    temp = temp[key_length::] + temp[0:key_length]
    res_bin += temp
  # 将密文转为ASCII字符表示
  for i in range(0, len(res_bin), 8):
    bin_data = res_bin[i: i + 8]
    decimal = int(bin_data, 2)
    res += chr(decimal)
  return res

解密过程

def feistel_decode(s):
  res = ''
  str_ascii = [ord(x) for x in s]
  str_bin = [format(x, '08b') for x in str_ascii]
  str_bin = ''.join(str_bin)
  res_bin = ''
  for n in range(0, len(str_bin), block_size):
    temp = str_bin[n:n + block_size]
    for key in reversed(keys):  # 确保使用反向密钥
      temp = round(temp, key)
    key_length = len(keys[0])
    # 最后一轮循环后交换左右部分
    temp = temp[key_length::] + temp[0:key_length]
    res_bin += temp
  # 转为ASCII字符
  for i in range(0, len(res_bin), 8):
    bin_data = res_bin[i: i + 8]
    decimal = int(bin_data, 2)
    res += chr(decimal)
  return res

最后测试一下

def main():
  print('plain_text: ', plain_text)
  # plain_text:  Hello world!
  cipher_text = feistel_encode(plain_text, rounds)
  print('cipher_text: ', cipher_text)
  # cipher_text:  yààÓlKÓàh}
  decode_text = feistel_decode(cipher_text)
  print('decode_text: ', decode_text)
  # decode_text:  Hello world!
if __name__ == "__main__":
  main()

总结

  • 本文中为了方便演示将block size和key size设置较小,实际一般会更长,如果不满整个block则需要补padding(用0填充)
  • 加密和解密使用相同的循环,但是注意不要忘记需要在加/解密的最后一轮循环后交换左、右部分
  • 动手实现时可以将round设为1或2,单步观察每一轮循环的结果
  • 时间复杂度 O(n)
  • 额外空间 O(n)
相关文章
|
2月前
|
算法 Linux 数据安全/隐私保护
加解密随笔
加解密随笔
25 2
|
2月前
|
算法 安全 数据安全/隐私保护
实战案例2:简单的文件加密解密程序。
实战案例2:简单的文件加密解密程序。
66 0
|
3月前
|
搜索推荐 安全 网络安全
AES 加密解密技术原理模式和实践
AES (Advanced Encryption Standard), aka Rijndael, is a symmetric encryption algorithm offering high security and speed over DES.
|
3月前
|
前端开发 安全 JavaScript
学习前端加密
【7月更文挑战第3天】前端加密保护数据安全,防止传输中被截获,提升用户体验。HTTPS基础保障,JavaScript库如CryptoJS辅助加密,Web Crypto API提供原生加密功能。但前端加密非万能,需结合后端措施,注意算法选择、密钥管理。
59 2
|
4月前
|
安全 算法 Java
密码学基础知识与加密算法解析
密码学基础知识与加密算法解析
|
5月前
|
机器学习/深度学习 算法 安全
密码学系列之三:DES、AES、IDEA —— 一文搞懂分组密码
密码学系列之三:DES、AES、IDEA —— 一文搞懂分组密码
1051 0
|
编解码 前端开发 算法
前端CryptoJS和Java后端数据互相加解密(AES)
最近刚好在做一个简单的保险代理人运营平台,主要是为了方便个人展业,由于有些客户数据比较敏感,所以在用户登录时准备对登录密码进行一波加密后再传输。
前端CryptoJS和Java后端数据互相加解密(AES)
|
数据安全/隐私保护
通俗易懂的RSA加密解密指导(二)
前言 RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙。 因为加密的钥匙是公开的,所又称公钥,解密的钥匙是不公开的,所以称为私钥。 图片 密钥 关于RSA加密有很多文章,但几乎都只介绍了RSACryptoServiceProvider类的使用方法,如果只是走走看看,是没问题的,但真的想使用时,就会发现,你没有密钥字符串。。。 下面我们从获取密钥字符串开始逐步学习加密。 密钥字符串 每个安装过VisualStudio的电脑都可以找到一个文件—makecert.exe。 我电脑的makecert.exe地址:
通俗易懂的RSA加密解密指导(二)
|
存储 算法 关系型数据库
【笔记】开发指南—函数—加密和压缩函数
本文主要介绍PolarDB-X支持的加密和压缩函数。
164 0
|
数据安全/隐私保护
[re入门]一个简单的加密程序的逆向破解与解密
[re入门]一个简单的加密程序的逆向破解与解密
271 0
[re入门]一个简单的加密程序的逆向破解与解密