- 密码学教程
- 密码学 - 首页
- 密码学 - 起源
- 密码学 - 历史
- 密码学 - 原理
- 密码学 - 应用
- 密码学 - 优点与缺点
- 密码学 - 现代
- 密码学 - 传统密码
- 密码学 - 加密的需求
- 密码学 - 双重强度加密
- 密码系统
- 密码系统
- 密码系统 - 组成部分
- 密码系统攻击
- 密码系统 - 彩虹表攻击
- 密码系统 - 字典攻击
- 密码系统 - 暴力攻击
- 密码系统 - 密码分析技术
- 密码学类型
- 密码系统 - 类型
- 公钥加密
- 现代对称密钥加密
- 密码学哈希函数
- 密钥管理
- 密码系统 - 密钥生成
- 密码系统 - 密钥存储
- 密码系统 - 密钥分发
- 密码系统 - 密钥吊销
- 分组密码
- 密码系统 - 流密码
- 密码学 - 分组密码
- 密码学 - Feistel 分组密码
- 分组密码的工作模式
- 分组密码的工作模式
- 电子密码本 (ECB) 模式
- 密码分组链接 (CBC) 模式
- 密码反馈 (CFB) 模式
- 输出反馈 (OFB) 模式
- 计数器 (CTR) 模式
- 经典密码
- 密码学 - 反向密码
- 密码学 - 凯撒密码
- 密码学 - ROT13 算法
- 密码学 - 换位密码
- 密码学 - 加密换位密码
- 密码学 - 解密换位密码
- 密码学 - 乘法密码
- 密码学 - 仿射密码
- 密码学 - 简单替换密码
- 密码学 - 简单替换密码的加密
- 密码学 - 简单替换密码的解密
- 密码学 - 维吉尼亚密码
- 密码学 - 实现维吉尼亚密码
- 现代密码
- Base64 编码和解码
- 密码学 - XOR 加密
- 替换技术
- 密码学 - 单表代换密码
- 密码学 - 破解单表代换密码
- 密码学 - 多表代换密码
- 密码学 - Playfair 密码
- 密码学 - 希尔密码
- 多表代换密码
- 密码学 - 一次性密码本密码
- 一次性密码本密码的实现
- 密码学 - 换位技术
- 密码学 - 栅栏密码
- 密码学 - 列置换密码
- 密码学 -隐写术
- 对称算法
- 密码学 - 数据加密
- 密码学 - 加密算法
- 密码学 - 数据加密标准
- 密码学 - 三重DES
- 密码学 - 双重DES
- 高级加密标准
- 密码学 - AES 结构
- 密码学 - AES 变换函数
- 密码学 - 字节替换变换
- 密码学 - 行移位变换
- 密码学 - 列混合变换
- 密码学 - 轮密钥加变换
- 密码学 - AES 密钥扩展算法
- 密码学 - Blowfish 算法
- 密码学 - SHA 算法
- 密码学 - RC4 算法
- 密码学 - Camellia 加密算法
- 密码学 - ChaCha20 加密算法
- 密码学 - CAST5 加密算法
- 密码学 - SEED 加密算法
- 密码学 - SM4 加密算法
- IDEA - 国际数据加密算法
- 公钥(非对称)密码学算法
- 密码学 - RSA 算法
- 密码学 - RSA 加密
- 密码学 - RSA 解密
- 密码学 - 创建 RSA 密钥
- 密码学 - 破解 RSA 密码
- 密码学 - ECDSA 算法
- 密码学 - DSA 算法
- 密码学 - Diffie-Hellman 算法
- 密码学中的数据完整性
- 密码学中的数据完整性
- 消息认证
- 密码学数字签名
- 公钥基础设施
- 散列
- MD5(消息摘要算法 5)
- SHA-1(安全散列算法 1)
- SHA-256(安全散列算法 256 位)
- SHA-512(安全散列算法 512 位)
- SHA-3(安全散列算法 3)
- 散列密码
- Bcrypt 散列模块
- 现代密码学
- 量子密码学
- 后量子密码学
- 密码协议
- 密码学 - SSL/TLS 协议
- 密码学 - SSH 协议
- 密码学 - IPsec 协议
- 密码学 - PGP 协议
- 图像和文件加密
- 密码学 - 图像
- 密码学 - 文件
- 隐写术 - 图像
- 文件加密和解密
- 密码学 - 文件加密
- 密码学 - 文件解密
- 物联网中的密码学
- 物联网安全挑战、威胁和攻击
- 物联网安全的加密技术
- 物联网设备的通信协议
- 常用的加密技术
- 自定义构建加密算法(混合加密)
- 云密码学
- 量子密码学
- 密码学中的图像隐写术
- DNA 密码学
- 密码学中的一次性密码 (OTP) 算法
- 区别
- 密码学 - MD5 vs SHA1
- 密码学 - RSA vs DSA
- 密码学 - RSA vs Diffie-Hellman
- 密码学 vs 密码学
- 密码学 - 密码学 vs 密码分析
- 密码学 - 经典 vs 量子
- 密码学 vs 隐写术
- 密码学 vs 加密
- 密码学 vs 网络安全
- 密码学 - 流密码 vs 分组密码
- 密码学 - AES vs DES 密码
- 密码学 - 对称 vs 非对称
- 密码学有用资源
- 密码学 - 快速指南
- 密码学 - 讨论
密码学 - 列置换密码
一种以矩阵形式表示明文的换位密码称为列置换密码。将明文按行写入,然后逐列读取密文称为列置换。在本教程中,我们描述了列置换密码的加密和解密方法。列置换可能是研究最多的换位密码。
它是如何工作的?
消息被构造为一个二维数组。消息的长度决定了将有多少行和列。如果消息长 30 个字符(包括空格),则有 50% 的概率会有 15 行 2 列、10 行 3 列、5 行 6 列或 6 行 5 列。
请记住,如果消息长度超过 29,我们必须在消息末尾附加一个虚拟字母。
加密
请参阅下面列置换密码的加密过程:
- 首先,明文按预先定义的行写入,密钥确定长度。
- 可以使用密钥确定明文列的转置顺序。
- 然后通过逐列读取转置后的明文来创建密文。
解密
因此,列置换密码的解密过程如下:
- 使用与加密相同的密钥,首先按列转置密文。
- 可以通过逐行读取转置后的密文来检索明文。
列置换示例
如果消息为“The attack will start on Monday”,那么我们可以看到它有 28 个字符。但是,如果我们在末尾添加虚拟字母“x”和“x”,则消息将为 30 个字符。我们可以计算出 30 = 10 X 3,如果密钥为 (2,3,1),则列排列如下:
明文:“the attack will start on Monday”
密文 - “HAA LSROMDXETCWLTTNOAXT TKI A NY” 是密文,它是根据表格按列读取计算得出的。为了更容易记住密钥,我们对关键字(如“TWO”)的字母进行重新排列,使其按字母顺序排列。因此,数组列将使用密钥 (2,3,1) 进行重新排列。
主要特征
列置换密码的主要特征如下:
- 列置换密码是一种换位密码,它需要在加密之前将明文重新排列成列。
- 由于密钥是对称的,因此它可以用于加密和解密。
- 列置换密码允许使用可变的密钥大小。密钥包含 1 到 N 的整数的排列,其中 N 是明文的长度。
- 密码分析可以破解列置换密码,尤其是在明文具有重复模式或密钥较短的情况下。
列置换密码的用例
- 列置换密码的应用非常广泛,例如数据保护、军事通信和间谍活动。
- 它在明文包含长重复模式(如二进制数据或 DNA 序列)的情况下特别有效。
- 为了提高加密数据的安全性,列置换密码还可以与其他加密技术(如替换密码)结合使用。
实施
现在,我们将使用 Python、Java、C++ 和 Javascript 实现列置换密码。
使用 Python 实现
该代码将演示如何使用 Python 编程语言中的列置换密码加密明文消息,然后将密文解密回明文。
示例
def columnar_encrypt(plaintext, keyword):
matrix = create_encryption_matrix(len(keyword), plaintext)
keyword_sequence = get_keyword_sequence(keyword)
ciphertext = ""
for num in range(len(keyword_sequence)):
pos = keyword_sequence.index(num + 1)
for row in range(len(matrix)):
if len(matrix[row]) > pos:
ciphertext += matrix[row][pos]
return ciphertext
def create_encryption_matrix(width, plaintext):
r = 0
c = 0
matrix = [[]]
for pos, ch in enumerate(plaintext):
matrix[r].append(ch)
c += 1
if c >= width:
c = 0
r += 1
matrix.append([])
return matrix
def get_keyword_sequence(keyword):
sequence = []
for pos, ch in enumerate(keyword):
previous_letters = keyword[:pos]
new_number = 1
for previous_pos, previous_ch in enumerate(previous_letters):
if previous_ch > ch:
sequence[previous_pos] += 1
else:
new_number += 1
sequence.append(new_number)
return sequence
def columnar_decrypt(ciphertext, keyword):
matrix = create_encryption_matrix(len(keyword), ciphertext)
keyword_sequence = get_keyword_sequence(keyword)
plaintext = ""
index = 0
for num in range(len(keyword_sequence)):
pos = keyword_sequence.index(num + 1)
for row in range(len(matrix)):
if len(matrix[row]) > pos:
matrix[row][pos] = ciphertext[index]
index += 1
for row in range(len(matrix)):
for col in range(len(matrix[row])):
plaintext += matrix[row][col]
return plaintext
# Execution of the functions
plaintext = "Tutorialspoint is best"
keyword = "railfence"
ciphertext = columnar_encrypt(plaintext, keyword)
print("The Encrypted Text:", ciphertext)
decrypted_text = columnar_decrypt(ciphertext, keyword)
print("The Decrypted Text:", decrypted_text)
以下是上述示例的输出:
输入/输出
The Encrypted Text: uoelsi s rttisontaiTpb The Decrypted Text: Tutorialspoint is best
使用 Java 实现
现在,我们将使用 Java 编程语言实现列置换密码。我们将使用 Java 的 util 包,该包用于导入 Map 接口和 HashMap 类。代码如下:
示例
import java.util.*;
public class ColumnarCipher {
// Define the Key
static final String encryptionKey = "BEST";
static Map<Character, Integer> keyMap = new HashMap<>();
static void setPermutationOrder() {
// Add the permutation order into the map
for (int i = 0; i < encryptionKey.length(); i++) {
keyMap.put(encryptionKey.charAt(i), i);
}
}
// Encryption Function
static String encrypt(String plaintext) {
int rows, columns;
StringBuilder ciphertext = new StringBuilder();
// Number of columns in the matrix
columns = encryptionKey.length();
// Maximum number of rows in the matrix
rows = (int) Math.ceil((double) plaintext.length() / columns);
char[][] matrix = new char[rows][columns];
for (int i = 0, k = 0; i < rows; i++) {
for (int j = 0; j < columns; ) {
if (k < plaintext.length()) {
char ch = plaintext.charAt(k);
if (Character.isLetter(ch) || ch == ' ') {
matrix[i][j] = ch;
j++;
}
k++;
} else {
/* Add padding character '_' */
matrix[i][j] = '_';
j++;
}
}
}
for (Map.Entry<Character, Integer> entry : keyMap.entrySet()) {
int columnIndex = entry.getValue();
// Get the cipher text
for (int i = 0; i < rows; i++) {
if (Character.isLetter(matrix[i][columnIndex]) || matrix[i][columnIndex] == ' ' || matrix[i][columnIndex] == '_') {
ciphertext.append(matrix[i][columnIndex]);
}
}
}
return ciphertext.toString();
}
// Decryption Function
static String decrypt(String ciphertext) {
int columns = encryptionKey.length();
int rows = (int) Math.ceil((double) ciphertext.length() / columns);
char[][] cipherMat = new char[rows][columns];
// Add characters into the matrix column-wise
int k = 0;
for (int j = 0; j < columns; j++) {
for (int i = 0; i < rows; i++) {
if (k < ciphertext.length()) {
cipherMat[i][j] = ciphertext.charAt(k);
k++;
} else {
cipherMat[i][j] = '_';
}
}
}
// Update the order of the key
int index = 0;
for (Map.Entry<Character, Integer> entry : keyMap.entrySet()) {
entry.setValue(index++);
}
char[][] decCipher = new char[rows][columns];
for (int l = 0; l < encryptionKey.length(); l++) {
int columnIndex = keyMap.get(encryptionKey.charAt(l));
for (int i = 0; i < rows; i++) {
decCipher[i][l] = cipherMat[i][columnIndex];
}
}
// Get the message with the help of the matrix
StringBuilder msg = new StringBuilder();
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (decCipher[i][j] != '_') {
msg.append(decCipher[i][j]);
}
}
}
return msg.toString();
}
public static void main(String[] args) {
/* Plain text message */
String plaintext = "This is a secret message.";
setPermutationOrder();
// Call the encryption function
String ciphertext = encrypt(plaintext);
System.out.println("The Encrypted Message: " + ciphertext);
// Call the Decryption function
System.out.println("The Decrypted Message: " + decrypt(ciphertext));
}
}
以下是上述示例的输出:
输入/输出
The Encrypted Message: T ac s_isseeg_s etse_hi rma_ The Decrypted Message: This is a secret message
使用 C++ 实现
现在,我们将使用相同的概念并在 C++ 中为列置换密码实现代码。请查看下面的代码:
示例
#include<bits/stdc++.h>
using namespace std;
// Encryption key
string const encryptionKey = "BEST";
map<int,int> keyMap;
// Set the permutation order
void setPermutationOrder() {
// Add the permutation order into map
for(int i=0; i < encryptionKey.length(); i++) {
keyMap[encryptionKey[i]] = i;
}
}
// Encryption function
string encrypt(string plaintext) {
int numRows, numCols, j;
string ciphertext = "";
// Calculate the number of columns in the matrix
numCols = encryptionKey.length();
// Calculate the maximum number of rows in the matrix
numRows = plaintext.length() / numCols;
if (plaintext.length() % numCols)
numRows += 1;
char matrix[numRows][numCols];
for (int i=0, k=0; i < numRows; i++){
for (int j=0; j < numCols; ){
if(plaintext[k] == '\0'){
// Add the padding character
matrix[i][j] = '_';
j++;
}
if(isalpha(plaintext[k]) || plaintext[k] == ' '){
// Add only spaces and alphabets
matrix[i][j] = plaintext[k];
j++;
}
k++;
}
}
for (map<int,int>::iterator it = keyMap.begin(); it != keyMap.end(); ++it){
j = it->second;
for (int i = 0; i < numRows; i++){
if(isalpha(matrix[i][j]) || matrix[i][j] == ' ' || matrix[i][j] == '_')
ciphertext += matrix[i][j];
}
}
return ciphertext;
}
// Decryption function
string decrypt(string ciphertext){
// Calculate the row and column
int numCols = encryptionKey.length();
int numRows = ciphertext.length() / numCols;
char cipherMat[numRows][numCols];
// Add characters into the matrix column-wise
for (int j = 0, k = 0; j < numCols; j++)
for (int i = 0; i < numRows; i++)
cipherMat[i][j] = ciphertext[k++];
// Update the order of the key
int index = 0;
for(map<int,int>::iterator it = keyMap.begin(); it != keyMap.end(); ++it)
it->second = index++;
// Arrange the matrix column-wise
char decCipher[numRows][numCols];
map<int,int>::iterator it = keyMap.begin();
int k = 0;
for(int l = 0, j; encryptionKey[l] != '\0'; k++){
j = keyMap[encryptionKey[l++]];
for(int i = 0; i < numRows; i++){
decCipher[i][k] = cipherMat[i][j];
}
}
// Get the plaintext message
string plaintext = "";
for(int i = 0; i < numRows; i++){
for(int j = 0; j < numCols; j++){
if(decCipher[i][j] != '_')
plaintext += decCipher[i][j];
}
}
return plaintext;
}
// Driver program
int main(void){
string plaintext = "I am using Tutorialspoint";
setPermutationOrder();
string ciphertext = encrypt(plaintext);
cout << "The Encrypted Message: " << ciphertext << endl;
cout << "The Decrypted Message: " << decrypt(ciphertext) << endl;
return 0;
}
以下是上述示例的输出:
输入/输出
The Encrypted Message: I nuipt ugtao_as oli_miTrsn_ The Decrypted Message: I am using Tutorialspoint
列置换的安全性
直到 20 世纪上半叶,列置换在全世界范围内被广泛使用。
为了破译密文,攻击者应该尝试制作各种大小的表格,将加密的消息输入到列中,并在每个表格中搜索行中存在的字谜。
优点
与任何加密方法一样,列置换密码也有其自身的优点。
- 列置换密码通过重新排列给定明文中的字符顺序提供基本的安全性。此属性使未经授权的用户难以在不知情密钥的情况下破译。
- 列置换密码算法非常易于实现,因为它需要最少的资源。
- 它支持多种密钥长度,这意味着它允许用户根据其特定需求自定义安全级别。
- 与其他替换密码不同,列置换密码不会保留字符的频率,这使得它对频率分析攻击具有很强的抵抗力。
缺点
尽管有优点,但列置换密码也有一些缺点:
- 列置换密码提供基本的安全性,但容易受到暴力攻击,尤其是在密钥空间有限或选择不佳的情况下。
- 适当的管理对于该保护至关重要,但在大型系统中很难做到。
- 已知明文攻击可以通过揭示加密密钥的详细信息来破坏密码的安全性。
- 尽管列置换密码适用于基本的加密需求,但它无法抵御意志坚定的对手或高级的密码分析技术。
- 此外,当使用明文文本量较大时,其性能会下降,尤其是在使用手动保存方法时,因为矩阵的创建和转换非常复杂。
结论
列置换密码是一种置换密码,在加密前会将明文按列重新排列。它是一种常用的加密技术,易于使用,并且可以有效地用于各种目的,例如数据保护和军事通信。它可以与其他加密技术结合使用,以提高加密数据的安全性,但同时也容易受到密码分析的攻击。因此,选择性地使用列置换密码并采取适当的预防措施以降低其漏洞至关重要。