- 密碼學教程
- 密碼學 - 首頁
- 密碼學 - 起源
- 密碼學 - 歷史
- 密碼學 - 原理
- 密碼學 - 應用
- 密碼學 - 優點與缺點
- 密碼學 - 現代
- 密碼學 - 傳統密碼
- 密碼學 - 加密的需求
- 密碼學 - 雙重強度加密
- 密碼系統
- 密碼系統
- 密碼系統 - 組成部分
- 密碼系統攻擊
- 密碼系統 - 彩虹表攻擊
- 密碼系統 - 字典攻擊
- 密碼系統 - 暴力攻擊
- 密碼系統 - 密碼分析技術
- 密碼學型別
- 密碼系統 - 型別
- 公鑰加密
- 現代對稱金鑰加密
- 密碼學雜湊函式
- 金鑰管理
- 密碼系統 - 金鑰生成
- 密碼系統 - 金鑰儲存
- 密碼系統 - 金鑰分發
- 密碼系統 - 金鑰吊銷
- 分組密碼
- 密碼系統 - 流密碼
- 密碼學 - 分組密碼
- 密碼學 - 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 世紀上半葉,列置換在全世界範圍內被廣泛使用。
為了破譯密文,攻擊者應該嘗試製作各種大小的表格,將加密的訊息輸入到列中,並在每個表格中搜索行中存在的字謎。
優點
與任何加密方法一樣,列置換密碼也有其自身的優點。
- 列置換密碼透過重新排列給定明文中的字元順序提供基本的安全性。此屬性使未經授權的使用者難以在不知情金鑰的情況下破譯。
- 列置換密碼演算法非常易於實現,因為它需要最少的資源。
- 它支援多種金鑰長度,這意味著它允許使用者根據其特定需求自定義安全級別。
- 與其他替換密碼不同,列置換密碼不會保留字元的頻率,這使得它對頻率分析攻擊具有很強的抵抗力。
缺點
儘管有優點,但列置換密碼也有一些缺點:
- 列置換密碼提供基本的安全性,但容易受到暴力攻擊,尤其是在金鑰空間有限或選擇不佳的情況下。
- 適當的管理對於該保護至關重要,但在大型系統中很難做到。
- 已知明文攻擊可以透過揭示加密金鑰的詳細資訊來破壞密碼的安全性。
- 儘管列置換密碼適用於基本的加密需求,但它無法抵禦意志堅定的對手或高階的密碼分析技術。
- 此外,當使用明文文字量較大時,其效能會下降,尤其是在使用手動儲存方法時,因為矩陣的建立和轉換非常複雜。
結論
列置換密碼是一種置換密碼,在加密前會將明文按列重新排列。它是一種常用的加密技術,易於使用,並且可以有效地用於各種目的,例如資料保護和軍事通訊。它可以與其他加密技術結合使用,以提高加密資料的安全性,但同時也容易受到密碼分析的攻擊。因此,選擇性地使用列置換密碼並採取適當的預防措施以降低其漏洞至關重要。