eSIM Profile 派發測試專案

January 2, 2026 · View on GitHub

本專案實作了 GSMA RSP (Remote SIM Provisioning) 規範中的 SM-DP+ 伺服器與 LPA 客戶端測試環境。

eSIM Profile 派發流程概述

根據 GSMA SGP.22 規範,eSIM Profile 的遠端派發涉及以下角色:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   SM-DP+    │     │     LPA     │     │    eUICC    │
│  (伺服器)    │◄───►│   (客戶端)   │◄───►│   (硬體)    │
└─────────────┘     └─────────────┘     └─────────────┘
   Profile           Local Profile       嵌入式
   準備與綁定         Assistant          SIM 晶片

完整的 ES9+ Profile 下載流程

步驟API 名稱方向說明本專案狀態
1InitiateAuthenticationLPA → SM-DP+發送 eUICC 資訊,開始認證✅ 已實作
2(eUICC 處理)LPA ↔ eUICCeUICC 驗證伺服器簽章,產生回應✅ 軟體模擬
3AuthenticateClientLPA → SM-DP+發送 eUICC 簽章,完成雙向認證✅ 軟體模擬
4GetBoundProfilePackageLPA → SM-DP+取得綁定的 Profile 封包✅ 軟體模擬
5(Profile 安裝)LPA ↔ eUICCeUICC 解密並安裝 Profile✅ 模擬完成
6HandleNotificationLPA → SM-DP+通知伺服器安裝結果⚠️ 部分支援

詳細流程說明

步驟 1: InitiateAuthentication ✅

LPA 發送:
├── euiccChallenge    (16 位元組隨機數)
├── euiccInfo1        (eUICC 版本與支援的 CI 公鑰 ID)
└── smdpAddress       (SM-DP+ 伺服器地址)

SM-DP+ 回應:
├── transactionId       (交易識別碼)
├── serverSigned1       (伺服器簽章資料)
├── serverSignature1    (ECDSA 簽章)
├── serverCertificate   (伺服器憑證)
└── euiccCiPKIdToBeUsed (選定的 CI 公鑰 ID)

步驟 2: eUICC 處理 ✅ (軟體模擬)

  • 軟體 eUICC 驗證 serverSignature1 和 serverCertificate
  • 使用測試 PKI 私鑰產生 euiccSigned1
  • 準備 prepareDownloadResponse

步驟 3: AuthenticateClient ✅ (軟體模擬)

  • LPA 發送 euiccSigned1 給 SM-DP+
  • SM-DP+ 驗證 eUICC 身份(憑證鏈驗證通過)
  • 伺服器準備 Profile 綁定

步驟 4: GetBoundProfilePackage ✅ (軟體模擬)

  • LPA 發送 prepareDownloadResponse
  • SM-DP+ 回傳加密的 BoundProfilePackage (約 12KB)
  • Profile 使用 eUICC 特定金鑰加密

步驟 5: Profile 安裝 ✅ (模擬)

  • 模擬 eUICC 接收 BoundProfilePackage
  • 實際安裝需要真實 eUICC 硬體

步驟 6: HandleNotification ⚠️ (部分支援)

  • LPA 通知 SM-DP+ 安裝結果
  • 伺服器端 session 管理限制,回傳 500 錯誤(非關鍵)

專案架構

smdpp/
├── docker-compose.yml      # Docker Compose 設定
├── Dockerfile.smdpp        # SM-DP+ 伺服器 Docker 映像
├── Dockerfile.client       # Go 客戶端 Docker 映像
├── Dockerfile.asn1helper   # ASN.1 Helper 服務映像
├── main.go                 # Go 客戶端程式碼
├── go.mod                  # Go 模組設定
├── asn1_helper.py          # ASN.1 編碼輔助服務
├── scripts/
│   └── gen_full_pki.sh     # PKI 憑證產生腳本
└── README.md               # 本文件

元件說明

SM-DP+ 伺服器 (osmo-smdpp)

  • 基於 Osmocom pySim 專案
  • Python 3.11 實作
  • 支援 ES9+ API (GSMA SGP.22)
  • 包含測試憑證與 Profile

