最近要做密码学课程设计,每做一个密码就当复习一下,把算法原理啥的都过一遍吧
简介
这个是用于GSM系统的序列密码算法,A5的特点是效率高,适合硬件上高效实现。
加密过程
- A5 / 1基于三个线性反馈移位寄存器LFSR的组合,三个寄存器的长度分别为 19 22 23位,然后产生一个114位的秘钥流。因此首先输入8个字节的秘钥去填充三个寄存器的总长也就是64位。
- 每次获取各寄存器的最后一位相互异或一下再与明文进行异或。从这一点还是可以看出关键点在于秘钥,异或了两遍原信息一致,所以加密解密都是一样的算法了。
- 然后根据寄存器的某一位决定是否需要对某个储存器进行移位,存在的数据多的决定
引用维基百科的一个图,这个图很好的揭示了加密的流程
总结要注意的加密的几个点:
产生秘钥流
- 根据8位秘钥产生的64位二进制填充寄存器
- 输出秘钥流,每一位都遵循
Z1[18]^Z2[21]^Z3[22]
这样的流程,我们需要注意的是这里讲序列密码的时候用+
表示的都是异或 - 然后就经过114轮迭代,就可以产生114位秘钥啦
寄存器反馈
遵循“服从多数”的原则,从每个寄存器里面取出一个中间位(上图标黄的位置)进行运算,取出的3个中间位里面至少有两个1,则中间位为1的就进行移位,为0的就不移位,反之至少两个为0,则为0的进行一次位移,为1的就不移位了,保证了每次至少有了两个LFSR被驱动移位了。
生成的补充值
补充值由某些抽头位进行异或运算的结果决定,运算结果为1则补充为1,否则补充0,3个LFSR里的抽头位如下图,但是补充的前提是又寄存器反馈决定的
python实现:
# -*- coding: utf-8 -*-
# Author:0verWatch
X = ''
Y = ''
Z = ''
import base64
import re
def str2bin(str_mess):
res = ""
for i in str_mess:
tmp = bin(ord(i))[2:].zfill(8)
res += tmp
return res
def bin2str(bin_mess):
res = ""
tmp = re.findall(r'.{8}',bin_mess)
for i in tmp:
res += chr(int(i,2))
return res
def LFSRinit(): #用64bit密钥初始3个移位寄存器,分别是19,22,23位
global X
global Y
global Z
key = input("请输入8位秘钥\n")
while len(key) != 8: #限定只能是8位,然后生成64位的二进制流
key = input("请输入8位秘钥\n")
key_bin_str = ""
for i in key:
tmp = bin(ord(i))[2:].zfill(8