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

iOS端RSA密钥生成与Java端解密异常问题求助

解决iOS RSA加密后Java服务端解密的IllegalBlockSizeException问题

嘿,咱们来解决这个Swift生成RSA密钥后,Java服务端解密报IllegalBlockSizeException: Data must not be longer than 512 bytes的问题。我之前处理过不少跨平台RSA加密解密的不匹配问题,下面一步步拆解可能的原因和解决办法:

核心问题分析

这个报错大概率是以下几个原因之一:

  • 密钥长度不匹配:比如Swift生成的是2048位RSA密钥(加密后密文256字节),但Java端用4096位密钥解密(期望密文512字节),就会触发这个错误;反之亦然。
  • 填充方式不一致:Swift和Java两端必须用完全相同的填充规则(比如PKCS1Padding),否则不仅解密失败,还可能导致块大小校验错误。
  • 公钥格式转换出错:从PKCS1转PKCS8的过程中如果格式损坏,Java无法正确解析密钥,也可能间接引发块大小问题。

步骤1:修正Swift端的密钥生成与加密代码

首先确保你的Swift代码正确生成指定长度的密钥,并且用正确的填充方式加密。以下是基于SwCrypt的修正代码:

import SwCrypt

// 生成2048位RSA密钥对(如果要4096位,改成4096即可,注意对应Java端也要用4096位)
guard let keyPair = try? SwCrypt.RSA.generateKeyPair(size: 2048) else {
    fatalError("生成RSA密钥对失败")
}

// 获取PKCS1格式的PEM公钥
let pkcs1PublicKey = keyPair.publicKeyPEM

// 转换为PKCS8格式(Java原生支持PKCS8,方便解析)
guard let pkcs8PublicKeyData = try? SwCrypt.RSA.convertPublicKeyFromPKCS1ToPKCS8(pemEncoded: pkcs1PublicKey) else {
    fatalError("PKCS1转PKCS8公钥失败")
}
let pkcs8PublicKey = String(data: pkcs8PublicKeyData, encoding: .utf8)!

// 加密明文:注意2048位RSA+PKCS1Padding的最大明文长度是245字节(2048/8 - 11)
let plaintext = "要加密的文本,长度别超过245字节哦"
guard let encryptedData = try? SwCrypt.RSA.encrypt(
    plaintext.data(using: .utf8)!,
    publicKey: pkcs1PublicKey,
    padding: .pkcs1
) else {
    fatalError("加密失败")
}
// 转Base64字符串发送给Java端
let encryptedBase64 = encryptedData.base64EncodedString()

⚠️ 重要提醒:如果要加密超过245字节的长文本,绝对不能直接用RSA加密,必须用混合加密方案:用AES加密明文,再用RSA加密AES密钥,最后把AES密文和加密后的AES密钥一起发送给Java端。


步骤2:修正Java端的解密代码

Java端要确保和Swift端的密钥长度、填充方式完全一致,并且正确解析PKCS8公钥。以下是测试代码:

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;

public class RSADecryptTest {
    public static void main(String[] args) throws Exception {
        // 从iOS接收的PKCS8公钥:去掉PEM头(-----BEGIN PUBLIC KEY-----)、尾(-----END PUBLIC KEY-----)和换行符,只留纯Base64
        String pkcs8PublicKeyBase64 = "替换成你的PKCS8公钥Base64字符串";
        
        // 解析PKCS8公钥
        byte[] publicKeyBytes = Base64.getDecoder().decode(pkcs8PublicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        
        // 从iOS接收的加密后Base64密文
        String encryptedBase64 = "替换成你的加密文本Base64字符串";
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
        
        // 解密:填充方式必须和Swift端一致,这里用RSA/ECB/PKCS1Padding
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        String decryptedText = new String(decryptedBytes, "UTF-8");
        
        System.out.println("解密结果:" + decryptedText);
    }
}

排查验证步骤

如果还是报错,可以按以下步骤排查:

  1. 核对两端密钥长度:Swift生成2048位,Java也要用2048位;如果是4096位,两端都要统一。
  2. 检查公钥格式:Java端必须去掉PKCS8公钥的PEM头、尾和换行符,只保留纯Base64字符串。
  3. 验证密文长度:2048位RSA加密后的密文是256字节(Base64编码后约344字符),4096位是512字节(Base64约688字符),如果密文长度不对,说明Swift端加密有问题。
  4. 确认填充方式:Swift端用.pkcs1,Java端必须用RSA/ECB/PKCS1Padding,不要混用OAEP填充。

内容的提问来源于stack exchange,提问作者Crazy Chef

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:43:03