维吉尼亚密码C语言实现
- 格式:doc
- 大小:81.00 KB
- 文档页数:8
一、实验目的1. 理解并掌握传统密码算法的基本原理和实现方法。
2. 通过编程实践,加深对传统密码算法的理解。
3. 分析传统密码算法的优缺点,为后续学习现代密码算法打下基础。
二、实验内容本次实验主要涉及以下三种传统密码算法:1. 仿射密码2. 单表代替密码3. 维吉尼亚密码1. 仿射密码(1)原理简介:仿射密码是一种单字母替换密码,加密公式为:Ci = (ai pi + bi) mod 26,其中Ci为密文,pi为明文,ai和bi为密钥。
(2)算法流程:① 加密:根据密钥计算密文。
② 解密:根据密钥计算明文。
(3)代码实现(C语言):```c#include <stdio.h>// 加密函数void encrypt(char plaintext, char key, char ciphertext) {int a = key[0] - 'a';int b = key[1] - 'a';for (int i = 0; plaintext[i] != '\0'; i++) {if (plaintext[i] >= 'a' && plaintext[i] <= 'z') {ciphertext[i] = (a (plaintext[i] - 'a') + b) % 26 + 'a';} else {ciphertext[i] = plaintext[i];}}ciphertext[strlen(plaintext)] = '\0';}// 解密函数void decrypt(char ciphertext, char key, char plaintext) {int a = key[0] - 'a';int b = key[1] - 'a';for (int i = 0; ciphertext[i] != '\0'; i++) {if (ciphertext[i] >= 'a' && ciphertext[i] <= 'z') {plaintext[i] = (a (ciphertext[i] - 'a' - b + 26) % 26) + 'a';} else {plaintext[i] = ciphertext[i];}}plaintext[strlen(ciphertext)] = '\0';}int main() {char plaintext[100] = "hello world";char key[3] = "ab";char ciphertext[100], decryptedtext[100];encrypt(plaintext, key, ciphertext);decrypt(ciphertext, key, decryptedtext);printf("Plaintext: %s\n", plaintext);printf("Ciphertext: %s\n", ciphertext);printf("Decrypted text: %s\n", decryptedtext);return 0;}```2. 单表代替密码(1)原理简介:单表代替密码是一种将明文中的每个字符映射到密文的密码算法。
哈尔滨工程大学实验报告实验名称:古典密码算法班级:学号:姓名:实验时间:2014年4月成绩:指导教师:实验室名称:哈尔滨工程大学实验室与资产管理处制一、实验名称古典密码算法二、实验目的通过编程实现经典的代替密码算法和置换密码,包括移位密码、维吉尼亚密码、周期置换密码、列置换密码,加深对代替技术的了解,为现代分组密码实验奠定基础。
三、实验环境(实验所使用的器件、仪器设备名称及规格)运行Windows 或Linux 操作系统的PC 机,具有gcc(Linux)、VC(Windows)等C 语言编译环境。
四、实验任务及其要求(1)根据实验原理部分对移位密码的介绍,自己创建明文信息,并选择一个密钥,编写移位密码的实现程序,实现加密和解密操作。
(2)根据实验原理部分对维吉尼亚密码的介绍,自己创建明文信息,并选择一个密钥,编写维吉尼亚密码的实现程序,实现加密和解密操作。
(3)根据实验原理部分对周期置换密码的介绍,自己创建明文信息,并选择一个密钥,编写周期置换密码的实现程序,实现加密和解密操作。
(4)根据实验原理部分对列置换密码的介绍,自己创建明文信息,并选择一个密钥,编写列置换密码的实现程序,实现加密和解密操作。
五、实验设计(包括原理图、真值表、分析及简化过程、卡诺图、源代码等)1.移位密码移位密码(Shift Cipher)是一种典型的单表替代密码,也称为加法密码。
移位密码的加密方法就是将明文中的每个字母用其在字母表后面的第k 个字母替代,它的加密过程可以表示为: c = (m + k) mod n其中,m 为明文字母在字母表中的位置数;n 为字母表中的字母总数;k 为密钥;c 为密文字母在字母表中对应的位置数。
相应的,移位密码的解密过程可以表示为:m = (c - k) mod n移位密码的一个典型代表就是凯撒密码(Ceaser Cipher),它是k=3 时的移位密码。
使用英文字母表的撒密码的加(解)密可以表示为:m = (c + 3) mod 26 m = (c - 3) mod 26,例如,明文:attacks at nine am密钥:3加密:将明文分组对每一个密文字母,依英文字母表,用其右的第 3 个字母代替密文:dwwdfnv dw qlqh dp另外,使用凯撒密码加密后的密文“dwwdfnvdwilyhsp”,其明文为“attacks at five pm”。
AESECB加密算法C语言代码实现要实现AESECB加密算法的C语言代码,需要先了解AES算法的基本原理和步骤。
以下是一个使用C语言实现AESECB加密算法的示例代码:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/aes.h>//定义密钥长度#define KEY_LENGTH 16//ECBAES加密函数void AESEncrypt_ECB(const unsigned char* plainText, int plainTextLength, unsigned char* cipherText,const unsigned char* key)//创建AES密钥结构体AES_KEY aesKey;//设置加密密码AES_set_encrypt_key(key, KEY_LENGTH * 8, &aesKey);//加密数据AES_ecb_encrypt(plainText, cipherText, &aesKey, AES_ENCRYPT);//ECBAES解密函数void AESDecrypt_ECB(const unsigned char* cipherText, int cipherTextLength, unsigned char* plainText,const unsigned char* key)//创建AES密钥结构体AES_KEY aesKey;//设置解密密码AES_set_decrypt_key(key, KEY_LENGTH * 8, &aesKey);//解密数据AES_ecb_encrypt(cipherText, plainText, &aesKey, AES_DECRYPT);int mai//指定原始明文和密钥unsigned char plainText[] = "Hello, World!";unsigned char key[] = "secretkey";//计算明文长度int plainTextLength = strlen(plainText);//计算加密后的数据长度int cipherTextLength = ((plainTextLength / KEY_LENGTH) + 1) * KEY_LENGTH;//分配加密后数据的内存unsigned char* cipherText = (unsignedchar*)malloc(cipherTextLength);//加密数据AESEncrypt_ECB(plainText, plainTextLength, cipherText, key);//打印加密后的结果printf("Cipher text: ");for (int i = 0; i < cipherTextLength; i++)printf("%02x ", cipherText[i]);}printf("\n");//分配解密后数据的内存unsigned char* decryptedText = (unsignedchar*)malloc(cipherTextLength);//解密数据AESDecrypt_ECB(cipherText, cipherTextLength, decryptedText, key);//打印解密后的结果printf("Decrypted text: %s\n", decryptedText);//释放已分配的内存free(cipherText);free(decryptedText);return 0;```上述代码使用了OpenSSL库提供的AES函数来实现ECB模式的AES加密和解密操作。
破解维吉尼亚密码题⽬密⽂为:KCCPKBGUFDPHQTYAVINRRTMVGRKDNBVFDETDGILTXRGUD DKOTFMBPVGEGLTGCKQRACQCWDNAWCRXIZAKFTLEWRPTYC QKYVXCHKFTPONCQQRHJVAJUWETMCMSPKQDYHJVDAHCTRL SVSKCGCZQQDZXGSFRLSWCW 1、Kasiski 测试法⾸先我们⽤Kasiski 测试法确定密钥字的长度。
密⽂串KC 在密⽂中的三处出现,起始位置在1,139,260,这三个数互素,所以未得到有效的信息2、计算重合指数确定密钥长度对该问题,使⽤如下代码计算其重合指数:cipher = 'KCCPKBGUFDPHQTYAVINRRTMVGRKDNBVFDETDGILTXRGUD\DKOTFMBPVGEGLTGCKQRACQCWDNAWCRXIZAKFTLEWRPTYC\QKYVXCHKFTPONCQQRHJVAJUWETMCMSPKQDYHJVDAHCTRL\SVSKCGCZQQDZXGSFRLSWCWSJTBHAFSIASPRJAHKJRJUMV\GKMITZHFPDISPZLVLGWTFPLKKEBDPGCEBSHCTJRWXBAFS\PEZQNRWXCVYCGAONWDDKACKAWBBIKFTIOVKCGGHJVLNHI\FFSQESVYCLACNVRWBBIREPBBVFEXOSCDYGZWPFDTKFQIY\CWHJVLNHIQIBTKHJVNPIST'# print(len(cipher))n = len(cipher)def getNum(code):#统计各字符出现频率count={}length = len(code)for i in range(len(code)):count[code[i]] = 0for i in range(len(code)):count[code[i]] += 1#print(count)#计算sum = 0for i in count:sum += count[i]*(count[i]-1)I = sum / (length*(length-1))# print(sum)# print((length*(length-1)))return I# print(getNum(cipher))def searchResult(code, k):print(k, "的结果:")step = int(n/k)sp = []for i in range(k):c = []for j in range(0, n, k):if j+i < n:c.append(code[j+i])c = ''.join(c)sp.append(c)for s in sp:if len(s) > 5:I = getNum(s)print(I)if I > 0.06:print('****************************************************')for i in range(1, 10):searchResult(cipher, i)输出结果为:1 的结果:0.0408718383495831552 的结果:0.0384615384615384640.047120045623039633 的结果:0.0559418457648546140.0481016731016731050.048262548262548264 的结果:0.037254901960784310.042742398164084910.0375788869764773350.049053356282271955 的结果:0.042581211589113260.043020193151887620.0325644504748982340.0352781546811397550.042966983265490736 的结果:0.06265664160401002****************************************************0.08376623376623377****************************************************0.049350649350649350.06493506493506493****************************************************0.042857142857142860.07337662337662337****************************************************7 的结果:0.0306122448979591830.0443262411347517750.043439716312056740.0407801418439716350.0443262411347517750.0443262411347517750.0407801418439716358 的结果:0.033222591362126250.040650406504065040.033681765389082460.040650406504065040.039488966318234610.045296167247386760.040650406504065040.05458768873403029 的结果:0.0512091038406827860.042674253200568990.06401137980085349****************************************************0.07539118065433854****************************************************0.040540540540540540.034534534534534530.043543543543543540.048048048048048050.042042042042042045由此可以初步判断出密钥长度为6。
在Scratch中,字符串加密的原理通常涉及将字符串中的每个字符按照某种规则进行转换或替换,使得原始信息变得难以被解读。
常见的加密方法包括使用替换密码、凯撒密码(Caesar Cipher)、维吉尼亚密码(Vigenere Cipher)等。
例如,一种简单的替换密码方法是将字符串中的每个字符替换为另一个字符。
为了增加安全性,可以随机生成替换字符,或者使用一个预先定义的替换表。
凯撒密码则是一种简单的移位密码,将字符串中的每个字符向后移动几位。
维吉尼亚密码是一种变体的移位密码,它使用一个密钥作为加密的基础,每个字母都被替换为密钥中的对应字母。
在Scratch中,可以使用不同的编程技巧来实现这些加密方法。
例如,可以使用字符串函数来获取字符串中的特定字符,使用随机数生成器来生成替换字符等。
为了实现更高级的加密方法,可能需要使用更复杂的编程技巧和算法。
需要注意的是,虽然Scratch是一个很好的编程学习工具,但它的安全性相对较低。
因此,如果需要在Scratch中处理敏感信息或进行高安全性的加密操作,建议使用经过严格验证的加密库或算法。
在Scratch中,可以使用以下几种字符串加密方法:替换密码:这种方法涉及将字符串中的每个字符替换为另一个字符。
为了增加安全性,可以随机生成替换字符,或者使用一个预先定义的替换表。
凯撒密码:这是一种简单的移位密码,将字符串中的每个字符向后移动几位。
在凯撒密码中,移动的位数是密钥,需要保密。
维吉尼亚密码:这是一种变体的移位密码,它使用一个密钥作为加密的基础,每个字母都被替换为密钥中的对应字母。
除了上述方法外,还可以使用一些更复杂的加密方法,例如AES加密、RSA 加密等。
这些方法需要在Scratch中使用更高级的编程技巧和算法来实现。
需要注意的是,Scratch是一个面向儿童的编程学习工具,它的安全性相对较低。
因此,如果需要在Scratch中处理敏感信息或进行高安全性的加密操作,建议使用经过严格验证的加密库或算法。
维吉尼亚密码c语言源代码#include<stdio.h> // 头文件<stdio.h> , 声明标准输入输出函数#include<string.h> // 头文件<string.h> ,声明字符串操作函数char vigenere_table[26][26]; //定义维吉尼亚表void set_vigenere_table(){int i,j;int key; //行指针for (i = 0; i < 26; i++){key=i;for(j=0;j<26;j++){vigenere_table[i][j]='A'+(key%26);key++;}}printf("初始化维吉尼亚表完毕:\n\n");}void vigenere_encrypt(char* source,char* des) //定义加密函数{int source_len=strlen(source);int key_len=strlen(des);int i;for(i=0;i<source_len;i++) //对每个字母进行加密{int source_index= source[i]-'A'; //密文指针int key_index=des[i%key_len]-'A'; //维吉尼亚表指针int des_index=vigenere_table[key_index][source_index]-'A';des[i]=des_index+'A';}des[source_len]='\0';}void vigenere_decrypt(char* source,char* des) //定义解密函数{#define MAX_LEN 26int source_len=strlen(source);int key_len=strlen(des);int i;for(i=0;i<source_len;i++) //对每个字母进行解密{int key_index=des[i%key_len]-'A'; //维吉尼亚表指针int j;for(j=0;j<MAX_LEN;j++) //从维吉尼亚表中查找密文指针{if(vigenere_table[key_index][j]==source[i]){break;}}des[i]=j+'A';}des[source_len]='\0';}int main(){char plain[]="VIGENERECIPHER";char key[]="ABCD";char result[20];char result1[20];set_vigenere_table();vigenere_encrypt(plain,result);printf("明文: %s\n密钥: %s\n密文: %s\n",plain,key,result);vigenere_decrypt(result,result1);printf("解密后: %s\n",result1);return 0;}。
一.预习准备1. 实验目的(1). 熟记古典对称密码的概念和特点;(2). 理解若干种古典密码体制的原理;(3). 掌握维吉尼亚及Playfair密码体制的编程实现。
2. 实验环境Widows7操作系统、Microsoft Visual Studio 2010 (选择自己熟悉的编程语言和环境)3. 实验内容和要求(1)实验内容1.实现维吉尼亚密码体制;2.实现Playfair密码体制。
(2) 实验要求1.复习课本/课件相关内容。
2.程序中不能固定密钥词,即用户可自行输入密钥词,然后对输入的明文进行加密,或对输入的密文进行解密二. 编程思路(实验原理)维吉尼亚密码原理:引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。
Playfair原理:根据下列规则一次对明文的两个字母加密:(1)、属于相同对中的重复的明文字母将用一个填充字母进行分隔,因此,词balloon将被加密为ba lx lo on。
(2)、属于该矩阵相同行的明文字母将由其右边的字母替代,而行的最后一个字母由行的第一个字母代替。
例如,ar被加密为RM。
(3)、属于相同列的明文字母将由它下面的字母代替,而列的最后一个字母由列的第一个字母代替。
例如,mu被加密为CM。
(4)、否则,明文的其他字母将由与其同行,且与下一个同列的字母代替。
因此,hs成为BP,ea成为IM(或JM,这可根据加密者的意愿而定)。
三. 实验总结1. 实验程序(详细设计)维吉尼亚代码:#include<stdio.h>#include<stdlib.h>#include<string.h>#define N 80int main(void){char message[N];int n,i;int length;printf("明文:");gets(message);printf("密钥:");scanf("%d",&n);printf("明文:");puts(message);printf("\n");length=strlen(message);for(i=0;i<length;i++){if(message[i]>='A' && message[i]<='Z'){message[i]=((message[i]-'A')+n)%26+'A';}else if(message[i]>='a' && message[i]<='z'){message[i]=((message[i]-'a')+n)%26+'a';}else continue;}puts("密文:");puts(message);printf("\n");return 0;}Playfair代码:void encrypt(){int i,k;const int N=100;char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//字母是否已在矩阵中,与letters数组对应char ch[5][5];//5X5矩阵char ch1[N];//密钥char ch2[N];//明文char ch4;//无关字符int len='a'-'A';cout<<"输入密钥:";cin>>ch1;int flg=1;while(flg==1){for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母{if(ch1[i]>'z'||ch1[i]<'a'){cout<<"请重新选择操作:"<<endl;flg=0;break;}elsech1[i]=ch1[i]-len;}if(flg==1){ for(i=0;i<strlen(ch1);i++) {if(ch1[i]=='J')ch1[i]='I';}i=0;int j=0;for(int k=0;k<strlen(ch1);k++){for(int t=0;t<25;t++){if(ch1[k]==letters[t]&&flag[t]==0){ch[i][j]=letters[t];flag[t]=1;if(j<4)j++;else {i++;j=0;}}}}for( k=0;k<25;k++){if(flag[k]==0){ch[i][j]=letters[k];flag[k]=1;if(j<4)j++;else{i++;j=0;}}}cout<<"密钥填充后的矩阵为:"<<endl;for(i=0;i<5;i++)for(j=0;j<5;j++){cout<<ch[i][j];cout<<" ";if(j==4)cout<<endl;}cout<<endl;cout<<"请输入明文(请输入英文字符):";cin>>ch2;cout<<"输入一个无关字符:";cin>>ch4;if(ch4>='a')ch4=ch4-len;for(k=0;k<strlen(ch2);k++)//把所输入的明文转化为大写字母{if(ch2[k]>='a')ch2[k]=ch2[k]-len;}for(k=0;k<strlen(ch2);k++)//把明文中的J都变为I{if(ch2[k]=='J')ch2[k]='I';}//为明文添加必要的无关字符以防止同一组的两个字符相同for( k=0;k<strlen(ch2);k+=2){if(ch2[k]==ch2[k+1]){for(int t=strlen(ch2);t>k;t--)ch2[t+1]=ch2[t];ch2[k+1]=ch4;}}//若明文有奇数个字符,则添加一个无关字符以凑够偶数个if(strlen(ch2)%2!=0){ch2[strlen(ch2)+1]=ch2[strlen(ch2)];//字符串结尾赋'\0'ch2[strlen(ch2)]=ch4;//明文串尾插入无关字符}cout<<"经过处理后的明文为:";for(k=0;k<strlen(ch2);k+=2)cout<<ch2[k]<<ch2[k+1]<<" ";cout<<endl;cout<<"其最终长度为:"<<strlen(ch2)<<endl;//////////////////明文输入并整理完毕/////////////////////////////// for(k=0;k<strlen(ch2);k+=2){int m1,m2,n1,n2;for(m1=0;m1<=4;m1++){for(n1=0;n1<=4;n1++){if(ch2[k]==ch[m1][n1])break;}if(ch2[k]==ch[m1][n1])break;}for(m2=0;m2<=4;m2++){for(n2=0;n2<=4;n2++){if(ch2[k+1]==ch[m2][n2])break;}if(ch2[k+1]==ch[m2][n2])break;}m1=m1%5;m2=m2%5;if(n1>4){n1=n1%5;m1=m1+1;}if(n2>4){n2=n2%5;m2=m2+1;}if(m1==m2){ch2[k]=ch[m1][(n1+1)%5];ch2[k+1]=ch[m2][(n2+1)%5];}else{if(n1==n2){ch2[k]=ch[(m1+1)%5][n1];ch2[k+1]=ch[(m2+1)%5][n2];}else{ch2[k]=ch[m1][n2];ch2[k+1]=ch[m2][n1];}}}cout<<"加密后所得到的密文是:";for(k=0;k<strlen(ch2);k+=2)cout<<ch2[k]<<ch2[k+1]<<" ";cout<<endl;}else break;}}//解密算法void decrypt(){int i,k;const int N=100;char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//标记字母是否已在矩阵中,与letters数组对应char ch[5][5];//5X5矩阵char ch1[N];//密钥char ch2[N];//密文int len='a'-'A';int flg=1;cout<<"输入密钥:";cin>>ch1;while(flg==1){for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母{if(ch1[i]>'z'||ch1[i]<'a'){cout<<"请重新选择操作:"<<endl;flg=0;break;}elsech1[i]=ch1[i]-len;}if(flg==1){ for(i=0;i<strlen(ch1);i++)//把密钥中的J都变为I{if(ch1[i]=='J')ch1[i]='I';}i=0;int j=0;//把密钥中的字母填入到矩阵中,并把该字母标记为已用for(int k=0;k<strlen(ch1);k++){for( int t=0;t<25;t++){if(ch1[k]==letters[t]&&flag[t]==0){ch[i][j]=letters[t];flag[t]=1;if(j<4)j++;else {i++;j=0;}}}}for( k=0;k<25;k++)//按字母表顺序把未用字母依次填入到矩阵中{if(flag[k]==0){ch[i][j]=letters[k];flag[k]=1;if(j<4)j++;else{i++;j=0;}}}cout<<"密钥填充后的矩阵为:"<<endl;for(i=0;i<5;i++)for(j=0;j<5;j++){cout<<ch[i][j];cout<<" ";if(j==4)cout<<endl;}cout<<endl;/////////////////////矩阵生成完毕////////////////////////////int f=0;do{cout<<"请输入密文(英文字符):";cin>>ch2;for(int k=0;k<strlen(ch2);k++)//把所输入的密文转化为大写字母{if(ch2[k]>='a')ch2[k]=ch2[k]-len;}for( k=0;k<strlen(ch2);k++)//把密文中的J都变为I{if(ch2[k]=='J')ch2[k]='I';}for( k=0;k<strlen(ch2);k+=2){if(ch2[k]==ch2[k+1]){cout<<"同一分组中不能出现相同字符!请重新输入。