ASN.1 Helper 服務 (asn1_helper.py)

  • Python Flask 服務,監聽 port 9999
  • 使用 pySim 的 rsp.asn1 模組編碼複雜的 ASN.1 結構
  • 動態從 CI 憑證提取 Subject Key Identifier 作為 PKID
  • 提供以下端點:
    • /encode/euiccInfo1 - 編碼 eUICC 資訊
    • /encode/euiccSigned1 - 編碼 eUICC 簽章資料
    • /encode/authenticateServerResponse - 編碼伺服器認證回應
    • /encode/prepareDownloadResponse - 編碼下載準備回應

Go 客戶端 (main.go)

  • 軟體 eUICC 模擬器
  • ECDSA P-256 金鑰產生與簽章
  • 完整 ES9+ 流程實作
  • 支援兩種模式:
    • HTTP 測試模式: 不需硬體,完整模擬 ES9+ 流程
    • 硬體模式: 需要 QMI/MBIM eUICC 設備

PKI 憑證產生 (gen_full_pki.sh)

  • 產生完整的測試 PKI 憑證鏈
  • 支援 GSMA Variant O (nameConstraints)
  • 產生的憑證:
    • CI (Certificate Issuer) 根憑證
    • EUM (eUICC Manufacturer) 中間憑證 (含 nameConstraints)
    • eUICC 終端憑證
    • SM-DP+ DPauth/DPpb 憑證

快速開始

前置作業

首先產生測試 PKI 憑證:

# 產生完整 PKI 憑證鏈
./scripts/gen_full_pki.sh

啟動服務

# 啟動所有服務 (SM-DP+、ASN.1 Helper、Client)
docker compose up

# 只啟動伺服器
docker compose up smdpp asn1-helper

# 重新建置並啟動
docker compose up --build

環境變數

變數說明預設值
HTTP_TEST_MODE1=HTTP 測試模式, 0=硬體模式1
SMDP_HOSTSM-DP+ 伺服器位址smdpp:8443
SMDP_ADDRESSSM-DP+ 邏輯地址testsmdpplus1.example.com
ASN1_HELPER_URLASN.1 Helper 服務位址http://asn1-helper:9999

測試結果範例

軟體模擬模式下的完整 ES9+ 流程輸出:

=== ES9+ Step 1: InitiateAuthentication ===
Response status: 200
Got transactionId: 0C4820EE324046F9BDE1B2991818228B
Got serverSigned1 (272 bytes)
Got serverCertificate

=== ES9+ Step 3: AuthenticateClient ===
Using software eUICC with EID: 89049032123451234512345678901235
Response status: 200
AuthenticateClient success!
Got smdpSigned2 (100 bytes)
Got smdpSignature2 (71 bytes)

=== ES9+ Step 4: GetBoundProfilePackage ===
Response status: 200
Got BoundProfilePackage (12543 bytes)
✓ Profile package received successfully!

=== ES9+ Step 5: Profile Installation (Simulated) ===
In real hardware mode, the profile would be installed to eUICC
Simulating successful installation...

=== ES9+ Step 6: HandleNotification ===
Sending installation notification...
(Server may return 500 due to session management - non-critical)

=== ES9+ Flow Complete ===
All steps executed successfully!

軟體 eUICC 模擬技術

為什麼可以模擬?

本專案透過以下方式繞過真實 eUICC 硬體需求:

  1. 自建 PKI 憑證鏈: 產生完整的 CI → EUM → eUICC 憑證鏈
  2. 軟體金鑰: 使用 ECDSA P-256 軟體金鑰代替硬體安全元件
  3. ASN.1 編碼服務: 正確編碼 SGP.22 規範定義的複雜 ASN.1 結構
  4. 符合 GSMA Variant O: EUM 憑證包含 nameConstraints 擴充

關鍵技術細節

憑證鏈驗證

