希尔密码(Hill Cipher)的实现

原理应该不用多讲了,自己百度就可以。

C++实现:

  1 #include <iostream>

  2 #include <string>

  3 #include <memory.h>

  4 #include <cstdlib>

  5 #include <ctime>

  6 #include <cstdio>

  7 #include <cmath>

  8 using namespace std;

  9 

 10 //定义一些常变量

 11 const int M = 26;   //定义集合{a,b,...,z}的26个英文字母

 12 

 13 //行和列均为5

 14 const int ROW = 5;

 15 const int COL = 5;   

 16 

 17 //定义5*5的加密矩阵

 18 int K[ROW][COL];

 19 

 20 //定义5*5的解密矩阵

 21 int D[ROW][COL];

 22 

 23 int P[ROW];  //明文单元

 24 int C[ROW];  //密文单元

 25 int F[ROW];  //密文解密后的单元

 26 

 27 //三元组gcd(a,b) = ax + by = d

 28 struct GCD

 29 {

 30     int x;

 31     int y;

 32     int d;

 33 };

 34 

 35 class Hill_Cipher

 36 {

 37 public:

 38     //产生随机矩阵

 39     void random_Matrix();

 40     //求矩阵的行列式

 41     int Det(int matrix[ROW][ROW],int row);

 42 

 43     //求两个数的最大公约数

 44     int gcd(int a,int b);

 45 

 46     /*

 47      *判断矩阵K是否在模26的情况下可逆

 48      *因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是

 49      *gcd(det K,26) = 1

 50      */

 51     bool Inverse(int matrix[ROW][ROW]);

 52 

 53     //矩阵相乘

 54     void multiphy(int matrix[ROW][ROW],int p[ROW],int row);

 55 

 56     //求出伴随矩阵

 57     void adjoint_matrix(int matrix[ROW][ROW],int row);

 58 

 59     //将明文加密为密文

 60     string encryption(string plaintext);

 61 

 62     //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)

 63     string deciphering(string ciphertext);

 64 

 65     //欧几里得算法求模的逆

 66     GCD extended_Euclid(int a,int b);

 67 

 68     //模逆运算

 69     int inverse(int a,int m);

 70 

 71     //由于C++不存在负数取模的内置函数,现在自己设定一个

 72     //定义一个模M的值

 73     int Mod(int a);

 74 };

 75 

 76 void Hill_Cipher::random_Matrix()

 77 {

 78     int i,j;

 79     for(i = 0;i < ROW;i++)

 80     {

 81         for(j = 0;j < COL;j++)

 82         {  

 83             K[i][j] = rand() % 26;  //产生一个5*5模26的矩阵

 84         }

 85     }

 86     cout << "随机产生5*5的矩阵:" << endl;

 87     for(i = 0;i < ROW;i++)

 88     {

 89         for(j = 0;j < COL;j++)

 90         {

 91             printf("%2d  ",K[i][j]);

 92         }

 93         cout << endl;

 94     }

 95 }

 96 

 97 //求矩阵的行列式

 98 int Hill_Cipher::Det(int matrix[ROW][ROW],int row)

 99 {

100     int i,j;            

101     int cofa[ROW][ROW];            //用于存放余子阵

102     int l;   //l为所递归的余子阵的行

103     int p = 0,q = 0;

104     int sum=0;

105     

106     //由于行和列相同(方阵),所以行列式的值一定存在,故不需要判断是否为方阵

107     

108     //递归基

109     if(row == 1) 

110         return matrix[0][0];

111    for(i = 0;i < row; i++)

112    {

113      for(l = 0;l < row - 1;l++)

114      {

115        if(l < i)  

116            p=0;

117        else  

118            p=1;

119        for(j = 0;j< row - 1;j++)

120        {

121          cofa[l][j] = matrix[l + p][j + 1];

122        }

123      }

124      //相当于(-1)^i

125      if(i % 2 == 0)  

126          q=1;

127      else 

128          q=(-1);

129      sum = sum + matrix[i][0] * q * Det(cofa,row - 1);

130    }

131    return sum;

132 }

133 

134 //求两个数的最大公约数

135 int Hill_Cipher::gcd(int a,int b)

136 {

137     int temp;

138     //交换两个数的大小,使得a为较大数

139     if(a < b)

140     {

141         temp = a;

142         a = b;

143         b = temp;

144     }

145     while(a % b)

146     {

147         temp = b;

148         b = a % b;

149         a = temp;

150     }

151     return b;

152 }

