首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

J2ME/MIDP 應用安全實戰:基於 Bouncy Castle 的 XML 數字簽名端到端實現

     編輯:Java 相關知識

背景:無線 Web 服務的安全缺口

無線通信易遭竊聽,設備算力弱難支撐強加密;Web 服務運行於防火牆外,面臨多中間節點篡改風險。SSL/TLS 僅保護點對點鏈路,**XML 數字簽名 (XML-DSig) 保護訊息內容本身**,實現真正的端到端完整性與不可抵賴性。

核心原理:PKI + 摘要 + 簽名

  1. 發送方擁有**私鑰**,接收方持有對應**公鑰**。
  2. 發送方計算消息**摘要**(SHA-1,固定長度、單向、快速)。
  3. 私鑰加密摘要 → **數字簽名**。
  4. 發送:原文 + 摘要 + 簽名 + 公鑰參數(封裝為 XML-DSig 格式)。
  5. 接收方:驗證摘要匹配 → 用公鑰解密簽名比對 → 通過則消息未被篡改且確由持私鑰者發送。

Bouncy Castle:J2ME 上唯一的純 Java 密碼庫

  • 輕量級、開源、支持 J2SE/J2ME/MIDP 全平台。
  • 實現 JCE 1.2.1 接口,提供 DSA、ECDSA、RSA 等算法。
  • **痛點**:文檔極缺,類層次多態複雜,需閱讀源碼/測試用例上手。

三大算法在 MIDP 上的性能實測

算法密鑰長度驗證耗時 (Palm VII, 16MHz)工程可行性
RSA1024-bit~1 分鐘**勉強可用**,需後台線程避免 UI 凍結
DSA1024-bit> 1 小時不可接受
ECDSA192-bit> 1 小時不可接受

**結論**:MIDP 設備上**僅 RSA 勉強可用**,且必須異步處理。DSA/ECDSA 純 Java 實現大整數運算太慢。未來需 JVM 原生優化或硬件加速支持。

完整流程:服務端簽名 → 客戶端驗證

1. 密鑰生成 (離線/服務端)

// RSA 示例
SecureRandom sr = new SecureRandom();
RSAKeyGenerationParameters params = new RSAKeyGenerationParameters(
    new BigInteger("11", 16), sr, 1024, 80); // 公鑰指數 0x11
RSAKeyPairGenerator gen = new RSAKeyPairGenerator();
gen.init(params);
AsymmetricCipherKeyPair pair = gen.generateKeyPair();
RSAPrivateCrtKeyParameters priv = (RSAPrivateCrtKeyParameters) pair.getPrivate();
RSAKeyParameters pub = (RSAKeyParameters) pair.getPublic();
// 提取參數:Modulus (N), PublicExponent (e)

2. 服務端簽名 (JSP/Servlet)

// 摘要
SHA1Digest dig = new SHA1Digest();
dig.update(msgBytes, 0, msgBytes.length);
byte[] digest = new byte[dig.getDigestSize()];
dig.doFinal(digest, 0);
String digestB64 = Base64.encode(digest);

// 簽名 (PSS 填充)
RSAEngine rsaEng = new RSAEngine();
PSSSigner signer = new PSSSigner(rsaEng, dig, 64); // salt 長度 64
signer.init(true, priv);
byte[] sig = signer.generateSignature(msgBytes);
String sigB64 = Base64.encode(sig);

// 嵌入 XML 響應

  Hello World
  
    
      
      digestB64
    
    sigB64
    
      
        modB64
        expB64
      
    
  

3. 客戶端驗證 (MIDP)

// 解析 XML (kXML/NanoXML) 取得:digestB64, sigB64, modB64, expB64
// 1. 重新計算明文摘要,比對 digestB64 → 不匹配直接拒絕
// 2. 重構公鑰
BigInteger modulus = new BigInteger(Base64.decode(modB64));
BigInteger exponent = new BigInteger(Base64.decode(expB64));
RSAKeyParameters pubKey = new RSAKeyParameters(false, modulus, exponent);

// 3. 驗證簽名
SHA1Digest dig = new SHA1Digest();
RSAEngine rsaEng = new RSAEngine();
PSSSigner verifier = new PSSSigner(rsaEng, dig, 64);
verifier.init(false, pubKey);
boolean valid = verifier.verifySignature(msgBytes, Base64.decode(sigB64));

DSA/ECDSA 代碼結構對比(僅參考,不建議 MIDP 使用)

  • **DSA**:參數 `p, q, g` + 公鑰 `y`;名由 `r, s` 兩大整數組成;`DSASigner` 驗證。
  • **ECDSA**:橢圓曲線參數 `q, a, b, n, G` + 公鑰點 `Q`;簽名同 `r, s`;`ECDSASigner` 驗證。

參數提取/編碼/驗證流程與 RSA 同構,僅類名與參數集不同。

工程落地關鍵點

  1. 異步驗證:MIDP 中必須在後台 `Thread` 執行驗證,`Canvas` 顯示「驗證中...」進度條,完成後回調 UI。
  2. 快取公鑰:同一服務公鑰緩存 `RecordStore`,避免重複解析 Base64/構建 `BigInteger`。
  3. 摘要預檢:先比對摘要,不匹配直接丟棄,阻斷昂貴的公鑰運算(防 DoS)。
  4. 時間戳/Nonce:防重放攻擊,簽名數據中包含時間戳或隨機數,客戶端驗證新鮮度。
  5. 異常處理:Base64 解碼失敗、參數解析異常、算法不支持等全部捕獲並轉為安全拒絕,避免崩潰泄露信息。

未來展望

  • JSR 177 (SATSA) 引入安全元件 API,可將私鑰操作下放到 SIM 卡/安全芯片,解決性能與密鑰存儲安全雙重問題。
  • JVM 內置大整數原生優化(HotSpot Intrinsics)將大幅提升 RSA/DSA/ECDSA 速度。
  • 輕量級簽名算法 (Ed25519, Schnorr) 標準化後或成移動端新寵。

結語

XML 數字簽名為無線 Web 服務提供了**內容級安全**,Bouncy Castle 使其在 MIDP 上成為可能。儘管當前硬件限制下**僅 RSA 勉強可用**,但隨著 JSR 177、JVM 優化落地,端到端簽名將成為移動商業應用標配。建議架構師提前佈局:抽象 `SignatureService` 接口,底層可熱插拔 RSA/國密/硬件加速實現,業務代碼零修改平滑升級。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved