明文加密可以通过各种方式。
比较老一点的有Caesar加密算法、Vigenere加密算法,这两种都是属于替代加密算法。替代加密算法是将明文中的每一个字符用另一个字符替换为密文中的一个字符。除接受者外,其他人不理解其间的替代。接受者对密文作反向替换后恢复成明文。Caesar加密算法是将26个英文字母循环右移3位而得来的,也就是说将明文中的A用密文D代替,以此类推得到密文,从而实现加密。 人们在单一Caesar密码的基础上扩展出多表密码,称为Vigenere密码。它是由16世纪法国亨利三世王朝的布莱瑟·维吉尼亚发明的。维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。维吉尼亚密码的密钥空间大小为26m,所以即使m的值很小,使用穷尽密钥搜索方法也需要很长的时间。例如,当m=5时,密钥空间大小超过1.1*107,这样的密钥量已经超出了使用手算进行穷尽搜索的能力范围。 以下为Vigenere加密算法的密表:
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
A 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
BB 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
CC 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
DD 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
EE 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
FF 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
GG 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
HH 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
II 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
JJ 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
KK 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
LL 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
MM 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 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
OO 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
PP 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
QQ 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
RR 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
SS 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
TT 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
UU 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
VV 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
WW 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
XX 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
YY 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
ZZ 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 通过这个加密表结合Caesar加密算法我们不难猜想Vigenere加密算法是如何加密的。首先,我们有一串明文和加密密钥,这里举个例子来说,明文为:thanks,加密密钥为:vigenere,我们会得到加密密文为:opgrxw,明文第一个字母为t,第一个密钥字母为v,因此可以找到在v行中代替t的为o,依此类推。以下是Caesar加密算法和Vigenere加密算法的C程序实现:
#include "stdio.h" #include "string.h" #include "ctype.h" #include "stdlib.h" #define N 50 void menu();/*显示菜单*/ char * inputPandK();/*输入明文和密钥*/ void caesar();/*恺撒加密算法*/ void vigenere();/*维吉尼亚加密算法*/ int main() { menu(); system("PAUSE"); return 0; } void menu() { int i=0; printf(" Clssical encrption program: \n"); printf("**** 0-----------EXIT **** \n"); printf("**** 1-----------Caesar **** \n"); printf("**** 2-----------Vigenere **** \n"); printf("******************************* \n"); printf("Choose your option: "); scanf("%d",&i); switch(i) { case 0: break; case 1: caesar(); break; case 2: vigenere(); break; default:break; } } //输入明文和密钥 char* inputPandK() { char * plntxt;//声明一个明文指针类型 int i = 0,choose = 0; //开辟一块内存空间 plntxt = (char *)malloc(N * sizeof(char)); if(plntxt == NULL) { printf("Memory location failed!"); exit(-1); } /*输入明文*/ printf("**** Please Enter plaintext: \n"); fflush(stdin); while(i < N) { plntxt[i] = getchar(); //如果输入不合法,跳出循环,最后一个元素赋值为空 if(plntxt[i] > 126 || plntxt[i] < 32) { plntxt[i] = '\0'; break; } else i++; } //返回该数组首地址 return plntxt; } void caesar() { char* _plntxt;//明文指针 int* _cphrtxt;//密文指针 unsigned int i,j; unsigned char key = 0; //接收明文 _plntxt = inputPandK(); printf("Please Enter the key:"); scanf("%c",&key); while(!isdigit(key)) { //key = 0; printf("Your input is error! \n"); printf("Enter the key again: \n"); scanf("%c",&key); } _cphrtxt = (int *)malloc(N * sizeof(int)); if(_cphrtxt == NULL) { printf("Memory location failed!"); exit(-1); } //caesar加密算法 for(i = 0;i < strlen(_plntxt);i++) { if(_plntxt[i] >= 'A' && _plntxt[i] <= 'Z') //直接转换为小写 _cphrtxt[i] = (_plntxt[i]%'A' + key)%26 + 'a'; else if(_plntxt[i] >= 'a' && _plntxt[i] <= 122) //直接转换为大写 _cphrtxt[i] = (_plntxt[i]%'a' + key)%26 + 'A'; else //如果为其他字符,则不变输出 _cphrtxt[i] = _plntxt[i]; } //输出密文 printf("The ciphertext is :"); for(j = 0;j <= i;j++) printf("%c",_cphrtxt[j]); printf("\n"); free(_plntxt); free(_cphrtxt); } void vigenere() { char* _plntxt; int* _cphrtxt; char* key; unsigned int i = 0,j; key = (char *)malloc(N * sizeof(char));//开辟密钥,密文空间 if(key == NULL) { printf("Memory location failed!"); exit(-1); } _cphrtxt = (int *)malloc(N * sizeof(int)); if(_cphrtxt == NULL) { printf("Memory location failed!"); exit(-1); } _plntxt = inputPandK(); //接受明文 printf("Enter the key: \n"); fflush(stdin);//用来清空输入缓存,以便不影响后面输入的东西 while(i < N) { key[i%strlen(key)] = getchar(); if(key[i%strlen(key)] > 126 || key[i%strlen(key)] < 32) { key[i%strlen(key)] = '\0'; break; } else i++; } for(i = 0;i < strlen(_plntxt);i++) { //密钥为大写字母 if(key[i%strlen(key)] >= 'A' && key[i%strlen(key)] <= 'Z') { //明文为大写字母 if(_plntxt[i] >= 'A' && _plntxt[i] <= 'Z') _cphrtxt[i] = (key[i%strlen(key)]-'A' + _plntxt[i]-'A')%26 + 'a'; //明文为小写字母 else if(_plntxt[i] >= 'a' && _plntxt[i] <= 'z') _cphrtxt[i] = (key[i%strlen(key)]-'A' + _plntxt[i]-'a')%26 + 'A'; } //密钥为小写 if(key[i%strlen(key)] >= 'a' && key[i%strlen(key)] <= 'z') { //明文为大写字母 if(_plntxt[i] >= 'A' && _plntxt[i] <= 'Z') _cphrtxt[i] = (key[i%strlen(key)]-'a' + _plntxt[i]-'A')%26 + 'a'; //明文为小写字母 if(_plntxt[i] >= 'a' && _plntxt[i] <= 'z') _cphrtxt[i] = (key[i%strlen(key)]-'a' + _plntxt[i]-'a')%26 + 'A'; } //如果为其他字符,则不变输出 if(key[i%strlen(key)] < 'A' || ((key[i%strlen(key)] > 'Z' && key[i%strlen(key)] < 'a')) || key[i%strlen(key)] > 'z') _cphrtxt[i] = _plntxt[i]; } //屏幕输出密文 printf("The ciphertext is :"); for(j = 0;j <= i;j++) printf("%c",_cphrtxt[j]); printf("\n"); free(_plntxt); free(_cphrtxt); free(key); }
基于这两种加密算法的理念,我们还可以从生活中得到自己的一些加密算法,比如说我们可以从电脑键盘上的26个字母的排序顺序来实现加密,具体对应关系如下(这里说明以下,比如第一个字母A是电脑键盘上的A,我们得到它是排在第11,从而我们在字母表中数到第11位为K,比如说明文为thanks,则密文为eiqfal。): ABCDE:KXVMT
FGHIJ:NOPHQ
KLMNO:RSZYI
PQRST:JADLE
UVWXY:GWBUF
Z:T
当然这里都是一种类型的加密方式,替代加密算法。有一种叫MD5的加密算法,全称是Message-Digest Algorithm 5(信息-摘要算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest开发出来,经MD2、MD3和MD4发展而来。这里附上一个MD5加密解密的网址:http://www.xmd5.com/。