前面几种密码都是连续的明文元素是使用相应的密钥K来加密的,即明文串使用如下方法得到 y = y 1 y 2 . . . = e k ( x 1 ) e k ( x 2 ) . . . y=y_1y_2...=e_k(x_1)e_k(x_2)... y=y1y2...=ek(x1)ek(x2)...这种类型的密码体质通常称为分组密码。还有一种广泛使用的密码体质称为流密码,其基本思想是产生一个密钥流 z = z 1 z 2 . . . z=z_1z_2... z=z1z2...然后使用它根据如下的规则来加密明文串 x = x 1 x 2 . . . x=x_1x_2... x=x1x2...:
y = y 1 y 2 . . . = e z 1 ( x 1 ) e z 2 ( x 2 ) . . . y=y_1y_2...=e_{z_1}(x_1)e_{z_2}(x_2)... y=y1y2...=ez1(x1)ez2(x2)...
最简单流密码是其密钥流直接由初始密钥使用某种特定算法变换得来,密钥流和明文串是相互独立的,这种类型的流密码称为同步流密码,正式定义如下:
同步流密码是一个六元祖(P,C,K,L,E,D)个一个函数g,并且满足如下条件:
- P是所有可能明文构成的有限集
- C是所有可能密文构成的有限集
- 密钥空间K为一有限集,由所有可能密钥构成
- L是一个称之为密钥流字母表的有限集
- ,g是一个密钥流生成器,g使用密钥K作为输入,产生无限长的密钥流 z = z 1 z 2 . . . z=z_1z_2... z=z1z2...其中 z i ∈ L z_i∈L zi∈L,i>=1
- 对任意的z∈L,都有一个加密规则 e z ∈ E e_z∈E ez∈E和相应的解密规则 d z ∈ D d_z∈D dz∈D,并且对每个明文 x ∈ P x∈P x∈P, e z : P − > C e_z:P->C ez:P−>C和 d z : C − > P d_z:C->P dz:C−>P是满足 d z ( e x ( x ) ) = x d_z(e_x(x))=x dz(ex(x))=x的函数
如果对于所有的i>=1的整数有 z i + d = z i z_{i+d}=z_i zi+d=zi则称该密码是具有周期d的周期流密码。
设m=4,密钥流按如下线性递归关系产生:
z i + 4 = ( z i + z i + 1 ) m o d 2 z_{i+4}=(z_i+z_{i+1})mod2 zi+4=(zi+zi+1)mod2 i>=1
如果密钥流的初始向量不为0,则我们将获得周期为 z 4 − 1 = 15 z^4-1=15 z4−1=15的密钥流,例如,若初始向量为(1,0,0,0),则可能产生密钥流如下:
1 0 0 0 1 0 0 1 1 0 1 0 1 1 1任何一个非零的初始向量都将产生具有相同周期的密钥流序列。
密钥流 z i z_i zi的产生不但与密钥K有关,而且还与明文元素 ( x 1 , x 2 . . . x i − 1 ) (x_1,x_2...x_{i-1}) (x1,x2...xi−1)和 ( y 1 , y 2 . . . y i − 1 ) (y_1,y_2...y_{i-1}) (y1,y2...yi−1)有关,这种类型的流密码称为异步流密码
设 P = V = K = L = Z 2 6 , z 1 = K P=V=K=L=Z_26,z_1=K P=V=K=L=Z26,z1=K定义 z i = x i − 1 z_i=x_{i-1} zi=xi−1,i>=2;对任意的 0 < = z < = 25 0<=z<=25 0<=z<=25, x , y ∈ Z — — 26 x,y∈Z——26 x,y∈Z——26,定义 e z ( x ) = ( x + z ) m o d 26 e_z(x)=(x+z)mod26 ez(x)=(x+z)mod26和 d z ( y ) = ( y − z ) m o d 26 d_z(y)=(y-z)mod26 dz(y)=(y−z)mod26
假设K=8,明文为rendezvous首先将明文转换为整数序列得到
17 4 13 3 4 25 21 14 20 18
相应的密钥流是
8 17 4 13 3 4 25 21 14 20
得到密文为:
ZVRQHDUJIM
package com.slp.cryptography;
import java.util.Arrays;
/**
* @ClassName AutoCrypt
* @Description 自动密钥流
* @Author sanglp
* @Date 2020/12/1 8:51
* @Version 1.0
**/
public class AutoCrypt {
static int[] key ;
/**
* 加密函数
* @param res
* @param z1
*/
private static void encrypt(String res,int z1){
int len = res.length();
key = new int[len];
char resarr[]= res.toUpperCase().toCharArray();
StringBuilder result = new StringBuilder();
int temp = (resarr[0]-'A'+z1)%26<0?(resarr[0]-'A'+z1)%26+26:(resarr[0]-'A'+z1)%26;
key[0]=z1;
result.append((char)(temp+'A'));
for(int i=1;i<len;i++){
temp = (resarr[i]-'A'+resarr[i-1]-'A')%26<0?((resarr[i]-'A'+resarr[i-1]-'A')%26+26):(resarr[i]-'A'+resarr[i-1]-'A')%26;
key[i]=resarr[i-1]-'A';
result.append((char)(temp+'A'));
}
System.out.println(result);
System.out.println(Arrays.toString(key));
}
/**
* 解密函数
* @param res
*/
private static void decrypt(String res){
int len = res.length();
//key = new int[len];
char resarr[]= res.toUpperCase().toCharArray();
StringBuilder result = new StringBuilder();
int temp = (resarr[0]-'A'-key[0])%26<0?(resarr[0]-'A'-key[0])%26+26:(resarr[0]-'A'-key[0])%26;
result.append((char)(temp+'A'));
for(int i=1;i<len;i++){
temp = (resarr[i]-'A'-key[i])%26<0?((resarr[i]-'A'-key[i])%26+26):(resarr[i]-'A'-key[i])%26;
result.append((char)(temp+'A'));
}
System.out.println(result);
}
public static void main(String[] args) {
encrypt("rendezvous",8);
decrypt("ZVRQHDUJIM");
}
}