JavaFX实现的加解密工具运行时Wuerfel类异常无法正常加密
可直接运行的修复方案
核心问题说明
- 栅栏密码(Wuerfel)的置换索引数组
verschluessler从未被正确赋值,原berechnenVers方法只做了字符计数没有生成置换规则,这是抛出异常的核心原因 - 接口要求
setzeLosung抛出非法参数异常,但原代码内部捕获了异常导致上层无法感知密钥错误 - GUI事件处理逻辑存在多处正则使用错误、未判断加密类型就调用Wuerfel方法的问题
修复后Wuerfel类代码
package pis.hue; public class Wuerfel implements Codec { private String schluessel; private int[] verschluessler; public Wuerfel(String schluessel) { setzeLosung(schluessel); } public Wuerfel() { } // 重写置换规则计算逻辑,生成正确的置换索引数组 private void berechnenVers() { int len = schluessel.length(); verschluessler = new int[len]; char[] keyChars = schluessel.toLowerCase().toCharArray(); int order = 0; // 按a-z顺序给密钥每个位置分配置换索引 for (char c = 'a'; c <= 'z'; c++) { for (int i = 0; i < len; i++) { if (keyChars[i] == c) { verschluessler[i] = order++; } } } } @Override public String kodiere(String klartext) { if (schluessel == null || schluessel.isBlank()) { throw new IllegalStateException("密钥未设置"); } int keyLen = schluessel.length(); int rows = (int) Math.ceil((double) klartext.length() / keyLen); char[][] grid = new char[rows][keyLen]; // 填充网格 int index = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < keyLen; j++) { if (index < klartext.length()) { grid[i][j] = klartext.charAt(index++); } else { grid[i][j] = '\0'; // 空白位置填充空字符 } } } // 按置换顺序读取 StringBuilder result = new StringBuilder(); for (int order = 0; order < keyLen; order++) { for (int j = 0; j < keyLen; j++) { if (verschluessler[j] == order) { for (int i = 0; i < rows; i++) { if (grid[i][j] != '\0') { result.append(grid[i][j]); } } break; } } } return result.toString(); } @Override public String dekodiere(String geheimtext) { if (schluessel == null || schluessel.isBlank()) { throw new IllegalStateException("密钥未设置"); } int keyLen = schluessel.length(); int len = geheimtext.length(); int rows = (int) Math.ceil((double) len / keyLen); int fullCols = len % keyLen == 0 ? keyLen : len % keyLen; char[][] grid = new char[rows][keyLen]; // 计算每个列的字符数 int[] colLength = new int[keyLen]; for (int j = 0; j < keyLen; j++) { colLength[j] = (j < fullCols) ? rows : rows - 1; } // 按置换顺序填充网格 int index = 0; for (int order = 0; order < keyLen; order++) { for (int j = 0; j < keyLen; j++) { if (verschluessler[j] == order) { for (int i = 0; i < colLength[j]; i++) { grid[i][j] = geheimtext.charAt(index++); } break; } } } // 按行读取明文 StringBuilder result = new StringBuilder(); for (int i = 0; i < rows; i++) { for (int j = 0; j < keyLen; j++) { if (grid[i][j] != '\0') { result.append(grid[i][j]); } } } return result.toString(); } @Override public String gibLosung() { return schluessel; } @Override public void setzeLosung(String schluessel) throws IllegalArgumentException { // 移除内部异常捕获,符合接口定义 if (schluessel == null || schluessel.isBlank() || !schluessel.matches("[a-zA-Z]+")) { throw new IllegalArgumentException("Nur Buchstaben von a-z und A-Z"); } this.schluessel = schluessel; berechnenVers(); } }
修复后GUI的handle方法代码
@Override public void handle(ActionEvent event) { String klartext = eingabetext.getText(); String lwuerfel1 = losung1.getText(); String lwuerfel2 = losung2.getText(); // 只在选择Würfel加密时执行相关逻辑 if (auswahl.getSelectionModel().isSelected(1)) { try { wuerfel1.setzeLosung(lwuerfel1); if (event.getSource() == codierer) { // 修复正则匹配,支持任意长度字母字符串 if (klartext.matches("[a-zA-Z]+")) { String encrypted = wuerfel1.kodiere(klartext); // 第二个密钥不为空时二次加密 if (!lwuerfel2.isBlank() && lwuerfel2.matches("[a-zA-Z]+")) { wuerfel2.setzeLosung(lwuerfel2); encrypted = wuerfel2.kodiere(encrypted); } eingabetext.setText(encrypted); } else { new Alert(Alert.AlertType.ERROR, "明文只能包含字母").show(); } } else if (event.getSource() == decodierer) { // 解密逻辑,二次加密的话要先解第二个密钥 String decrypted = klartext; if (!lwuerfel2.isBlank() && lwuerfel2.matches("[a-zA-Z]+")) { wuerfel2.setzeLosung(lwuerfel2); decrypted = wuerfel2.dekodiere(decrypted); } decrypted = wuerfel1.dekodiere(decrypted); eingabetext.setText(decrypted); } } catch (IllegalArgumentException e) { new Alert(Alert.AlertType.ERROR, e.getMessage()).show(); } } }
其他优化建议
- 增加凯撒加密逻辑的实现,补全ComboBox选择凯撒后的处理逻辑
- 给加解密操作增加加载提示,避免长文本处理时界面无响应
- 增加密文合法性校验,避免解密时传入非加密文本导致异常
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