153 

154 /*

155  *判断矩阵K是否在模26的情况下可逆

156  *因为矩阵在模26的情形下存在可逆矩阵的充分必要条件是

157  *gcd(det K,26) = 1

158  */

159 bool Hill_Cipher::Inverse(int matrix[ROW][ROW])

160 {

161     if(gcd(Det(matrix,ROW),M) == 1)

162         return true;

163     else

164         return false;

165 }

166 

167 void Hill_Cipher::multiphy(int matrix[ROW][ROW],int p[ROW],int row)

168 {

169     int i,j;

170     //先将密文单元清零

171     memset(C,0,sizeof(C));

172     for(i = 0;i < ROW;i++)

173     {

174         for(j = 0;j < ROW;j++)

175         {

176             C[i] += P[j] * K[j][i];

177         }

178     }

179 }

180 

181 //将明文加密为密文

182 string Hill_Cipher::encryption(string plaintext)

183 {

184     int i;

185     string ciphertext;

186     //将字符串转化为明文数组

187     for(i = 0;i < ROW;i++)

188     {

189         P[i] = plaintext[i] - 'a';

190     }

191     multiphy(K,P,ROW);

192     //将密文数组转化为密文

193     for(i = 0;i < ROW;i++)

194         //这里先将其模26,再翻译为对应的字母

195     {

196         C[i] =Mod(C[i]);

197         ciphertext += C[i] + 'A';

198     }

199     return ciphertext;

200 }

201 

202 //求出伴随矩阵

203 void Hill_Cipher::adjoint_matrix(int matrix[ROW][ROW],int row)

204 {

205     int i,j,k,l;

206     int p,q;

207     p = q = 0;

208     int temp[ROW][ROW];

209     for(i = 0;i < ROW;i++)

210     {

211         for(j = 0;j < ROW;j++)

212         {

213             for(k = 0;k < ROW - 1;k++)

214             {

215                 if(k < i)

216                     p = 0;

217                 else

218                     p = 1;

219                 for(l = 0;l < ROW - 1;l++)

220                 {

221                     if(l < j)

222                         q = 0;

223                     else

224                         q = 1;

225                     temp[k][l] = matrix[k+p][l+q];

226                 }

227             }

228             D[j][i] = (int)pow(-1,(double)i+j)*Det(temp,ROW-1);

229             D[j][i] = Mod(D[j][i]);

230         }

231     }

232 }

233 

234 //将密文解密为明文(为了辨识清楚,我们统一以小写字母作为明文,大写字母作为密文)

235 string Hill_Cipher::deciphering(string ciphertext)

236 {

237     //求出矩阵的逆

238     string text;

239     int determinant = Det(K,ROW);

240     int inver = inverse(determinant,26);

241     adjoint_matrix(K,ROW);   //伴随矩阵

242     cout << "行列式的值: " << determinant << endl;

243     int i,j;

244     memset(F,0,sizeof(F));

245     for(i = 0;i < ROW;i++)

246     {

247         for(j = 0;j < ROW;j++)

248         {

249             F[i] += C[j] * D[j][i];

250         }

251         F[i] *= inver;

252         F[i] = Mod(F[i]);   //算到的结果要模去26

253     }

254     for(i = 0;i < ROW;i++)

255         text += F[i] + 'a';

256     return text;

257 }

258 

259 GCD Hill_Cipher::extended_Euclid(int a,int b)

260 {

261     GCD aa,bb;

262     if(b == 0)

263     {

264         aa.x = 1;

265         aa.y = 0;

266         aa.d = a;

267         return aa;

268     }

269     else

270     {

271         bb = extended_Euclid(b,a%b);

272         aa.x = bb.y;

273         aa.y = bb.x - (a / b) * bb.y;

274         aa.d = bb.d;

275     }

276     return aa;

277 }

278 

279 int Hill_Cipher::inverse(int a,int m)

280 {

281     GCD aa;

282     aa = extended_Euclid(a,m);

283     return aa.x;

284 }

285 

286 int Hill_Cipher::Mod(int a)

287 {

288     return a >= 0 ? a % M : (M + a % M);

289 }

290 

291 int main()

