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

以 Kerberos 保障 J2ME 應用程式安全:第 2 部分 — 產生 Kerberos 票據請求

     編輯:Java 相關知識

承接 第 1 部分 的訊息格式分析,本文進入程式碼實作層面,示範如何在資源受限的 J2ME 環境下,利用 Bouncy Castle 輕量級加密庫與自訂 ASN.1 工具類,完成 Kerberos 客戶端核心類別 的建構與 TGT 請求 (AS-REQ) 的產生。

核心類別架構設計

為平衡程式碼重用與 Kerberos 專用邏輯,採三層類別設計:

  • ASN1DataTypes:純粹的 ASN.1 基礎型別產生器(INTEGER、STRING、SEQUENCE、Tag-Length 編碼等),不含任何 Kerberos 業務邏輯,可供非 Kerberos 專案復用。
  • KerberosKey:實作 Kerberos 規範的 密碼轉金鑰演算法(String-to-Key),輸入密碼、realm、用戶名,輸出 8-byte DES-CBC 金鑰。
  • KerberosClient:繼承 ASN1DataTypes,整合 KerberosKey,實作完整 Kerberos 協定流程(TGT/服務票據請求、回應解析、安全通訊)。

ASN.1 基礎型別產生方法詳解

ASN1DataTypes 提供統一的「Tag-Length-Value」建構流程:

  1. 計算內容位元組數。
  2. 呼叫 getLengthBytes() 產生長度欄位(支援短/長形式)。
  3. 配置標籤位元組(Universal/Application/Context-specific)。
  4. 依序串接 Tag、Length、Value 回傳完整 byte[]。

關鍵方法:

  • getLengthBytes(int):自動判斷短/長形式編碼長度。
  • getIntegerBytes(int):產生 Universal Tag 2 的 INTEGER。
  • getGeneralStringBytes(String)、getOctetStringBytes(byte[])、getBitStringBytes(byte[])、getGeneralizedTimeBytes(byte[]):對應 Universal Tag 27/4/3/24。
  • concatenateBytes(byte[], byte[]):位元組陣列串接工具。
  • getSequenceBytes(byte[]):包裝成 Universal Tag 16 SEQUENCE。
  • getTagAndLengthBytes(int tagType, int tagNumber, byte[]):產生 Application/Context-specific 標籤結構,tagType 為 APPLICATION_TYPE 或 CONTEXT_SPECIFIC。

Kerberos 密碼轉金鑰演算法 (String-to-Key)

Kerberos 規範定義從「密碼 + realm + 用戶名」衍生 DES-CBC 金鑰,防止跨 realm 金鑰重用攻擊。KerberosKey.generateKey() 實作 11 步驟:

  1. 串接 password + realm + username 字串。
  2. ISO-8859-1 編碼為位元組陣列。
  3. 以 0x00 填充至 8 的倍數長度。
  4. 分割為 8-byte 區塊。
  5. 隔區塊反轉位元順序(奇數區塊)。
  6. 所有區塊 XOR 累積成 8-byte 暫存金鑰。
  7. 奇偶校驗修正(每 byte 最低位設為奇數個 1)。
  8. 弱金鑰檢測(DES 弱金鑰表),若命中則與 0xF0 XOR 強化。
  9. 以暫存金鑰為 Key/IV,對步驟 3 的填充資料執行 DES-CBC 加密,取最後一區塊密文作為新金鑰。
  10. 再次奇偶校驗修正。
  11. 再次弱金鑰檢測與強化,最終產出 8-byte Kerberos 金鑰。

加密運算採用 Bouncy Castle DESEngine + CBCBlockCipher,getFinalKey() 示範 CBC 模式下以前一區塊密文為 IV 的鏈式加密。

產生 TGT 請求 (AS-REQ) 完整流程

KerberosClient.getTicketResponse() 依 ASN.1 結構逐欄位建構:

AS-REQ ::= [APPLICATION 10] SEQUENCE {
  pvno [1] INTEGER (5),
  msg-type [2] INTEGER (10),
  req-body [4] KDC-REQ-BODY
}

req-body 子欄位產生順序:

  1. kdc-options:5-byte 全零 BIT STRING(不啟用任何選項)。
  2. cname:PrincipalName = SEQUENCE { name-type [0] INTEGER (NT_PRINCIPAL=1), name-string [1] SEQUENCE OF GeneralString(username) },外層 Context Tag 1。
  3. realm:GeneralString(realmName),Context Tag 2。
  4. sname:PrincipalName,name-type = NT_UNKNOWN(0),name-string = SEQUENCE { "krbtgt", realmName },Context Tag 3。
  5. till:GeneralizedTime("19700101000000Z") 表不指定失效期,Context Tag 5。
  6. nonce:getRandomNumber() 產生 4-byte 隨機整數,Context Tag 7。
  7. etype:SEQUENCE OF INTEGER (3=DES-CBC),Context Tag 8。

最終以 getTagAndLengthBytes(APPLICATION_TYPE, 10, sequenceBytes) 包裝完整 AS-REQ。getRandomNumber() 結合系統時間、種子與用戶資料雜湊,經 KerberosKey.getFinalKey() 混淆產出 4-byte 隨機數。

程式碼封裝與測試

原始碼下載包含:

  • ASN1DataTypes.java、KerberosKey.java、KerberosClient.java 三大核心類。
  • J2MEClientMIDlet.java 簡易測試 MIDlet。
  • ReadMe.txt 建置與執行說明(需引入 Bouncy Castle J2ME 版)。

下一部分將實作 KDC 回應解析、服務票據請求與安全通訊上下文建立。

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