CI (Certificate Issuer)
├── EUM Certificate (with nameConstraints: IIN=89049032)
│   └── eUICC Certificate (EID: 89049032123451234512345678901235)
└── DPauth/DPpb Certificates (SM-DP+ 使用)

EID 格式

  • 測試 EID: 89049032123451234512345678901235
  • IIN (前 8 碼): 89049032 (須符合 EUM 的 nameConstraints)
  • Luhn 檢查碼: 最後一碼 5

限制說明

雖然可以完成 ES9+ 流程,但有以下限制:

  1. Profile 無法真正安裝: BoundProfilePackage 使用 eUICC 公鑰加密,軟體私鑰無法解密真正的 Profile 內容
  2. 僅適用於測試: 需要伺服器端也使用測試憑證
  3. Step 6 部分問題: osmo-smdpp 的 session 管理導致 HandleNotification 回傳 500

硬體模式

如需完成真正的 Profile 安裝,需要以下硬體之一:

  • QMI 介面的 eUICC 模組 (如 Qualcomm 晶片)
  • MBIM 介面的 eUICC 模組
  • PC/SC 智慧卡讀卡機 + eUICC 卡
# 硬體模式 (需要 /dev/cdc-wdm0 或類似設備)
HTTP_TEST_MODE=0 docker compose up client

相關規範

SM-DP+ 伺服器限制

功能限制

本專案的 smdpp.py 是一個 概念驗證實作,以下是主要限制:

項目狀態說明
ES9+ API✅ 完整支援完整 Profile 下載流程
ES2+ API❌ 缺少無營運商後台介面
SM-DS 整合❌ 缺少無 Discovery Service 整合
Confirmation Code⚠️ 部分未完整實作驗證邏輯
Profile 狀態管理⚠️ 簡化基於檔案/記憶體的 session 儲存
高可用性❌ 缺少無負載平衡或叢集支援

Profile 來源

# Profile 從檔案系統讀取 (簡化實作)
path = os.path.join(self.upp_dir, matchingId) + '.der'
  • 需預先準備 .der 格式的 Unprotected Profile Package (UPP)
  • 無動態 Profile 產生功能
  • 無與電信商 BSS/OSS 系統整合

憑證限制

# 使用固定的測試主機名稱
HOSTNAME = 'testsmdpplus1.example.com'  # 必須與憑證匹配
  • 使用自簽測試憑證,非 GSMA 認證的 CI 憑證
  • 無法與商業 eUICC 互通
  • 僅支援 NIST P-256 和 Brainpool P-256 曲線

適用場景

用途適合度說明
開發測試✅ 非常適合測試 LPA 客戶端實作
PoC 驗證✅ 適合驗證 RSP 協議流程
學習教育✅ 適合理解 SGP.22 規範
小規模內部部署⚠️ 需額外開發需加入 ES2+ 和狀態管理
商業營運部署❌ 不適合缺少必要的營運功能

若需商業部署

商業級 SM-DP+ 需要額外實作:

  1. ES2+ 介面 - 與電信商後台系統整合
  2. SM-DS 整合 - Profile Discovery 服務
  3. HSM 整合 - 硬體安全模組保護金鑰
  4. Profile 庫存管理 - 動態 Profile 分配
  5. 審計日誌 - 合規性記錄
  6. 高可用架構 - 叢集、負載平衡、災難復原
  7. GSMA SAS 認證 - 安全認證標準

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

SM-DP+ HTTP Service

Early proof-of-concept towards a SM-DP+ HTTP service for GSMA consumer eSIM RSP (Remote SIM Provisioning).

GSMA RSP ES 介面總覽

根據 GSMA SGP.21/SGP.22 規範,RSP 架構定義了以下介面:

