密文:qqnscgpyjioxaiqksufhsnwvvkwixkbljngjepwelyreazscfufpiaggihlabltngkxngyyrtmrjiwsexwihrglnzbkotrzgtculfctugrihwlqqjkrecbskxlyeeosnavpxkbvmdultxwihbcmyvbzjqaajhyseqqnnsurgsmflxtegnmdtqrtnnrbcgbkotrzgtculpnssbxihxhovftvisufwfvfgvtgcfylaragocmobiugeakfclyoxraaonnwzojyeqgpjjhxlmosviyubkpyotktbwkarkfrxehltpyjcgyozhxobtnnritwwfwkoesanahkowozgdcnxobjrntgygyajyafuuluxpkttuytlmvqdweqgnxmgpcwupzulwwzxaeeonayxkxripyplgmbxripymyltyxqozocmsltnqlnyigszfwlcyoncutimnattomalxwilbtgnwkjltngonognpymyfoofgzflflfknmagdxkaaonxaofmzayotckxuyjcgkdnztqajcrttuvoxwhefonvazajyajolfwqmjsdbarefhtujdtkfijmbbyiamnyoavyttuksyktyxztqosyslbvfnnmegwgqowozjiuyglbnsguplwobwyibttihxobtnnritwwqajagsehlmenwifkoztbdmftnnoqwobaflfurualbbhhnrlyfzbbnngkrgkhcywiigcskxzdwigedultlfseeyhchwxcfsgkwujwpqnpntdagobasaaienzbpyfprxdckvrbxefyogwhccmerdimlbkpfcgovclbbbfnqlunmkbxupbxtofbqrjseklulxactbvmdultcxwhrglnzhrcqiaonakhjntfgneewrrwieerycfzfbxurytbsmknjdgubyltztqeqnhbza
结果:
1.算法思想
首先循环对密文分子串,分别分为一个字串,两个字串等等,然后计算子串的无偏估计值IC,直到字串的无偏估计值的平均值大于0.065为止,然会返回字串的个数,这就是密钥的长度。然后每个字串分别求移位26次的拟重合指数,最大拟重合指数的移位次数加上a就是单个字串的密钥。然后把每个字串的密钥加一起就是密文的密钥。然后根据密钥减a的次数对每个字串移位,即得到明文。
2.步骤
(1)调用input()方法从txt文件引入密文
(2)调用get_keysize()方法求出密钥长度
(3)调用get_keyword()方法求出密钥
(4)调用decode()方法根据密钥解密
说明:由于把分字串,词频,求单个字串的密钥都定义成了方法,是一层一层调用的,叙述起来很麻烦,于是就只写了几个大的方法。
#include<iostream>
#include<map>
#include<string>
#include <fstream>
using namespace std;
map<char, int> get_count(string s)
{
map<char, int> word_count;
size_t i = 0;
string words = s;
while (i != s.size())
{
++word_count[words[i]];//统计字符个数,按字母顺序排列
++i;
}
return word_count;
}
void print(map<char, int> m)
{
map<char, int> word_count = m;
map<char, int>::const_iterator iter = m.begin();
while (iter != m.end())
{
cout << iter->first << ":"<<iter->second<<endl;
++iter;
}
}
float get_per_ic(string s)
{
map<char, int> word_count = get_count(s);
map<char, int>::const_iterator iter = word_count.begin();
fl
float sum=0;
float l = (float)s.size();
while (iter != word_count.end())
{
float count = float(iter->second);
float ic = (count*(count - 1)) / (l*(l - 1));//计算无偏估计值
sum += ic;
++iter;
}
return sum;
}
string* divid_str(string s, int n)
{
int i=0,l=(int)s.size();
string *a = new string[n];
float *ic = new float[n];
for (int i = 0; i < n; i++)
{
int distance =i;
for (int j = 0; j < l; j++)
{
if (distance >= l)break;//越界退出
a[i] += s[distance];
distance+= n;//每次移动n位
}
}
return a;
}
float get_mean_ic(string s, int n)
{
float ic=0;
string *a = divid_str(s,n);
for (size_t i = 0; i < n; i++)
{
ic += get_per_ic(a[i]);//总的无偏估计值
}
return ic / n;
}
double get_prob(char i)
{
double prob = 0;
switch (i)
{
case 'a':prob = 0.0805; break;
case 'b':prob = 0.0162; break;
case 'c':prob = 0.0320; break;
case 'd':prob = 0.0365; break;
case 'e':prob = 0.1231; break;
case 'f':prob = 0.0228; break;
case 'g':prob = 0.0161; break;
case 'h':prob = 0.0514; break;
case 'i':prob = 0.0718; break;
case 'j':prob = 0.0010; break;
case 'k':prob = 0.0052; break;
case 'l':prob = 0.0403; break;
case 'm':prob = 0.0225; break;
case 'n':prob = 0.0719; break;
case 'o':prob = 0.0794; break;
case 'p':prob = 0.0229; break;
case 'q':prob = 0.0020; break;
case 'r':prob = 0.0603; break;
case 's':prob = 0.0659; break;
case 't':prob = 0.0959; break;
case 'u':prob = 0.0310; break;
case 'v':prob = 0.0093; break;
case 'w':prob = 0.0203; break;
case 'x':prob = 0.0020; break;
case 'y':prob = 0.0188; break;
case 'z':prob = 0.0009; break;
}
return prob;
}
double get_m(string s)
{
map<char, int> wordcount = get_count(s);
map<char, int>::const_iterator iter = wordcount.begin();
double m=0.0;
size_t l = s.size();
while (iter != wordcount.end())
{
int count = iter->second;
m += get_prob(iter->first)*count / l;//拟重合指数
++iter;
}
return m;
}
char move_position(string s)
{
string temp;
size_t i;
float max_ic = 0;
int max_i = 0;
for (i = 1; i <=26; i++)
{
temp = s;
int n = 0;
char c = temp[0];
for (size_t j = 0; j < temp.size(); j++)
{
n= temp[j] - 97;
char c =((n - i+26)%26)+97;//移位
temp[j] = c;
}
float ic = get_m(temp);
if (ic>max_ic)
{
max_ic = ic;//最大值
max_i = i;
}
}
char c = 'a' + max_i%26;
return c;
}
string get_keyword(string s, int n)
{
string keyword = "";
string *a = divid_str(s,n);
for (size_t i = 0; i < n; i++)
{
keyword += move_position(a[i]);
}
return keyword;
}
int get_keysize(string s)
{
int i;
for ( i = 1; i>0; i++)
{
float ic = get_mean_ic(s,i);
if (ic >= 0.065)break;
}
return i;
}
string input(string filename)
{
ifstream in(filename);
string line,str;
if (in) // 有该文件
{
while (getline(in, line)) // line中不包括每行的换行符
{
str += line;
}
}
else // 没有该文件
{
return "no such file";
}
return line;
}
string decode(string s)
{
string str = s;
string keyword = get_keyword(s, get_keysize(s));
int keysize = (int)keyword.size();
string decode(s.size(),' ');
for (int i = 0; i < keysize; i++)
{
int n,distance=i;
for (int j = 0; j < s.size(); j++)
{
if (distance >= s.size())break;//越界退出
n = (int)s[distance] - 97;
int move = keyword[i] - 97;
str[distance] = ((n - move + 26) % 26) + 97;
distance += keysize;//每次移动n位
}
}
return str;
}
本文介绍了维吉尼亚密码的破解方法,首先通过计算子串的无偏估计值IC来确定密钥长度,然后利用拟重合指数找出每个字串的密钥,最后解密得到明文。主要步骤包括读取密文、求密钥长度、获取密钥及解密过程。
753

被折叠的 条评论
为什么被折叠?



