维吉尼亚密码是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。

其相当于对明文不同偏移的字符进行不同的凯撒加密

实现

生成字母表

1
2
3
4
5
6
7
8
9
10
11
12
13
char x[] = "abcdefghijklmnopqrstuvwxyz";
char box[26][26];
int Xlength = 26;
void generateBox()
{
for (int i = 0; i < 26; i++)
{
for (int j = 0; j < 26; j++)
{
box[i][j] = x[(j+i)%Xlength];
}
}
}

这样便生成了这样的字母表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
a b c d e f g h i j k l m n o p q r s t u v w x y z
b c d e f g h i j k l m n o p q r s t u v w x y z a
c d e f g h i j k l m n o p q r s t u v w x y z a b
d e f g h i j k l m n o p q r s t u v w x y z a b c
e f g h i j k l m n o p q r s t u v w x y z a b c d
f g h i j k l m n o p q r s t u v w x y z a b c d e
g h i j k l m n o p q r s t u v w x y z a b c d e f
h i j k l m n o p q r s t u v w x y z a b c d e f g
i j k l m n o p q r s t u v w x y z a b c d e f g h
j k l m n o p q r s t u v w x y z a b c d e f g h i
k l m n o p q r s t u v w x y z a b c d e f g h i j
l m n o p q r s t u v w x y z a b c d e f g h i j k
m n o p q r s t u v w x y z a b c d e f g h i j k l
n o p q r s t u v w x y z a b c d e f g h i j k l m
o p q r s t u v w x y z a b c d e f g h i j k l m n
p q r s t u v w x y z a b c d e f g h i j k l m n o
q r s t u v w x y z a b c d e f g h i j k l m n o p
r s t u v w x y z a b c d e f g h i j k l m n o p q
s t u v w x y z a b c d e f g h i j k l m n o p q r
t u v w x y z a b c d e f g h i j k l m n o p q r s
u v w x y z a b c d e f g h i j k l m n o p q r s t
v w x y z a b c d e f g h i j k l m n o p q r s t u
w x y z a b c d e f g h i j k l m n o p q r s t u v
x y z a b c d e f g h i j k l m n o p q r s t u v w
y z a b c d e f g h i j k l m n o p q r s t u v w x
z a b c d e f g h i j k l m n o p q r s t u v w x y

加密

加密的时候以key在子母集中的位置为行号,以明文在子母集中的位置为列号,此行号列号所定位的字母就是加密的对应字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
inp: 密文字符串
x: 要查询的字符
*/
int indexOf(char *inp, char x)
{
char tmp = inp[0];
int offset = x >= tmp ? x - tmp : x - tmp + 26;
if (inp[offset] != x)
offset -= 6;
return offset;
}

/*
buf: 明文字符串
key: key字符串
*/
void Vencrypt(char* buf, char* key)
{
int Clength = strlen(buf);
int Klength = strlen(key);
for (int i = 0, j = 0; i < Clength; i++)
{
char c = buf[i];
if (c == ' ')
continue;
char k = key[j++];
if (j == Klength)
j = 0;
int Cidx = indexOf(x, c);
int Kidx = indexOf(x, k);
char b = box[Kidx][Cidx];
buf[i] = b;
}
}

解密

解密也很简单,依旧根据key的位置定位行号,然后再根据密文的位置定位到列号,该列号在子母集中对应的字母就是明文的字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
inp: 密文字符串
x: 要查询的字符
*/
int invertIndexOf(char *inp, char x)
{
return indexOf(inp, x);
}

/*
buf: 密文字符串
key: key字符串
*/
void Vdecrypt(char* buf, char* key)
{
int Clength = strlen(buf);
int Klength = strlen(key);
for (int i = 0, j = 0; i < Clength; i++)
{
char c = buf[i];
if (c == ' ')
continue;
char k = key[j++];
if (j == Klength)
j = 0;
int Kidx = indexOf(x, k);
char b = x[invertIndexOf(box[Kidx], c)];
/*
for (int j = 0; j < Xlength; j++)
{
if (box[Kidx][j] == c)
b = x[j];
}
*/
buf[i] = b;
}
}

