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

以 Kerberos 保障 J2ME 應用程式安全:第 3 部分 (上) — 建立與電子銀行的安全通訊

     編輯:Java 相關知識

前兩部分已完成 ASN.1 基礎建設與 TGT 請求產生,本文進入 KDC 回應處理、服務票據申請、安全上下文建立 的完整流程,並實作所需的底層 ASN.1 解析與加密輔助方法。

環境準備與 KDC 設定

範例採用 Microsoft KDC (Windows Server)。須於 KDC 設定允許特定用戶 略過預驗證 (padata) 直接請求 TGT,以降低行動裝置運算負擔。詳細設定步驟請參考原始碼包內 readme.txt。

發送 TGT 請求並接收回應

KerberosClient.getTicketResponse() 新增 Datagram 通訊邏輯:

Datagram dg = dc.newDatagram(ticketRequest, ticketRequest.length);
dc.send(dg);
// 接收回應
Datagram resp = dc.newDatagram(700);
dc.receive(resp);
byte[] ticketResponse = new byte[resp.getLength()];
System.arraycopy(resp.getData(), 0, ticketResponse, 0, resp.getLength());

同一方法同時支援 TGT 請求 (msg-type=10) 與服務票據請求 (msg-type=12),透過 kerberosTicket != null 判斷。

ASN.1 回應解析核心工具方法 (ASN1DataTypes)

新增解析端方法:

  • isSequence(byte):檢查 Tag 0x30。
  • getIntegerValue(byte[]):ASN.1 INTEGER (大端序) 轉 J2ME int (最多 4 byte)。
  • isASN1Structure(byte, tagType, tagNumber):比對 Tag 類型與編號。
  • getNumberOfLengthBytes(byte):解析長度欄位佔用位元組數。
  • getLength(byte[], offset):計算指定位移處結構總長度 (含 Tag/Length/Value)。
  • getASN1Structure(byte[], tagType, tagNumber):從序列中擷取指定 Tag 結構。
  • getContents(byte[]):剝離 Tag/Length 回傳純 Value 位元組。

底層加密輔助方法 (KerberosClient)

  • encrypt/decrypt(key, data, iv):Bouncy Castle DES-CBC,IV 可選。
  • getMD5DigestValue(data):Bouncy Castle MD5Digest 計算 16-byte 雜湊。
  • decryptAndVerifyDigest(encData, key):完整解密 EncryptedData (Tag 0=etype, 1=kvno, 2=cipher) 流程:
    1. 驗證 SEQUENCE、提取 etype 必須為 3 (DES-CBC)。
    2. 解密 cipher (OCTET STRING) 取得明文。
    3. 明文結構:8-byte confounder + 16-byte checksum + 實際資料。
    4. 將 checksum 歸零重算 MD5,比對原 checksum 驗證完整性。
    5. 通過則回傳實際資料 (offset 24 之後)。

從票據回應提取票據與金鑰

getTicketAndKey(ticketResponse, decryptionKey) 統一處理 TGT 回應 (App Tag 11) 與服務票據回應 (App Tag 13):

  1. 驗證外層 Application Tag。
  2. 剝離 KDC-REP SEQUENCE,擷取 ticket (Context Tag 5) 與 enc-part (Context Tag 6)。
  3. 呼叫 decryptAndVerifyDigest() 解密 enc-part 獲取 EncKDCRepPart (App Tag 25/26)。
  4. 從 SEQUENCE 中提取 key (Context Tag 0) → EncryptionKey → keyvalue (Context Tag 1) → OCTET STRING 內容,即為會話金鑰或子會話金鑰。
  5. 封裝於 TicketAndKey 物件回傳。

產生服務票據請求 (TGS-REQ)

getTicketResponse() 進入 kerberosTicket != null 分支:

  1. 建構 req-body (Context Tag 4),欄位:kdc-options、realm、sname (目標業務伺服器)、till、nonce、etype。
  2. 計算 req-body SEQUENCE 的 MD5 雜湊作為 cksum (cksumtype=7=RSA-MD5)。
  3. 呼叫 getAuthenticationHeader() 產生 KRB_AP_REQ (App Tag 14),內含 TGT 與以會話金鑰加密的 Authenticator (App Tag 2),Authenticator 含 pvno、crealm、cname、cksum、cusec=0、ctime。
  4. 將 KRB_AP_REQ 包裝為 PA-DATA (padata-type=1, padata-value=OCTET STRING),置入頂層 padata (Context Tag 3)。
  5. 最終組裝 TGS-REQ (App Tag 12) 發送並接收回應。

關鍵輔助方法

  • authorDigestAndEncrypt(key, data):與 decryptAndVerifyDigest 互為逆操作。產生 8-byte confounder、16-byte 零校驗和、填充資料 → 串接 → 計算 MD5 → 回填校驗和 → DES-CBC 加密 → 包裝成 EncryptedData (etype=3, cipher=OCTET STRING)。
  • getChecksumBytes(cksumData, cksumType):建構 Checksum SEQUENCE (cksumtype Tag 0, checksum Tag 1)。
  • getAuthenticationHeader(ticket, realm, name, checksum, key, seqNum):依 seqNum 決定是否包含 subkey/seq-number,完整建構 KRB_AP_REQ。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved