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

RSA加密数据生成QR码扫码后无法解密问题解决指导

问题描述

已完成数据的RSA加密处理,加密后密文生成QR码存储。使用QR扫码器扫描对应QR码时,仅能读取到加密后的密文,无法将密文解密还原为原始明文。

原有加解密功能代码

public class SecureQRcodeWithDigitalSignature {

    private PrivateKey privateKey;
    private PublicKey publicKey;
    public SecureQRcodeWithDigitalSignature () {
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
            generator.initialize(2048);
            KeyPair pair = generator.generateKeyPair();
            privateKey = pair.getPrivate();
            publicKey = pair.getPublic();
        } catch (Exception ignored) {
        }
    }

    public String encrypt(String message) throws Exception{
        byte[] messageToBytes = message.getBytes();
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        byte[] encryptedBytes = cipher.doFinal(messageToBytes);
        return encode(encryptedBytes);
    }
    private String encode(byte[] data){
        return Base64.getEncoder().encodeToString(data);
    }

    public String decrypt(String encryptedMessage) throws Exception{
        byte[] encryptedBytes = decode(encryptedMessage);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE,privateKey);
        byte[] decryptedMessage = cipher.doFinal(encryptedBytes);
        return new String(decryptedMessage,"UTF8");
    }
    private byte[] decode(String data){
        return Base64.getDecoder().decode(data);
    }

    public static void main(String[] args) {
        Scanner message = new Scanner(System.in);
        String data= message.nextLine();
        SecureQRcodeWithDigitalSignature  rsa = new SecureQRcodeWithDigitalSignature ();
        try{
            String encryptedMessage = rsa.encrypt(data);
            String decryptedMessage = rsa.decrypt(encryptedMessage);
            System.err.println("Encrypted:\n"+encryptedMessage);
            System.err.println("Decrypted:\n"+decryptedMessage);
        }catch (Exception ignored){}
    }
}

原有扫码功能代码

public void run (){
    do {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(ScannerQR.class.getName()).log(Level.SEVERE, null, ex);
        }
        Result result = null;
        BufferedImage image = null;
     
        String data = result_field.getText();
        if(webcam.isOpen()){
            if((image = webcam.getImage()) ==null){
                continue;
            }
        }
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap (new HybridBinarizer(source));
      
        try {
            result= new MultiFormatReader().decode(bitmap);
        } catch (NotFoundException ex) {
            Logger.getLogger(ScannerQR.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (result != null){
            SecureQRcodeWithDigitalSignature  b = new SecureQRcodeWithDigitalSignature ();
            result_field.setText(result.getText());
            result_field.setEditable(false);
            plaintext_result.setText(data);
        }
        
    }while(true);
}
核心问题排查
  • 密钥对不匹配:SecureQRcodeWithDigitalSignature的构造函数每次执行都会生成全新的2048位RSA密钥对。生成QR码时加密用的是当时实例的密钥对,扫码时新建实例生成的是完全无关的新密钥,用新密钥的私钥根本解不了旧公钥加密的内容。
  • 未执行解密逻辑:扫码识别到QR码内容后,代码直接把密文设置到了结果框,全程没有调用decrypt()方法做解密处理。虽然创建了加解密类的实例b,但没有调用该实例的任何方法,属于无效代码。
  • 变量取值顺序错误:在还没拿到扫码结果的时候,就提前把result_field的旧值取出来赋值给data变量,后续展示明文用的是这个旧值,根本不是扫到的密文解密后的内容。
  • 异常被空捕获:加解密环节的异常直接被吞掉,没有任何日志输出,出问题时完全无法定位错误点。
修复步骤
  • 持久化RSA密钥对:第一次生成密钥对后,将公钥、私钥通过Base64编码后存储到本地文件或配置项中,加密和解密环节加载同一套密钥,禁止每次实例化都生成新密钥。
  • 补全解密调用逻辑:扫码拿到密文后,加载存储的私钥初始化RSA解密实例,调用decrypt()方法处理密文得到明文。
  • 修正变量取值顺序:拿到result.getText()的密文内容后,再做解密处理,最后把明文赋值给plaintext_result展示。
  • 移除空异常捕获,加解密、扫码环节的异常要打印错误栈,方便排查问题。

修正后的扫码逻辑参考

public void run (){
    // 提前初始化加解密实例,加载持久化存储的同一套密钥对,不要每次扫码都新建实例
    SecureQRcodeWithDigitalSignature rsaProcessor = new SecureQRcodeWithDigitalSignature();
    do {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(ScannerQR.class.getName()).log(Level.SEVERE, null, ex);
        }
        Result result = null;
        BufferedImage image = null;
     
        if(webcam.isOpen()){
            if((image = webcam.getImage()) ==null){
                continue;
            }
        }
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap (new HybridBinarizer(source));
      
        try {
            result= new MultiFormatReader().decode(bitmap);
        } catch (NotFoundException ex) {
            // 未识别到QR码时直接跳过,避免冗余日志
            continue;
        }
        if (result != null){
            String encryptedContent = result.getText();
            result_field.setText(encryptedContent);
            result_field.setEditable(false);
            try {
                // 调用解密方法拿到明文
                String plainContent = rsaProcessor.decrypt(encryptedContent);
                plaintext_result.setText(plainContent);
            } catch (Exception e) {
                Logger.getLogger(ScannerQR.class.getName()).log(Level.SEVERE, "解密失败", e);
                plaintext_result.setText("密文解密失败,请检查密钥是否匹配");
            }
        }
        
    }while(true);
}

注意:RSA 2048位单次最多加密245字节内容,如果要加密更长的明文,建议用RSA加密对称密钥、对称密钥加密明文的混合加密方案,避免密文过长导致QR码容量不足、解密失败。

内容的提问来源于stack exchange,提问作者Hanis Rashid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:09:18