破解

有时候我们会遇到给了一串密文,但是没有给key的情况,这种情况下如果要暴力猜解将会是非常困难的,因此我们用统计学的方法来解决这个问题

弗里德曼试验由威廉·F·弗里德曼(William F. Friedman)于1920年代发明。他使用了重合指数(index of coincidence)来描述密文字母频率的不匀性,从而破译密码。

kappa _{p}](https://wikimedia.org/api/rest_v1/media/math/render/svg/dca34d1a0228682daff98ed2767294435e07cb4c)指目标语言中两个任意字母相同的概率(英文中为0.067),![kappa _{r}

kappa _{p}](https://wikimedia.org/api/rest_v1/media/math/render/svg/dca34d1a0228682daff98ed2767294435e07cb4c)指目标语言中两个任意字母相同的概率(英文中为0.067),![kappa _{r}

指字母表中这种情况出现的概率(英文中为1/26=0.0385),从而密钥长度可以估计为:

其中,观察概率为

其中,c是指字母表的长度(英文为26),N指文本的长度,n1到nc是指密文的字母频率,为整数。

此方法只是一种估计,会随着文本长度的增加而更为精确。在实践中,会尝试接近此估计的多个密钥长度。 一种更好的方法是将密文写成矩阵形式,其中列数与假定的密钥长度一致,将每一列的重合指数单独计算,并求得平均重合指数。对于所有可能的密钥长度,平均重合指数最高的最有可能是真正的密钥长度。这样的试验可以作为卡西斯基试验的补充。

根据第二个公式来实现重合指数的计算

重合指数确定key长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
这个数组用来存储密文字符出现的次数
*/
int N[26];

/*
得到密文不带空格的版本
inp: 密文字符串
buf: 存放不带空格版本的密文的buffer
*/
void getNoAlpha(char *inp, char *buf)
{
int i = 0;
int j = 0;
do
{
if (inp[i] == ' ')
continue;
buf[j++] = inp[i];
} while (inp[i++] != '\x00');
}

/*
维吉尼亚是根据key中字符在子母集中的位置来选择对应的表进行凯撒加密的
所以我们需要将使用相同key的字符所加密,即使用相同的密码表进行凯撒加密的密文字符当作一串密文
然后计算这串密文的重合指数,所以for循环要这样写
inp: 密文字符串
l: 开始偏移
n: key的长度
return: 字符串长度
*/
int calcN(char *inp, int l, int n)
{
for (int i = 0; i < Xlength; i++)
{
N[i] = 0;
}
int Ilength = strlen(inp);
char *buff = (char*)malloc(Ilength);
getNoAlpha(inp, buff);
Ilength = strlen(buff);
int len = 0;
for (int i = l; i < Ilength; i+=n, len++)
{
N[indexOf(x, buff[i])]++;
}
free(buff);
return len;
}

/*
这就是计算重合指数的关键函数,返回值越接近0.067,就代表
inp: 密文字符串
l: key长度
return: 重合指数
*/
double IC(char *inp, int l)
{
double ICNUM = 0.0;
for (int i = 0; i < l; i++)
{
int len = calcN(inp, i, l);
double sum = 0.0;
for (int j = 0; j < Xlength; j++)
{
sum = sum + N[j] * (N[j] - 1);
}
ICNUM += sum / (len*(len - 1));
}
return ICNUM / l;
}

//假设key的最大长度
#define MAX_KEY_LENGTH 100

/*
用来生成假设的不同key的长度所计算出的重合指数,并根据谁最接近0.067进行排序
str: 密文字符串
ICS: 存放字符串的重合指数
ICSIdx: 存放ICS存的重合指数对应的key的长度
*/
void genICS(char *str, double *ICS, char*ICSIdx)
{
int pos = 0;
for (int i = 1; i < MAX_KEY_LENGTH; i++)
{
double ic = IC(str, i);
if (ic > 0.06 && ic < 0.07)
{
ICSIdx[pos] = i;
ICS[pos++] = ic;
}
}
for (int i = 0; i < pos - 1; i++)
{
for (int j = 0; j < pos - 1; j++)
{
double t1 = ICS[j];
double t2 = ICS[j + 1];
if (fabs(t1 - 0.067) > fabs(t2 - 0.067))
{
ICS[j] = t2;
ICS[j + 1] = t1;
char t1 = ICSIdx[j];
ICSIdx[j] = ICSIdx[j + 1];
ICSIdx[j + 1] = t1;
}
}
}
}

频度分析确定key

上述步骤可以得到key的可能的长度,我保存了所有位于区间(0.06, 0.07)的重合指数以及它所对应的key的长度

接下来就要分别根据这些key的长度来求key的内容

首先,如果key只有一个字符,那么维吉尼亚加密就变成了凯撒加密

如果key有两个字符,可以把明文分称两部分,两个两个一组,一部分全部取左边,一部分全部取右边,然后对这两部分进行不同字母表的凯撒加密:

1
2
3
4
5
6
7
8
假设key:ab
假设明文:this is easy
对应关系:abab ab abab
组a:tiies 字母表:abcdefghijklmnopqrstuvwxyz
组b:hssay 字母表:bcdefghijklmnopqrstuvwxyza
加密结果a:tiies
加密结果b:ittbz
加密结果:tiit it ebsz

因此可以分别对组a和组b,假设他们所对应的key的字符,进行解密,解密结果进行频度分析

字母表频率

正常的文本中,字母出现的频率是符合上表的。

字符是哪种情况与频度表所计算出的内积最大,则这一位的key就最有可能是什么

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
得到key的某一位所加密过的全部字符所组成的字符串
str: 密文字符串
buf: key的某一位所加密过的全部字符所组成的字符串
l: 开始偏移
n: key的长度
*/

void genStr(char *str, char *buf, int l, int n)
{
int Ilength = strlen(str);
char *unAlpha = (char*)malloc(Ilength);
getNoAlpha(str, unAlpha);
Ilength = strlen(unAlpha);
int pos = 0;
for (int i = l; i < Ilength; i += n)
{
buf[pos++] = unAlpha[i];
}
buf[pos] = '\x00';
free(unAlpha);
}

/*
频度表,从头到尾分别对应a,b,......,z
*/
double g[] = { 0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,0.01974, 0.00074 };

/*
对上一个函数所得到的字符串用假定的key的字符所对应的字母表表进行解密
buf: 上一个函数得到的buf
o: 加密时字母表的偏移
*/
void genBuf(char *buf, int o)
{
int i = 0;
while (buf[i] != '\x00')
{
int idx = indexOf(x, buf[i]);
idx -= o;
idx = idx < 0 ? idx + Xlength : idx;
buf[i++] = x[idx];
}
}

/*
上一个calcN函数的重载
buf: 上上个函数的结果
*/
void calcN(char *buf)
{
for (int i = 0; i < Xlength; i++)
{
N[i] = 0;
}
int Ilength = strlen(buf);
for (int i = 0; i < Ilength; i++)
{
N[indexOf(x, buf[i])]++;
}
}

/*
频度分析的关键函数,计算内积
buf: genStr所得到的buf
o: 加密时字母表的偏移
*/
double getqp(char *buf, int o)
{
char *bufCopy = (char*)calloc(strlen(buf)+1, 1);
strcpy(bufCopy, buf);
genBuf(bufCopy, o);
double sum = 0;
int i = 0;
int Blength = strlen(bufCopy);
calcN(bufCopy);
while (bufCopy[i] != '\x00')
{
int idx = indexOf(x, bufCopy[i]);
sum += ((double)N[idx]/Blength) * g[idx];
i++;
}
free(bufCopy);
return sum;
}

/*
根据计算出的最大内积来生成key值
str: 密文字符串
KL: key的长度
preKey: 求出的可能的key
*/
void genKey(char *str, int KL, char* preKey)
{
int Ilength = strlen(str);
for (int i = 0; i < KL; i++)
{
char *buf = (char*)calloc(Ilength, 1);
genStr(str, buf, i, KL);
double *avg = (double*)calloc(KL, 8);
for (int j = 0; j < Xlength; j++)
{
double s = getqp(buf, j);
if (avg[i] < s)
{
avg[i] = s;
preKey[i] = x[j];
}
}
free(avg);
free(buf);
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void test()
{
generateBox();
char str[] = "this is easy there is a river in front of me aunt cow said it was not deep but the little squirrel said it was deep what shall i do the old horse says my child you should try to cross the river by yourself if you donot try how do you know the river is deep or not the little horse carries the wheat and returns to the riverside at last he succeeds incrossing the river now he knows how deep the river is bosses used to use labour monitoring technologies to control over how workers do their jobs in februday amazon received patents for a wristband and it intended to force labourers to do their jobs with maximum efficiency it is a good option for firms seeking to maximise productivity but to labours it may not technology creates new opportunities for oversight but text book economics suggests that in a competitive labour market any attempt to coerce people into working harder than they want will fail";
char key[] = "thisisatest";
Vencrypt(str, key);
printf("Encrypted: %s\n", str);
double *ICS = (double*)calloc(MAX_KEY_LENGTH, 8);
char *ICSIdx = (char*)calloc(MAX_KEY_LENGTH, 1);
genICS(str, ICS, ICSIdx);
printf("-----------------------\n");
for (int i = 0; i < MAX_KEY_LENGTH; i++)
{
if (ICSIdx[i] != 0 || ICS[i] != 0)
printf("%d %f\n", ICSIdx[i], ICS[i]);
}
printf("-----------------------\n\n");
int i = 0;
while (ICSIdx[i] != 0 || ICS[i] != 0)
{
int KL = ICSIdx[i];
char *preKey = (char*)calloc(KL + 1, 1);
genKey(str, KL, preKey);
printf("Key: %s\n\n", preKey);
char *strCopy = (char*)calloc(strlen(str) + 1, 1);
strcpy(strCopy, str);
Vdecrypt(strCopy, preKey);
printf("Decrypt: %s\n", strCopy);
free(strCopy);
free(preKey);
i++;
printf("-----------------------\n\n");
}
free(ICS);
free(ICSIdx);
}

运行出现多个结果,但是同样也出现了正确的key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Encrypted: moqk qk etwq malzw qk a kmnxk pv xzgnm sx fx hcfb uop wsbw pb oik nhx vxxw jmb lhx pammsm kymikvwe lhqv ql wtw vxxw ezil saede b kw lpw oeh zhkzm kiqs fc uabsl qwm sasmew azq bg ckskl mom jqnek fq rhbzkmdf bj qhn kwfwl tkc zhp kw qwm kgso mal zadwr bw vxxw wj vgt mlw ebabdm zokww vtyzamk tai oaxhb svv rxxmkgz bg bze kmnxkzqvm st eekm al amkuexhk bgjzgakigk lax yqnmj nha zx duwoa zop hwxi apw zavxv al uvakmk uliv mh baw tsbhyj fhuqlwjigk lxvovgtggbik mh jwfbjoe snxk owo egrdijl wv bzmar cstl bu nwjjuweq tfhhgv jeviaoxk xsbwnmw xhk h ejqktuefw tul ab anmifwxk bg ngrvi dtuvcjmjs ms vh momaz bouw obmo usfamnq wyypkamfcr ml bl h ogwv oixahg mwj narfw kxxrqfo lo fepbfpaw xjowyumbcqlg  tum xg etiwmzk im qsr gvb lmuhgsdhzf kjmstxw fxp vxhwjtnrambla xwj ooijlbnpl jmt mipm uvwc muogsebvz amoyelxk mahb av s chqhxmpbadw ltfgnk tijswt trq tmamexl th ggxkjm hmgpei agmv egzcigk ztkkmj bzag xzxr difb oiep xtbs
-----------------------
11 0.066778
22 0.066718
33 0.067964
55 0.065468
44 0.064895
77 0.063709
99 0.062650
-----------------------

Key: thisisatest

Decrypt: this is easy there is a river in front of me aunt cow said it was not deep but the little squirrel said it was deep what shall i do the old horse says my child you should try to cross the river by yourself if you donot try how do you know the river is deep or not the little horse carries the wheat and returns to the riverside at last he succeeds incrossing the river now he knows how deep the river is bosses used to use labour monitoring technologies to control over how workers do their jobs in februday amazon received patents for a wristband and it intended to force labourers to do their jobs with maximum efficiency it is a good option for firms seeking to maximise productivity but to labours it may not technology creates new opportunities for oversight but text book economics suggests that in a competitive labour market any attempt to coerce people into working harder than they want will fail
-----------------------

Key: thisisatewttdifiskgest

Decrypt: this is easu thirr is q eiver in front ob me euat cej said it was not zeet bht txr little squirral seiq it mns deep what shahl i ho ghe eyd horse says my yhipd lou iuould try to croos tle eivue by yourself if uou hoaot jey how do you knos thi rvveh vs deep or not tha lixtye heese carries the sheet nnd hrturns to the rirerwiqe aj yast he succeedo ingrbssyag the river now de krojs hej deep the river es bssfes kfed to use laboun morigoryag technologieo to goatrey over how workens ds tueih wobs in februdau amezbn rupeived patents bor e weisjoand and it intejdeh tb fohpe labourers to zo tlevr jeos with maximum affmcvensl it is a good opteon joe fihzs seeking to matimmsr prequctivity but tk lafohrs yg may not technohogc ceeajrs new opportunetiis sor eiersight but tett bsox eceaomics suggesto thet vn a sbmpetitive labkur qaekej nny attempt to ckerge ceofye into working darhee thqa they want will baip
-----------------------

..........

但是有时会得不到正确结果,只能得到部分正确的key,这也就是利用统计分析的局限性了

比如这种情况:char key[] = "abcdefghijklmnopqrstuvwxyz";

会求出错误的key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Encrypted: tikv mx khah dsqes xi r jbpzn fl erppw sk sl idxe obk hqzv bn rwp lnt eght gaa bqo wughau jincmnbj rajf lx bgz lnoa iuoi iysef d zl rge png ltxzm bkje zm rxzdw sjq pfnumf wvd zv kayde gvt hznxl wu vmtrtgoj nl fwd nzzbh ihp zhq yk vmt koqz xmk yqeoc uf rtug gk hjp qfd ljvwpj nvzbo nmefxuj lay rdbys aof uiyayvb dz fus gymwkmdzb ys lbuw lj ybkloppf wcsiglmdjd rge skyiw tve qo vzbkh xfo wyzl qfd rjxhv ny iwbcpe hgtt kg nmz hxznus orrnzvzrxr frqwdfdhadap rn cppwvtr vdnb saj kdhbwkm yk qfdis lrfx ou nnlcgqon qdssii nbadiwgg tfzlvcc qae o lhzkmvvja ymd jv lrykulnn ea scgsv dtvjqocqs uq gs ynlqa tznf kxjy etrdirk dfgkfmjtjg rd te n udeu gindkk dnr gkuqx ylmtsys gc bqoafcna mpndvewmaoag  kee fb zprfmkm dp jyx npv wihnuwuyrk pftqkwl hzs lnoosvxrnzpmb pzd bjthjazbo xrr seyv estq lkxxzyvqh ilyzynpp rgau kq e hutxndtfvjt brthom ixpjeu cqc fzamvze fb qduiux jzkmjd iovr atxrqwq smerth kzth odbw vaov zmqr mirv
-----------------------
26 0.065404
78 0.062892
52 0.061496
-----------------------

Key: abrsefghijklmxgpdrstuzwxyz

Decrypt: thtd is easy thehm if a rivar in froye of me aunt cee snid it sas not dppp but the lijblr squinrel saio tt was deep wxit fhall e do the owo horse says cg cuild yku shoulo ery to cross jpe eiver xy yourspwf if you doneb tey how zo you knzh the river ii lerp or nkt the lieele horse cahzirs the sheat ano ceturns to txm rvversede at lade he succeedi qnprosseng the rtger now he knees uow deap the rigpr is bosses kaeq to usa labour xznitoring tukhaologees to coyerol over hom eoekers zo their uzbs in februtiy nmazoj receivpo patents foh i weistbwnd and ie tntended to vwrpe labkurers tz oo their jobi eigh maxemum efftniency it is q oobd opteon for ftcms seeking jw mnximioe produneivity but te taoours et may noe eechnology szentes naw opporefnities for edeesighp but texe mook economyks fuggeots that ty a competityde yaboun market lyy attempt te korrce paople inez working hahlee than phey wane hill fail
-----------------------

Key: avrnefkhsjzvmqopeksgizvxyzwlcsefghenkpbbmpmvcdzzflnjafrsrfvrijkamncpqfwtyvgifz

Decrypt: tnti is aaiy exeoe ie h rvhas in fvene of me eqnp nay seet yo sre yet zppc bfj the witfle emuerhte saoo yt wws tepf weat eoayx e eo thi elo horsi oaud ya clebt tkl eseuho eey ee crods tte ruren bo nhurypbf ib yeu oenlt tdf hbi zp you odoh the rmren te feil eh ikk fsu leeeye serse nardiee pha wxttt ato hetqrds ee tee ruceeeeee at pqse he sugyeaoe kngneinees exe ntgrr yew he vnois has daef iae rogur io besdus rsep ao hea maboyh mznitovenc eqehrkbebeve ee ckyeeow ever sow iorwaro de iaeix uebs en vemhuaay mtamaj secemleo paterps bzd c wveijwwep ldd ee tatpdded eo farcq haxokgxrs zz to tdeyr uebp wifo mnjenum ejviniencc et ed m iosz efoefz qer btczs duekiyg ta majemesu ekodanjiveto bfj tl lanvuee eu may ret eechnshocj oteepui ian aafonefaieyes fzr ohereegdt rjm tede roog esoyemfcs ebgtqous thej iy a comtateeuxe pwrepn dmcaep lyl aejempe to ooedye leeeee itee wonkynr xaoded ahnz piey wedt hill feel
-----------------------

Key: abcsifuhixklwndtqvstyvgifzwordeugrcjkabxgpdbzguzlxyz

Decrypt: thid es qask thurp es w rireh xg fvbyt oq mu gune nee snyw vt sls not depl bgt tte lytehe oquerhte sevo it hai jeea hxit fxtyl e oo the olo dodse eayi mj yheld uok haoyyo trj te irodd jpe eyorr xj yoursewb ir yog dodoe pru hos de nhu oazw tse hovec ti lerf he nke the litehe toree cqrceeo tha wxttt eao reeuhts tz exm rvlxeseoe at lase de eucoeets tjcnosoidv mhi etvec nec he vyees uep qeaa the rivpn ie boesei udad po uoe bpuoye xonttexinr eukhaeebgeps to conenox ovqr hew hkrgero de iaeme uobd id lebcftiy nctmoj ceceiveo lafenfs fer l srestxads tnh ve ineedjed ez vwrpu enbkfrers to ok tteid jors hetd maticjf ejstcipnse it td q oobt hctezn for ficis eeewinw tz iatimesu ekohhntigije bue ee taoenes ee may not eactnoxogo ccaapes jem dipseeunttyks fzc edeeibthp mut text mkow ecanocino sqggasjh mheg tn a nocvetteyde yqubun xarket ayu afteypt jo nkence leeeee maeo wzraong slhlee jann psey want helx faul
-----------------------