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)
相关文章
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂XTEA加密
本篇文章,我们来看一下上一次讲过的TEA加密算法的一个升级版XTEA, 相比于TEA, XTEA的安全性显然是更高的,其中的过程要比TEA稍微复杂一点点。
1270 0
【密码学】一文读懂XTEA加密
|
Rust 算法 安全
【密码学】一文读懂HMAC
本文将来聊一聊基于哈希函数的消息认证码,在此之前,先来科普一下什么是 「消息认证码」 (MAC), 先来看一个简单的栗子
1676 0
【密码学】一文读懂HMAC
|
4月前
|
前端开发 安全 JavaScript
学习前端加密
【7月更文挑战第3天】前端加密保护数据安全,防止传输中被截获,提升用户体验。HTTPS基础保障,JavaScript库如CryptoJS辅助加密,Web Crypto API提供原生加密功能。但前端加密非万能,需结合后端措施,注意算法选择、密钥管理。
68 2
|
4月前
|
安全 算法 Java
密码学基础知识与加密算法解析
密码学基础知识与加密算法解析
|
6月前
|
机器学习/深度学习 算法 安全
密码学系列之三:DES、AES、IDEA —— 一文搞懂分组密码
密码学系列之三:DES、AES、IDEA —— 一文搞懂分组密码
1376 0
|
6月前
|
算法 安全 网络安全
一文搞懂常见的加密算法
一文搞懂常见的加密算法
819 0
|
编解码 前端开发 算法
前端CryptoJS和Java后端数据互相加解密(AES)
最近刚好在做一个简单的保险代理人运营平台,主要是为了方便个人展业,由于有些客户数据比较敏感,所以在用户登录时准备对登录密码进行一波加密后再传输。
前端CryptoJS和Java后端数据互相加解密(AES)
|
数据安全/隐私保护
通俗易懂的RSA加密解密指导(二)
前言 RSA加密算法是一种非对称加密算法,简单来说,就是加密时使用一个钥匙,解密时使用另一个钥匙。 因为加密的钥匙是公开的,所又称公钥,解密的钥匙是不公开的,所以称为私钥。 图片 密钥 关于RSA加密有很多文章,但几乎都只介绍了RSACryptoServiceProvider类的使用方法,如果只是走走看看,是没问题的,但真的想使用时,就会发现,你没有密钥字符串。。。 下面我们从获取密钥字符串开始逐步学习加密。 密钥字符串 每个安装过VisualStudio的电脑都可以找到一个文件—makecert.exe。 我电脑的makecert.exe地址:
通俗易懂的RSA加密解密指导(二)
|
算法 安全 数据安全/隐私保护
【密码学】一文读懂MD4
MD4是麻省理工学院教授Ronald Rivest于1990年设计的一种信息摘要算法。它是一种用来测试信息完整性的密码散列函数的实行。其摘要长度为128位。这个算法影响了后来的算法如MD5、SHA家族和RIPEMD等。
1448 0
【密码学】一文读懂MD4
|
算法 安全
【密码学】一文读懂MD2
MD2是Ranald Rivest在1989年提出的哈希函数,本文主要介绍一下MD2算法的基本原理,尽管现在MD2已经并不安全,作为一个结构比较简单的哈希函数,学习一下还是十分有必要的。
1455 0
【密码学】一文读懂MD2