如何基于现有Bash实现的Vigenère加密脚本完成解密功能?
Vigenère密码Bash脚本:从加密扩展到解密
看起来你已经搞定了Vigenère加密的Bash脚本,现在想复用现有代码实现解密功能对吧?其实核心逻辑只需要反向调整一下位移计算,再通过参数区分加密/解密模式就能搞定,不用重新写一套代码。
先把你提供的原脚本补全(看起来最后截断了,我补了合理的加密逻辑):
#!/usr/local/bin/bash # vigenere.sh # Vigenère Cipher Implementation (Encryption Only) a="ABCDEFGHIJKLMNOPQRSTUVWXYZ" # Check for invalid arguments [[ "${*/-d/}" != "" ]] && echo "Usage: $0 [-d]" && exit 1 # 补全的加密核心逻辑 read -p "Enter plaintext: " plaintext read -p "Enter key: " key plaintext=$(echo "$plaintext" | tr '[:lower:]' '[:upper:]') key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | tr -cd '[:upper:]') key_len=${#key} result="" for (( i=0; i<${#plaintext}; i++ )); do char=${plaintext:$i:1} if [[ "$char" =~ [A-Z] ]]; then plain_pos=$(expr index "$a" "$char") key_char=${key:$((i % key_len)):1} key_pos=$(expr index "$a" "$key_char") cipher_pos=$(( (plain_pos + key_pos - 2) % 26 + 1 )) cipher_char=${a:$((cipher_pos - 1)):1} result+="$cipher_char" else result+="$char" fi done echo "Encrypted text: $result"
核心逻辑分析
加密的本质是:明文字母在字母表的位置 + 密钥对应字母的位置,模26后得到密文字母的位置(因为expr index返回的是从1开始的索引,所以要做-2的调整)。
解密的逻辑刚好相反:密文字母的位置 - 密钥对应字母的位置,模26后得到明文字母的位置,这里要注意处理负数的情况(比如密文字母位置比密钥位置小的时候)。
复用代码的改造方案
我把脚本改成支持-d参数切换解密模式,并且把核心转换逻辑抽成函数,避免重复代码:
#!/usr/local/bin/bash # vigenere.sh # Vigenère Cipher Implementation (Encryption + Decryption) a="ABCDEFGHIJKLMNOPQRSTUVWXYZ" # 显示用法提示 show_usage() { echo "Usage: $0 [-d]" echo " Without -d: Encrypt plaintext" echo " With -d: Decrypt ciphertext" exit 1 } # 判断运行模式:加密/解密 mode="encrypt" if [[ "$1" == "-d" ]]; then mode="decrypt" shift fi # 检查多余参数 [[ $# -ne 0 ]] && show_usage # 核心字符转换函数:根据模式处理单个字符和密钥字符 transform_char() { local char=$1 local key_char=$2 local mode=$3 local plain_pos=$(expr index "$a" "$char") local key_pos=$(expr index "$a" "$key_char") local result_pos if [[ "$mode" == "encrypt" ]]; then # 加密公式:(明文位置 + 密钥位置 - 2) mod 26 + 1 result_pos=$(( (plain_pos + key_pos - 2) % 26 + 1 )) else # 解密公式:处理负数,确保结果在1-26之间 result_pos=$(( (plain_pos - key_pos) % 26 )) result_pos=$(( result_pos < 0 ? result_pos + 26 : result_pos )) result_pos=$(( result_pos == 0 ? 26 : result_pos )) fi echo "${a:$((result_pos - 1)):1}" } # 获取用户输入 if [[ "$mode" == "encrypt" ]]; then read -p "Enter plaintext to encrypt: " input_text else read -p "Enter ciphertext to decrypt: " input_text fi read -p "Enter key (letters only): " key # 统一格式:转大写,密钥只保留字母 input_text=$(echo "$input_text" | tr '[:lower:]' '[:upper:]') key=$(echo "$key" | tr '[:lower:]' '[:upper:]' | tr -cd '[:upper:]') # 检查密钥合法性 if [[ -z "$key" ]]; then echo "Error: Key cannot be empty or non-alphabetic" exit 1 fi key_len=${#key} result="" # 逐字符处理输入文本 for (( i=0; i<${#input_text}; i++ )); do char=${input_text:$i:1} if [[ "$char" =~ [A-Z] ]]; then key_char=${key:$((i % key_len)):1} transformed_char=$(transform_char "$char" "$key_char" "$mode") result+="$transformed_char" else # 非字母字符直接保留 result+="$char" fi done # 输出结果 if [[ "$mode" == "encrypt" ]]; then echo "Encrypted result: $result" else echo "Decrypted result: $result" fi
关键改造点说明
- 模式切换:通过
-d参数设置解密模式,默认是加密模式,同时增加了参数合法性检查 - 代码复用:把加密和解密的核心字符转换逻辑抽成
transform_char函数,只在函数内部根据模式切换计算方式 - 负数处理:解密时如果密文字母位置减密钥位置得到负数,先加26再取模,确保结果始终是1-26之间的有效索引
- 鲁棒性提升:增加了密钥合法性检查,避免空密钥或非字母密钥的情况
使用方法
- 加密:直接运行
./vigenere.sh,输入明文和密钥即可 - 解密:运行
./vigenere.sh -d,输入密文和密钥即可
内容的提问来源于stack exchange,提问作者Neo1234
相关产品推荐
相关产品推荐

