其他分享
首页 > 其他分享> > 单表代替密码

单表代替密码

作者:互联网

凯撒密码

Caser密码是古典加密的一种,由Julius Caser发明,当时发明的那种就是将26个英文字母按字母表循环移位,按顺序依次a -> d , b -> e , c -> f......根据移位不同统称为移位密码。

按照密码体制五元组

P = { a,b,c......z }
C = { a,b,c......z }
K = { 0,1,2......25 }
若是Caser密码,得到加密算法
E p = ( p + 3 ) mod 26
若移位可以是任意整数,得到加密算法
E p = ( p + k ) mod 26
得到解密算法
D c = ( c - k ) mod 26
注:mod为模算数即取余
因为密钥空间只可能有26种,而至多测试25种即能获得k,用穷举攻击是很容易实现的。

单表代替密码

若移位密码的密钥空间允许任意代替,则能得到26!种可能密钥,成为单表代替密码,急剧增大了密钥空间,可以抵挡穷举攻击,但由于语言使用的一些统计学规律仍然可以进行破解攻击。

字母频率分析解密

以英文为例,首先要把所有英文字母使用相对频率统计出来,和给定的密文的字母频率进行比较,但这种方法需要保证已知密文足够长,且在一些近似频率字母之间需要人为分析结果。
已知英文字母表单字母替换出现频率较高的五位为e、t、a、o、i。

C语言实现

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void Encrypt(int key, char infilename[], char outfilename[]);//加密函数
void Decrypt(int key, char infilename[], char outfilename[]);//解密函数
void frequency(char infilename[], char outfilename[]);//频率分析解密函数
int Character(char);//字符判断函数

int main(int argc, char *argv[]){
    if (argc != 5 || argv[1][0] != '-' || argv[1][2] != '\0'){
        printf("Usage: exename -e/-d key inputfile outputfile\nno key Usage: exename -d no inputfile outputfile");
        return;
    }
    int key = atoi(argv[2]);//密钥
    if (key == 0 ){
        if(argv[1][1] != 'd'){
            printf("Usage: exename -e/-d key inputfile outputfile\nno key Usage: exename -d no inputfile outputfile");
        }else{
            frequency(argv[3], argv[4]);
        }
    }else{
        if (key <0 || key >25) { //判断密钥合法性
            printf("The key is wrong!\n");
            return;
        }
        switch (argv[1][1]){
            case 'e':
                Encrypt(key, argv[3], argv[4]);
                break;
            case 'd':
                Decrypt(key, argv[3], argv[4]);
                break;
            default:
                break;
        }
    }
    return;
}

void Encrypt(int key, char infilename[], char outfilename[]){
    char plaintext[1000] = { 0 };//定义明文数组
    FILE *fp = NULL;//定义文件指针
    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(infilename, "r");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(plaintext, 999, fp);
    }else{//非文本文件
        fp = fopen(infilename, "rb");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(plaintext, 999, fp);//读取文件中的明文存放到数组中
    }
    fclose(fp);
    int pl = strlen(plaintext);//明文长度

    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(outfilename, "w");
    }else{//非文本文件
        fp = fopen(outfilename, "wb");
    }
    int i,value;
    for (i = 0; i < pl; i++){
        value = Character(plaintext[i]);
        if (value == -1) fprintf(fp, "%c", (plaintext[i] - 'a' + key) % 26 + 'a');
        if (value == 1)  fprintf(fp, "%c", (plaintext[i] - 'A' + key) % 26 + 'A');
        if (value == 0 || value == 255) fprintf(fp, "%c", plaintext[i]);
    }//通过移位加密原理输出密文
    fclose(fp);
    printf("The file is encrypt successful.\n");
}

void Decrypt(int key, char infilename[], char outfilename[]){
    char ciphertext[1000] = { 0 };//定义密文
    FILE *fp = NULL;//定义文件指针
    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(infilename, "r");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(ciphertext, 999, fp);
    }
    else{//非文本文件
        fp = fopen(infilename, "rb");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(ciphertext, 999, fp);
    }
    fclose(fp);
    int cl = strlen(ciphertext);//密文长度

    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(outfilename, "w");
    }
    else{//非文本文件
        fp = fopen(outfilename, "wb");
    }
    int i,value;
    for (i = 0; i < cl; i++){
        value = Character(ciphertext[i]);
        if (value == -1)fprintf(fp, "%c", (ciphertext[i] - 'a' - key + 26) % 26 + 'a');
        if (value == 1) fprintf(fp, "%c", (ciphertext[i] - 'A' - key + 26) % 26 + 'A');
        if (value == 0 || value == 255) fprintf(fp, "%c", ciphertext[i]);
    }//通过移位解密原理输出明文
    fclose(fp);
    printf("The file is decrypt successful.\n");
}

void frequency(char infilename[], char outfilename[]){
    char ciphertext[1000] = { 0 };//定义密文
    FILE *fp = NULL;//定义文件指针
    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(infilename, "r");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(ciphertext, 999, fp);
    }
    else{//非文本文件
        fp = fopen(infilename, "rb");
        if (fp == NULL) {
            printf("The file was not found!\n");
            return;
        }
        fgets(ciphertext, 999, fp);
    }
    fclose(fp);
    int cl = strlen(ciphertext);//密文长度

    int i, value, a[26] = { 0 };
    for (i = 0; i < cl; i++){
        value = Character(ciphertext[i]);
        if (value == -1) { a[ciphertext[i] - 'a']++; }
        else if (value == 1) { a[ciphertext[i] - 'A']++; }
    }//将每个字母出现的次数存放到a数组中

    int max, e;
    for (i = 0, max = 0; i<26; i++){
        if (a[i] > max) {
            max = a[i];
            e = i;
        }
    }//找到频率最高的字母即为e
    int key = (e + 22) % 26;//求出密钥值

    if (strchr(infilename, '.txt') != NULL){//文本文件
        fp = fopen(outfilename, "w");
    }
    else{//非文本文件
        fp = fopen(outfilename, "wb");
    }
    for (i = 0; i < cl; i++){
        value = Character(ciphertext[i]);
        if (value == -1)fprintf(fp, "%c", (ciphertext[i] - 'a' - key + 26) % 26 + 'a');
        if (value == 1) fprintf(fp, "%c", (ciphertext[i] - 'A' - key + 26) % 26 + 'A');
        if (value == 0 || value == 255) fprintf(fp, "%c", ciphertext[i]);
    }//通过字母频率分析解密原理输出明文
    fclose(fp);
    printf("The file is decrypt successful.\n");

}

int Character(char n){
    if (n >= 'a'&&n <= 'z') {
        return -1;//小写
    }
    else if (n >= 'A'&&n <= 'Z') {
        return 1;//大写
    }
    else if (n == ' '){
        return 0;//空格
    }
    else{
        return 255;//其它字符
    }
}

标签:fp,ciphertext,infilename,26,value,密码,代替,单表,key
来源: https://www.cnblogs.com/saltedcorgi/p/12034449.html