You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX实现的加解密工具运行时Wuerfel类异常无法正常加密

可直接运行的修复方案

核心问题说明

  1. 栅栏密码(Wuerfel)的置换索引数组verschluessler从未被正确赋值,原berechnenVers方法只做了字符计数没有生成置换规则,这是抛出异常的核心原因
  2. 接口要求setzeLosung抛出非法参数异常,但原代码内部捕获了异常导致上层无法感知密钥错误
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 16:15:05