介面連接端點說明本專案實作
ES1SM-DP+ ↔ Operator (BSS)營運商業務系統與 SM-DP+ 之間的介面,用於 Profile 訂購、管理
ES2+SM-DP+ ↔ OperatorProfile 下載訂單管理、狀態通知
ES3SM-DS ↔ Operator事件註冊、刪除(用於 SM-DS 模式)
ES4SM-SR ↔ OperatorM2M 架構中的 SM-SR 介面(Consumer RSP 不使用)❌ 不適用
ES5SM-SR ↔ eUICCM2M 架構中的遠端管理介面(Consumer RSP 不使用)❌ 不適用
ES6SM-DP ↔ SM-SRM2M 架構中 Profile 傳輸介面(Consumer RSP 不使用)❌ 不適用
ES7SM-DS ↔ SM-DP+SM-DP+ 向 SM-DS 註冊/刪除事件
ES8+SM-DP+ ↔ eUICCProfile 下載、安裝的安全通道(透過 LPA 轉發)⚠️ 部分
ES9+SM-DP+ ↔ LPALPA 與 SM-DP+ 之間的 HTTPS 介面主要實作
ES10aLPA ↔ eUICC (LDS)本地發現服務(Local Discovery Services)❌ LPA 端
ES10bLPA ↔ eUICC (LPD)本地 Profile 下載(Local Profile Download)❌ LPA 端
ES10cLPA ↔ eUICC (LUI)本地使用者介面(Local User Interface)❌ LPA 端
ES11LPA ↔ SM-DSLPA 查詢 SM-DS 取得待處理事件❌ LPA/SM-DS 端
ES12SM-DS ↔ SM-DSRoot SM-DS 與 Alternative SM-DS 之間的介面❌ SM-DS 端

架構說明

┌─────────────┐     ES2+      ┌──────────┐
│  Operator   │◄────────────► │  SM-DP+  │ ◄── 本專案
│   (BSS)     │               │          │
└─────────────┘               └────┬─────┘
                                   │ ES9+ (HTTPS)

                              ┌──────────┐
                              │   LPA    │
                              │ (Device) │
                              └────┬─────┘
                                   │ ES10a/b/c (Local)

                              ┌──────────┐
                              │  eUICC   │
                              └──────────┘

本專案實作的 ES9+ 端點

端點SGP.22 章節說明
/gsma/rsp2/es9plus/initiateAuthentication5.6.1啟動認證流程
/gsma/rsp2/es9plus/authenticateClient5.6.3客戶端(eUICC)認證
/gsma/rsp2/es9plus/getBoundProfilePackage5.6.2取得綁定的 Profile 套件
/gsma/rsp2/es9plus/handleNotification5.6.4處理通知(安裝結果等)
/gsma/rsp2/es9plus/cancelSession5.6.5取消會話

為什麼不需要實作所有介面?

  1. ES4/ES5/ES6 - 這些是 M2M(機器對機器)架構的介面,Consumer RSP 使用不同架構
  2. ES10a/ES10b/ES10c - 這些是 LPA 與 eUICC 之間的本地介面,由設備端實作
  3. ES11/ES12 - 這些是 SM-DS 相關介面,本專案僅實作 SM-DP+
  4. ES1/ES2+/ES3/ES7 - 這些是後端系統整合介面,PoC 階段可簡化

使用方式

# 基本執行
python3 smdpp.py

# 使用 Brainpool 曲線
python3 smdpp.py -b

# 詳細輸出
python3 smdpp.py -v

# 禁用 SSL(開發測試用)
python3 smdpp.py -s

延伸

要讓手機透過掃描 QR Code 新增 eSIM,需要補充以下幾個關鍵服務:

  • QR Code 產生服務 - 產生符合 SGP.22 規範的 Activation Code
  • ES2+ 介面 - 讓營運商系統可以下載訂單、查詢狀態
  • SM-DS 服務(可選) - 如果要支援 SM-DS 模式而非直接 QR Code
  • 公開可存取的 HTTPS 端點 - 手機需要能連到 SM-DP+

必要條件總覽

項目必要性目前狀態說明
QR Code 產生服務✅ 必要❌ 缺少產生 Activation Code
ES2+ 介面✅ 必要❌ 缺少Profile 訂單管理
公網 HTTPS✅ 必要❌ 缺少手機需可存取
有效 TLS 憑證✅ 必要❌ 測試憑證需 CA 簽發
GSMA CI 憑證✅ 必要❌ 測試憑證需 GSMA 認證(最大障礙)
Profile 庫存✅ 必要⚠️ 簡化需真實營運商 Profile
SM-DS 整合⚠️ 可選❌ 缺少Push 模式需要