292 {

293     int i,j;

294     Hill_Cipher hh;

295     cout << "使用希尔密码进行消息的加解密:" << endl;

296 

297     //srand()函数产生一个以当前时间开始的随机种子.以保证每次产生的随机数矩阵都不相同

298     srand((unsigned)time(0));   

299     hh.random_Matrix();

300     while(!hh.Inverse(K))

301     {

302         cout << "该矩阵模26不可逆,不可以作为密钥!" << endl;

303         cout << endl;

304         hh.random_Matrix();

305     }

306     cout << "该矩阵模26可逆,因此可以作为密钥." << endl;

307     cout << endl;

308     

309     //利用所选密钥,对给定的5元明文信息进行加解密

310     string plaintext,ciphertext;

311     cout << "请输入5元明文信息:" << endl;

312     cin >> plaintext;

313     ciphertext = hh.encryption(plaintext);

314     cout << endl;

315     cout << "该明文通过希尔密码法加密过后,输出的密文消息为:" << endl;

316     cout << ciphertext << endl;

317     cout << endl;

318 

319     cout << "***输入0:退出          ***" << endl;

320     cout << "***输入1:查看明文空间对***" << endl;

321     cout << "***输入2:查看密文空间对***" << endl;

322     cout << "***输入3:查看密钥      ***" << endl;

323     cout << "***输入4:将消息解密    ***" << endl;

324     cout << "***输入5:查看菜单      ***" << endl;

325 

326     char c;

327     while(cin >> c)

328     {

329         if(c == '0')

330         {

331             cout << endl;

332             cout << "退出" << endl;

333             break;

334         }

335         else if(c == '1')

336         {

337             cout << "明文空间:" << endl;

338             for(i = 0;i < ROW;i++)

339                 cout << P[i] << "  ";

340             cout << endl;

341             cout << endl;

342         }

343         else if(c == '2')

344         {

345             cout << "密文空间:" << endl;

346             for(i = 0;i < ROW;i++)

347                 cout << C[i] << "  ";

348             cout << endl;

349             cout << endl;

350         }

351         else if(c == '3')

352         {

353             cout << "密钥:" << endl;

354             for(i = 0;i < ROW;i++)

355             {

356                 for(j = 0;j < ROW;j++)

357                 {

358                     printf("%2d  ",K[i][j]);

359                 }

360                 cout << endl;

361             }

362             cout << endl;

363         }

364         else if(c == '4')

365         {

366             hh.adjoint_matrix(K,ROW);

367             string ss;

368             ss = hh.deciphering(ciphertext);

369             cout << "该密文解密过后,显示的原来的明文消息:" << endl;

370             cout << ss << endl;

371             cout << endl;

372         }

373         else

374         {

375             cout << "***输入0:退出          ***" << endl;

376             cout << "***输入1:查看明文空间对***" << endl;

377             cout << "***输入2:查看密文空间对***" << endl;

378             cout << "***输入3:查看密钥      ***" << endl;

379             cout << "***输入4:将消息解密    ***" << endl;

380             cout << "***输入5:查看菜单      ***" << endl;

381         }

382     }

383     return 0;

384 }

Mathematica 9.0实现:

 1 Print["请输入你要输入的5元明文数组:"];

 2 

 3 A = {}

 4 For[i = 0, i < 5, i++, AppendTo[A, Input[]]]

 5 

 6 请输入你要输入的5元明文数组:

 7 

 8 {}

 9 

10 Print["请输入你要输入的5元明文数组:"];

11 

12 A = {}

13 For[i = 0, i < 5, i++, AppendTo[A, Input[]]]

14 

15 Print["产生5*5的随机数组"];

16 

17 While[True, B = RandomInteger[{0, 25}, {5, 5}];

18  If[Det[B] != 0, Break[]];]

19 Print["A=", A]

20 Print["B=", B]

21 

22 请输入你要输入的5元明文数组:

23 

24 {}

25 

26 产生5*5的随机数组

27 

28 A={1,2,3,4,5}

29 

30 B={{0,10,0,3,9},{22,18,0,17,4},{5,1,1,10,11},{8,8,13,16,15},{10,9,23,21,5}}

31 

32 

33 

34 

35 d = A.B

36 

37 {141, 126, 170, 236, 135}

38 

39 Print["d=", d]

40 

41 d={141,126,170,236,135}

42 

43 e = Mod[d, 26]

44 Print["加密后的密文为:", e]

45 

46 {11, 22, 14, 2, 5}

47 

48 加密后的密文为:{11,22,14,2,5}

49 

50 f = d.Inverse[B]

51 

52 Print["解密后的密文为:", f]

53 

54 {1, 2, 3, 4, 5}

55 

56 解密后的密文为:{1,2,3,4,5}

 

你可能感兴趣的:(IP)