列置换密码

置换密码(Permutation Cipher) 又叫 换位密码(Transposition Cipher) ,其特点就是保持明文的所有字符不变,打乱明文字符的位置和次序。常见的置换密码有两种: 列置换密码 周期置换密码

列置换 的加密过程:

1.将明文M以设定的固定分组宽度m按 写出,即每行有m个字符。若明文不是m的整数倍,用双方提前规定好的方式补充,如空格,得到矩阵 M_{[m\times n]}

2.按1,2,3 ...m的某一置换交换列的位置次序得到新的字符矩阵。

3.按 的顺序依次读出得密文序列C。

解密过程:

1.将密文C按加密过程的分组宽度m按 写出字符矩阵。

2.按加密过程的置换的逆置换的位置次序得到新的字符矩阵。

3.按 的顺序依次读出得明文序列M。

2、流程图

3、编程实现

难点: 如何根据密钥实现列置换和逆置换。

因为主要是学习算法思想,程序用户输入明文分组的固定长度,再输入列置换,得到密文。之后通过求出列置换的逆置换,解密得到明文。

具体代码如下:

#include"ColPermutation.h"
int main() {
	while (1) {
		show();		//菜单界面
		keyDown();	//按键处理
		system("pause");
		system("cls");

        头文件ColPermutation.h  

#pragma once
#include<cstdio>
#include<iostream>
#include<cstring>
#include<Windows.h>
#include<vector>
using namespace std;
void init();
void show();
void keyDown();
void readFile();
void saveFile();
void encrypt();
void decrypt();

         ColPermutation.cpp

#include "ColPermutation.h"
string fileStr = "";
string finalStr = "";
void init()//初始化
	fileStr = "";
	finalStr = "";
void show()
	cout << "***************列置换密码***************" << endl;
	cout << "\t\t1.加密文件" << endl;
	cout << "\t\t2.解密文件" << endl;
	cout << "\t\t3.退出" << endl;
	cout << "******************************************" << endl;
void keyDown()//按键处理
	int userkey = 0;
	cin >> userkey;
	switch (userkey) {
	case 1:
		cout << "-----------------加密文件-----------------" << endl;
		readFile();
		encrypt();
		saveFile();
		init();
		break;
	case 2:
		cout << "-----------------解密文件-----------------" << endl;
		readFile();
		decrypt();
		saveFile();
		init();
		break;
	case 3:
		exit(0);
		break;
void readFile()//读取文件
	cout << "请输入文件名:" << endl;
	string fileName;
	cin >> fileName;
	FILE* fp = fopen(fileName.c_str(), "r+");
	if (fp == nullptr) {
		cout << "未找到相关文件" << endl;
		return;
	else {
		cout << "成功打开文件" << endl;
	char ch;
	int pos = 0;
	while ((ch = fgetc(fp)) != EOF) {
		fileStr += ch;
	cout << endl << "待处理的文件为:" << endl;
	cout << fileStr << endl;
	fclose(fp);
void saveFile()//保存文件
	string fileName;
	cout << endl << "请输入要保存信息的文件名:" << endl;
	cin >> fileName;
	FILE* fp = fopen(fileName.c_str(), "w+");
	if (fp == nullptr) {
		cout << endl << "保存文件失败" << endl;
		return;
	else {
		cout << endl << "保存成功" << endl;
	fprintf(fp, "%s", finalStr.c_str());
	fclose(fp);
void encrypt()//加密文件
	cout << endl << "请输入密钥:(固定长度和列置换)" << endl;
	cout << "请输入固定长度:" << endl;
	int length = 0;
	cin >> length;
	int col = fileStr.size() / length + (fileStr.size() % length != 0);//每列的长度
	cout << "明文矩阵为:" << endl;
	for (int i = 0; i < fileStr.size(); i++) {
		if (i != 0 && i % length == 0)cout << endl;
		cout << fileStr[i] << " ";//明文矩阵
	cout << endl;
	vector<string> c;//存放明文的数组
	int pos = 0;
	for (int i = 0; i < length; i++) {
		int pos = i;
		string temp = "";
		while (pos < fileStr.size()) {
			temp += fileStr[pos];
			pos += 6;
		if (temp.size() != col)temp += ' ';
		c.push_back(temp);//按列存入数组中
	int* key = new int[length + 1]();//存放列置换 key[目标列]=源列
	while (1) {
		cout << "请输入一组列置换:" << endl;
		string temp = "";
		cin >> temp;//列置换字符串// 143或者56
		//求key
		//(1 4 3)(5 6)
		//key[1]=4  key[2]=2  key[3]=1  key[4]=3  key[5]=6 key[6]=5
		for (int i = 0; i < temp.size(); i++) {
			if (i == temp.size() - 1) {
				key[temp[i] - '0'] = temp[0] - '0';
			else key[temp[i] - '0'] = temp[i + 1] - '0';
		//继续输出还是退出
		char ch = '\0';
		cout << "是否继续输入列置换(y/n)?" << endl;
		cin >> ch; if (ch == 'n')break;
	for (int i = 1; i <= length; i++) {
		if (key[i] == 0) {
			key[i] = i;//不移动的列序号
		//cout << i << " " << key[i] << endl;
	cout << endl << "按下任意键进行加密" << endl;
	char ch = getchar(); ch = getchar();
	for (int i = 1; i <= length; i++) {
		finalStr += c[key[i] - 1];
	cout << "密文矩阵为:" << endl;
	for (int i = 0; i < col; i++) {
		for (int j = 1; j <= length; j++) {
			cout << c[key[j] - 1][i] << " ";
		cout << endl;
	cout << endl << "得到的密文为:" << endl;
	cout << finalStr << endl;
void decrypt()//解密文件
	cout << endl << "请输入密钥:(固定长度和列置换)" << endl;
	cout << "请输入固定长度:" << endl;
	int length = 0;
	cin >> length;
	int col = fileStr.size() / length + (fileStr.size() % length != 0);//每列的长度
	cout << "密文矩阵为:" << endl;
	for (int i = 0; i < col; i++) {
		int pos = i;
		for (int j = i; j < fileStr.size(); j += col) {
			cout << fileStr[j] << " ";
		cout << endl;
	vector<string> antic;//存放密文的数组
	for (int i = 0; i < fileStr.size();) {
		antic.push_back(string(fileStr.begin() + i, fileStr.begin() + i + col));
		i += col;
	int* antikey = new int[length + 1]();//存放列置换 key[目标列]=源列
	while (1) {
		cout << "请输入一组列置换(不是列置换的逆置换):" << endl;
		string temp = "";
		cin >> temp;//列置换字符串// 143和56
		//(1 4 3)(5 6)
		for (int i = 0; i < temp.size(); i++) {
			if (i == 0) {
				antikey[temp[i] - '0'] = temp[temp.size() - 1] - '0';
			else antikey[temp[i] - '0'] = temp[i - 1] - '0';
		//继续输出还是退出
		char ch = '\0';
		cout << "是否继续输入列置换(y/n)?" << endl;
		cin >> ch; if (ch == 'n')break;
	cout << "列置换的逆置换为:" << endl;
	for (int i = 1; i <= length; i++) {
		if (antikey[i] == 0) {
			antikey[i] = i;
		//cout << i << " " << antikey[i] << endl;
	cout << "成功得到列置换的逆置换!" << endl;
	cout << endl << "按下任意键进行解密" << endl;
	char ch = getchar(); ch = getchar();
	cout << "明文矩阵为:" << endl;
	for (int i = 0; i < col; i++) {
		for (int j = 1; j <= length; j++) {
			cout << antic[antikey[j] - 1][i] << " ";
			finalStr += antic[antikey[j] - 1][i];//按行输出的明文
		cout << endl;
	cout << endl << "得到的明文为:" << endl;
	cout << finalStr << endl;

         列置换密码的有很多不同的细节实现,但主要算法思想是一样的,同样和之前一样学习算法思想是最主要的,编程实现可以帮助我们更好的学习和理解。

置换密码/huanweim 置换密码(Permutation Cipher)又叫换位密码(Transposi-tionCipher),它根据一定的规则重新排明文,以便打破明文的结构特性。置换密码的特点是保持明文的所有字符不变,只是利用置换打乱了明文字符的位置和次序。 最常见的置换密码有二种: 置换密码(明文遵照密钥的规程按换位并且按读出序得到密文);周期置换密码(将明文P按固定长度m分组,然后对每组按1,2…,m的某个置换重排位置从而得到密文C)。        置换密码(Permutation Cipher)又叫换位密码(Transposition Cipher),其特点就是保持明文的所有字符不变,打乱明文字符的位置和次序。常见的置换密码有两种:置换密码和周期置换密码。        一、置换加密        将明文字符P以固定的分组宽度m按行写出,构成m x n的矩阵[M]mxn,不够的按双方约定的字符补充,比如空格字符。然... 加密过程 将明文p以设定的固定分组宽度m按行写出,即每行有m个字符;若明文长度不是m的整数倍,则不足部分用双方约定的方式填充,如双方约定用空格代替空缺处字符,不妨设最后得字符矩阵[Mp]n×m 按1,2…,m的某一置换σ交换的位置次序得字符矩阵[Mp]n×m 把矩阵按[Mp]n×m的顺序依次读出得密文序c。 1.要求使用4行*4的双重置换密码,使用行置换:(1,2,3,4)→(2,4,1,3)和置换:(1,2,3,4)→(3,1,2,4) 编写置换密码算法的实现程序,实现加密和解密操作。它将明文中的字母按照给定的顺序安排在一个矩阵中,然后用根据密钥提供的顺序重新组合矩阵中的字母,从而形成密文。其解密过程是根据密钥的字母数作为数,将密文按照、行的顺序写出,再根据由密钥给出的矩阵置换产生新的矩阵,从而恢复明文。置换密码通过改变明文消息各元素的相对位置,但明文消息元素本身的取值或内容形式不变; 重新排明文字母,达到信息加密的目的。与替代密码不同的是,原来明文中的字母同样出现在密文中,只是顺序被打断。古典的置换密码的例子:Rail Fence密码、行置换密码、乘积密码、转子机、隐写术。