替换密码技术【密码学笔记】

概念  

替换密码是基于符号替换的密码技术,以符号的置换来达到掩盖文明信息的目的。

1、单字符单表替换密码技术

单表单字符的含义是对明文中所有的字符都使用一个固定的映射,即:

  • 任何明文加密、密文解密均使用同一个密码表。
  • 明文中相同的字母,必被加密成相同的密文字母。

(1)乘法密码技术

乘法密码技术的密匙是k。k满足gcd(k,n)=1,若n为素数,则有n-2个密匙(k=1是恒等变换,即加密后的密文和明文是一样的,应当舍弃);若n不是素数,则有φ(n)-1个密匙(同样是舍弃了为1的情况)。

解密变换中的 k-1 为 k 对模 n 的逆,满足:

  

所以,在已知密匙的情况下,k-1是可以求出来的。

【例1】

英文字母 n = 26,取密匙 k = 9。

明文:m = a man liberal in his views

密文:c  = a ean vujkxav un lug hukqg

根据k=9,n=26可以求出来k-1为3。

测试代码:

#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;

char encypt(char c) {
    if (c != ' ')
        return (c - 'a') * 9 % 26 + 'a';//未考虑大小写
    return ' ';
}

char decode(char c) {
    if (c != ' ') {
        return (3 * (c - 'a')) % 26 + 'a';//未考虑大小写
    }
    return ' ';
}

void drawMapTable() {
    //未考虑大小写
    for (char cc = 'a'; cc <= 'z'; cc++){
        cout << cc << ": " << encypt(cc) << endl;
    }
}

int main() {
#ifdef LOCAL
    fstream cin("data.in");
#endif // LOCAL

    string s;
    
    getline(cin, s);
    for (int i = 0; i < s.length(); i++) {
        cout << encypt(s[i]);
    }
    cout << endl;
    getline(cin, s);
    for (int i = 0; i < s.length(); i++) {
        cout << decode(s[i]);
    }
    cout << endl;
    drawMapTable();
    return 0;
}
知识兔View Code

(2)加法密码技术

加法密码技术是一种移位替换密码技术。

其实就是循环取余

 【例2】

 凯撒密码,对26个英文字母进行移位替换,取n = 26,k = 3.

#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;

char encypt(char c) {
    if (c != ' ') {
        return ((c - 'a') + 3) % 26 + 'a';
    }
        
    return ' ';
}

char decode(char c) {
    if (c != ' ') {
        return ((c - 'a' - 3 + 26)) % 26 + 'a';
    }
    return ' ';
}

void drawMapTable() {
    //未考虑大小写
    for (char cc = 'a'; cc <= 'z'; cc++){
        cout << cc << ": " << encypt(cc) << endl;
    }
}

int main() {
#ifdef LOCAL
    fstream cin("data.in");
#endif // LOCAL

    string s;
    
    getline(cin, s);
    for (int i = 0; i < s.length(); i++) {
        cout << encypt(s[i]);
    }
    cout << endl;
    getline(cin, s);
    for (int i = 0; i < s.length(); i++) {
        cout << decode(s[i]);
    }
    cout << endl;
    drawMapTable();
    return 0;
}
知识兔View Code
计算机