1. QR Code 產生服務

Activation Code 格式(SGP.22 規範)

LPA:1$<SM-DP+ 地址>$<Matching ID>[$<Confirmation Code Flag>]

範例:

LPA:1$smdp.example.com$K2ABC-XY9HG-L3DEF
欄位說明範例
LPA:1$固定前綴,表示 RSP v2.xLPA:1$
SM-DP+ AddressSM-DP+ 伺服器 FQDNsmdp.example.com
Matching IDProfile 識別碼(與下載訂單關聯)K2ABC-XY9HG-L3DEF
Confirmation Code Flag(可選)是否需要確認碼1 = 需要

2. ES2+ 介面

ES2+ 是營運商後台系統與 SM-DP+ 之間的介面,用於管理 Profile 下載訂單。

必要端點

端點說明優先級
DownloadOrder建立 Profile 下載訂單✅ 必要
ConfirmOrder確認訂單(釋放 Profile)✅ 必要
ReleaseProfile釋放 Profile 供下載✅ 必要
GetProfileStatus查詢 Profile 狀態⚠️ 建議
CancelOrder取消訂單⚠️ 建議

ES2+ 流程

┌──────────┐                    ┌──────────┐
│ Operator │                    │  SM-DP+  │
│  (BSS)   │                    │          │
└────┬─────┘                    └────┬─────┘
     │  1. DownloadOrder             │
     │──────────────────────────────►│
     │  Response (matchingId)        │
     │◄──────────────────────────────│
     │  2. ConfirmOrder              │
     │──────────────────────────────►│
     │  3. 產生 QR Code              │
     │  LPA:1$smdp.example.com$...   │
     │◄──────────────────────────────│

3. 公網 HTTPS 與有效憑證

手機的 LPA 必須能透過網際網路連接到 SM-DP+:

  • 公網 IP 或域名 - SM-DP+ 需有公開可存取的位址
  • 有效 TLS 憑證 - 需由公認 CA 簽發(Let's Encrypt 等)
  • 防火牆設定 - 開放 443 port

4. GSMA 認證 CI 憑證(最大障礙)

這是最大的障礙。真實手機的 eUICC 只信任 GSMA 認證的 CI(Certificate Issuer)簽發的憑證鏈:

GSMA Root CI (手機 eUICC 預載)
    └── SM-DP+ Certificate (需 GSMA 認證)
情況可行性說明
測試憑證 + 真實手機❌ 不可行手機 eUICC 不信任自簽憑證
測試憑證 + 軟體 eUICC✅ 可行本專案目前做法
GSMA 憑證 + 真實手機✅ 可行需通過 SAS 認證

取得 GSMA 認證的途徑

  1. 成為 GSMA 會員 - 加入 GSMA 組織
  2. 通過 SAS 認證 - Security Accreditation Scheme(3-12 個月)
  3. 或與現有 SM-DP+ 供應商合作 - 如 IDEMIA、Thales、G+D 等

實作優先順序建議

階段工作項目時間估計
1公網部署 + TLS 憑證1-2 天
2ES2+ 介面實作2-4 週
3QR Code 產生服務1 週
4GSMA 認證3-12 個月 ⚠️

總結

技術實作(QR Code、ES2+)相對簡單,真正的障礙是取得 GSMA 認證的 CI 憑證

對於非 GSMA 會員,建議:

  • 與現有 SM-DP+ 供應商合作(如 IDEMIA、Thales、G+D、Oasis Smart SIM)
  • 而非自建完整 SM-DP+ 服務

參考規範

  • SGP.21 - RSP Architecture
  • SGP.22 - RSP Technical Specification
  • SGP.26 - RSP Test Specification

License

GNU Affero General Public License v3.0 (AGPL-3.0)