硬體安全模組 HSM 憑證儲存

Hardware Security Module HSM Certificate Storage

前言

在現代企業資安架構中,保護加密金鑰與數位憑證是最關鍵的任務之一。硬體安全模組(Hardware Security Module,HSM)提供了符合 FIPS 140-2/140-3 標準的硬體級安全保護,確保私鑰永不離開受保護的硬體環境。本文將深入探討 HSM 的概念、主流解決方案,以及如何將 HSM 整合至憑證管理系統中。


1. HSM 概念與用途

什麼是 HSM?

硬體安全模組(HSM)是一種專門設計用於保護和管理加密金鑰的實體裝置。HSM 提供以下核心功能:

  • 金鑰生成:在安全硬體內部生成高品質隨機金鑰
  • 金鑰儲存:將私鑰安全地儲存在防篡改的硬體中
  • 加密運算:在 HSM 內部執行加解密、簽章等運算
  • 存取控制:嚴格的身份驗證與授權機制

HSM 的主要應用場景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
┌─────────────────────────────────────────────────────────────┐
│                    HSM 應用場景                              │
├─────────────────────────────────────────────────────────────┤
│  • PKI / CA 根憑證私鑰保護                                   │
│  • TLS/SSL 憑證私鑰管理                                      │
│  • 程式碼簽章(Code Signing)                                │
│  • 資料庫加密金鑰管理(TDE)                                  │
│  • 支付系統 PCI-DSS 合規                                     │
│  • 區塊鏈錢包金鑰保護                                        │
│  • IoT 裝置身份認證                                          │
└─────────────────────────────────────────────────────────────┘

HSM 安全等級

安全等級FIPS 140-2 Level說明
Level 1基本軟體安全無實體安全要求
Level 2防篡改封條可見的篡改跡象
Level 3防篡改機制主動回應入侵嘗試
Level 4完整實體保護環境攻擊防護

2. PKCS#11 介面標準

PKCS#11 概述

PKCS#11(Cryptoki)是由 RSA Laboratories 制定的加密令牌介面標準,定義了應用程式與加密裝置(如 HSM、智慧卡)之間的通用 API。

PKCS#11 架構

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
┌─────────────────────────────────────────────┐
│           應用程式 (OpenSSL, Java, etc.)     │
└─────────────────────┬───────────────────────┘
                      │ PKCS#11 API
┌─────────────────────▼───────────────────────┐
│           PKCS#11 Library (.so/.dll)         │
└─────────────────────┬───────────────────────┘
┌─────────────────────▼───────────────────────┐
│           HSM 硬體裝置                       │
└─────────────────────────────────────────────┘

基本 PKCS#11 操作

初始化與 Session 管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <pkcs11.h>

// 初始化 PKCS#11 函式庫
CK_RV rv = C_Initialize(NULL);

// 取得可用的 Slot 列表
CK_SLOT_ID slotList[10];
CK_ULONG slotCount = 10;
rv = C_GetSlotList(CK_TRUE, slotList, &slotCount);

// 開啟 Session
CK_SESSION_HANDLE hSession;
rv = C_OpenSession(slotList[0],
                   CKF_SERIAL_SESSION | CKF_RW_SESSION,
                   NULL, NULL, &hSession);

// 登入 HSM
CK_UTF8CHAR pin[] = "UserPIN123";
rv = C_Login(hSession, CKU_USER, pin, sizeof(pin) - 1);

金鑰生成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// RSA 金鑰對生成
CK_MECHANISM mechanism = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
CK_ULONG modulusBits = 2048;
CK_BYTE publicExponent[] = { 0x01, 0x00, 0x01 };  // 65537

CK_ATTRIBUTE publicKeyTemplate[] = {
    { CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits) },
    { CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent) },
    { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
    { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
    { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }
};

CK_ATTRIBUTE privateKeyTemplate[] = {
    { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
    { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
    { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
    { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
    { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
    { CKA_SIGN, &ckTrue, sizeof(ckTrue) }
};

CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
rv = C_GenerateKeyPair(hSession, &mechanism,
                       publicKeyTemplate, 5,
                       privateKeyTemplate, 6,
                       &hPublicKey, &hPrivateKey);

使用 OpenSSL 與 PKCS#11

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 安裝 OpenSSL PKCS#11 engine
sudo apt-get install libengine-pkcs11-openssl

# 設定 OpenSSL 使用 PKCS#11
export PKCS11_MODULE_PATH=/usr/lib/pkcs11/libsofthsm2.so

# 使用 HSM 金鑰進行 CSR 生成
openssl req -new -engine pkcs11 -keyform engine \
    -key "pkcs11:token=mytoken;object=mykey;type=private" \
    -out server.csr \
    -subj "/CN=example.com/O=My Organization/C=TW"

# 使用 HSM 金鑰簽署憑證
openssl x509 -req -engine pkcs11 -keyform engine \
    -in server.csr \
    -CA ca.crt \
    -CAkey "pkcs11:token=mytoken;object=cakey;type=private" \
    -CAcreateserial \
    -out server.crt \
    -days 365

Java 與 PKCS#11 整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.security.*;
import sun.security.pkcs11.SunPKCS11;

public class HSMExample {
    public static void main(String[] args) throws Exception {
        // PKCS#11 設定檔
        String config = "--name=HSM\n" +
                       "library=/usr/lib/pkcs11/libCryptoki2_64.so\n" +
                       "slot=0\n";

        // 載入 PKCS#11 Provider
        Provider provider = Security.getProvider("SunPKCS11");
        provider = provider.configure(config);
        Security.addProvider(provider);

        // 取得 KeyStore
        KeyStore ks = KeyStore.getInstance("PKCS11", provider);
        char[] pin = "UserPIN123".toCharArray();
        ks.load(null, pin);

        // 取得私鑰
        PrivateKey privateKey = (PrivateKey) ks.getKey("mykey", pin);

        // 使用私鑰簽章
        Signature sig = Signature.getInstance("SHA256withRSA", provider);
        sig.initSign(privateKey);
        sig.update("Hello, HSM!".getBytes());
        byte[] signature = sig.sign();

        System.out.println("Signature generated successfully");
    }
}

3. AWS CloudHSM 整合

AWS CloudHSM 概述

AWS CloudHSM 提供雲端託管的 HSM 服務,符合 FIPS 140-2 Level 3 認證。客戶擁有 HSM 的獨佔存取權,AWS 無法存取您的金鑰。

架構圖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
┌──────────────────────────────────────────────────────────────┐
│                        AWS Cloud                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │                       VPC                               │  │
│  │  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐ │  │
│  │  │   EC2/EKS   │────│   CloudHSM  │────│   CloudHSM  │ │  │
│  │  │  Application│    │   Cluster   │    │   (Backup)  │ │  │
│  │  └─────────────┘    └─────────────┘    └─────────────┘ │  │
│  │         │                  │                            │  │
│  │         │           ENI (私有連線)                       │  │
│  │         │                  │                            │  │
│  │  ┌─────────────────────────▼──────────────────────────┐ │  │
│  │  │              CloudHSM Client                        │ │  │
│  │  │         (PKCS#11 / JCE / OpenSSL)                   │ │  │
│  │  └────────────────────────────────────────────────────┘ │  │
│  └────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

部署 CloudHSM Cluster

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 建立 CloudHSM Cluster
aws cloudhsmv2 create-cluster \
    --hsm-type hsm1.medium \
    --subnet-ids subnet-12345678 subnet-87654321 \
    --region ap-northeast-1

# 取得 Cluster 狀態
aws cloudhsmv2 describe-clusters \
    --filters clusterIds=cluster-1234567890abc \
    --query 'Clusters[0].State'

# 初始化 Cluster(需要 CSR)
aws cloudhsmv2 initialize-cluster \
    --cluster-id cluster-1234567890abc \
    --signed-cert file://customerCA.crt \
    --trust-anchor file://customerCA.crt

# 建立 HSM 節點
aws cloudhsmv2 create-hsm \
    --cluster-id cluster-1234567890abc \
    --availability-zone ap-northeast-1a

安裝 CloudHSM Client

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 下載並安裝 CloudHSM Client(Amazon Linux 2)
wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-client-latest.el7.x86_64.rpm
sudo yum install -y ./cloudhsm-client-latest.el7.x86_64.rpm

# 安裝 PKCS#11 函式庫
wget https://s3.amazonaws.com/cloudhsmv2-software/CloudHsmClient/EL7/cloudhsm-pkcs11-latest.el7.x86_64.rpm
sudo yum install -y ./cloudhsm-pkcs11-latest.el7.x86_64.rpm

# 設定 CloudHSM Client
sudo /opt/cloudhsm/bin/configure -a <HSM_IP_ADDRESS>

# 啟動 CloudHSM Client
sudo systemctl start cloudhsm-client
sudo systemctl enable cloudhsm-client

CloudHSM 使用者管理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 登入 CloudHSM Management Utility
/opt/cloudhsm/bin/cloudhsm_mgmt_util /opt/cloudhsm/etc/cloudhsm_mgmt_util.cfg

# 在 cloudhsm_mgmt_util 內執行
aws-cloudhsm> loginHSM PRECO admin password
aws-cloudhsm> changePswd PRECO admin <new_password>

# 建立 Crypto User (CU)
aws-cloudhsm> createUser CU myuser <password>

# 列出使用者
aws-cloudhsm> listUsers

# 登出
aws-cloudhsm> logoutHSM
aws-cloudhsm> quit

使用 CloudHSM 生成金鑰

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 使用 key_mgmt_util 生成 RSA 金鑰對
/opt/cloudhsm/bin/key_mgmt_util

Command: loginHSM -u CU -s myuser -p <password>

# 生成 RSA 2048 金鑰對
Command: genRSAKeyPair -m 2048 -e 65537 -l "my-rsa-key"

# 生成 ECC P-256 金鑰對
Command: genECCKeyPair -i 14 -l "my-ecc-key"

# 列出金鑰
Command: findKey

# 匯出公鑰
Command: exportPubKey -k <key_handle> -out public_key.pem

CloudHSM 與 Nginx 整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# /etc/nginx/nginx.conf
ssl_engine pkcs11;

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/server.crt;

    # 使用 CloudHSM 中的私鑰
    ssl_certificate_key "engine:pkcs11:pkcs11:token=cavium;object=my-rsa-key;type=private";

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;

    location / {
        root /var/www/html;
    }
}

4. Azure Dedicated HSM

Azure Dedicated HSM 概述

Azure Dedicated HSM 提供 Thales Luna Network HSM 7 的單租戶存取,符合 FIPS 140-2 Level 3 認證。

架構設計

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
┌──────────────────────────────────────────────────────────────┐
│                      Azure Cloud                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │                      VNet                               │  │
│  │  ┌─────────────┐         ┌──────────────────────────┐  │  │
│  │  │   AKS/VM    │─────────│    Dedicated HSM         │  │  │
│  │  │  Workloads  │         │    (Luna Network HSM 7)  │  │  │
│  │  └─────────────┘         └──────────────────────────┘  │  │
│  │         │                         │                     │  │
│  │  ┌──────▼─────────────────────────▼─────────────────┐  │  │
│  │  │              Luna Client Library                  │  │  │
│  │  │         (PKCS#11 / JCA / CSP / CNG)              │  │  │
│  │  └──────────────────────────────────────────────────┘  │  │
│  └────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────┘

部署 Azure Dedicated HSM

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 使用 Azure CLI 建立 Dedicated HSM
az dedicated-hsm create \
    --resource-group myResourceGroup \
    --name myDedicatedHSM \
    --location eastus \
    --sku SafeNet Luna Network HSM A790 \
    --stamp-id stamp1 \
    --network-profile-network-interfaces \
        "[{\"privateIpAddress\":\"10.0.0.5\",\"id\":\"/subscriptions/{sub-id}/resourceGroups/myRG/providers/Microsoft.Network/networkInterfaces/myNIC\"}]"

# 查詢 HSM 狀態
az dedicated-hsm show \
    --resource-group myResourceGroup \
    --name myDedicatedHSM

# 列出所有 Dedicated HSM
az dedicated-hsm list --resource-group myResourceGroup

Luna Client 設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 下載並安裝 Luna Client
# (需從 Thales Customer Portal 下載)

# 設定 HSM 連線
/usr/safenet/lunaclient/bin/vtl addServer -n myDedicatedHSM -c server.pem

# 建立 NTLS 連線
/usr/safenet/lunaclient/bin/vtl createCert -n client

# 註冊客戶端
/usr/safenet/lunaclient/bin/vtl addClient -c client.pem

# 驗證連線
/usr/safenet/lunaclient/bin/vtl verify

# 列出可用的 Slot
/usr/safenet/lunaclient/bin/cmu list

Azure Key Vault 與 HSM 整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 建立使用 HSM 支援的 Key Vault
az keyvault create \
    --name myKeyVault \
    --resource-group myResourceGroup \
    --location eastus \
    --sku premium

# 在 HSM 中生成金鑰
az keyvault key create \
    --vault-name myKeyVault \
    --name myHSMKey \
    --kty RSA-HSM \
    --size 2048

# 使用 HSM 金鑰簽署
az keyvault key sign \
    --vault-name myKeyVault \
    --name myHSMKey \
    --algorithm RS256 \
    --value $(echo -n "data to sign" | base64)

5. Thales Luna HSM

Luna Network HSM 概述

Thales Luna Network HSM 是業界領先的網路型 HSM 解決方案,提供最高等級的安全性和效能。

Luna HSM 初始化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 使用 LunaSH 進行 HSM 初始化
lunash:> hsm init -label "Production-HSM"

# 設定 HSM Policy
lunash:> hsm changepolicy -policy 15 -value 1

# 建立 Partition
lunash:> partition create -partition ProductionPartition -domain ProductionDomain

# 設定 Partition Policy
lunash:> partition changepolicy -partition ProductionPartition -policy 0 -value 0

使用 CMU(Certificate Management Utility)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 生成自簽憑證
cmu generatekeypair -slot 0 \
    -keyType RSA \
    -modulusBits 2048 \
    -publicExponent 65537 \
    -labelPublic "CA-Public" \
    -labelPrivate "CA-Private"

# 生成 CSR
cmu requestcertificate -slot 0 \
    -privateKeyLabel "CA-Private" \
    -publicKeyLabel "CA-Public" \
    -outputFile ca.csr \
    -subjectDN "CN=My CA,O=My Organization,C=TW"

# 匯入憑證
cmu importcert -slot 0 \
    -inputFile ca.crt \
    -label "CA-Certificate"

# 列出憑證
cmu list -slot 0 -class certificate

Luna HSM 高可用性設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 設定 HA Group
lunacm:> hagroup creategroup -label ProductionHA

# 新增成員
lunacm:> hagroup addmember -group ProductionHA -serialNumber 123456

# 設定 HA 模式
lunacm:> hagroup setmode -group ProductionHA -mode activeactive

# 驗證 HA 狀態
lunacm:> hagroup listgroups

Python 與 Luna HSM 整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python3
"""
Luna HSM PKCS#11 整合範例
"""

from PyKCS11 import *
import hashlib

# PKCS#11 函式庫路徑
PKCS11_LIB = "/usr/safenet/lunaclient/lib/libCryptoki2_64.so"

def init_pkcs11():
    """初始化 PKCS#11 Session"""
    pkcs11 = PyKCS11Lib()
    pkcs11.load(PKCS11_LIB)

    # 取得 Slot
    slots = pkcs11.getSlotList(tokenPresent=True)
    if not slots:
        raise Exception("No HSM slots found")

    # 開啟 Session
    session = pkcs11.openSession(slots[0], CKF_RW_SESSION)

    # 登入
    session.login("partition_password")

    return pkcs11, session

def generate_rsa_keypair(session, label):
    """在 HSM 中生成 RSA 金鑰對"""
    public_template = [
        (CKA_CLASS, CKO_PUBLIC_KEY),
        (CKA_KEY_TYPE, CKK_RSA),
        (CKA_TOKEN, True),
        (CKA_MODULUS_BITS, 2048),
        (CKA_PUBLIC_EXPONENT, (0x01, 0x00, 0x01)),
        (CKA_ENCRYPT, True),
        (CKA_VERIFY, True),
        (CKA_LABEL, f"{label}-public"),
    ]

    private_template = [
        (CKA_CLASS, CKO_PRIVATE_KEY),
        (CKA_KEY_TYPE, CKK_RSA),
        (CKA_TOKEN, True),
        (CKA_PRIVATE, True),
        (CKA_SENSITIVE, True),
        (CKA_EXTRACTABLE, False),
        (CKA_DECRYPT, True),
        (CKA_SIGN, True),
        (CKA_LABEL, f"{label}-private"),
    ]

    mechanism = Mechanism(CKM_RSA_PKCS_KEY_PAIR_GEN)
    public_key, private_key = session.generateKeyPair(
        public_template, private_template, mechanism
    )

    return public_key, private_key

def sign_data(session, private_key, data):
    """使用 HSM 私鑰簽署資料"""
    mechanism = Mechanism(CKM_SHA256_RSA_PKCS)
    signature = session.sign(private_key, data, mechanism)
    return bytes(signature)

def verify_signature(session, public_key, data, signature):
    """驗證簽章"""
    mechanism = Mechanism(CKM_SHA256_RSA_PKCS)
    try:
        session.verify(public_key, data, signature, mechanism)
        return True
    except:
        return False

if __name__ == "__main__":
    pkcs11, session = init_pkcs11()

    # 生成金鑰對
    pub_key, priv_key = generate_rsa_keypair(session, "test-key")
    print("RSA key pair generated successfully")

    # 簽署資料
    data = b"Hello, Luna HSM!"
    signature = sign_data(session, priv_key, data)
    print(f"Signature: {signature.hex()[:64]}...")

    # 驗證簽章
    is_valid = verify_signature(session, pub_key, data, signature)
    print(f"Signature valid: {is_valid}")

    # 登出並關閉 Session
    session.logout()
    session.closeSession()

6. 與憑證管理系統整合

HashiCorp Vault 與 HSM 整合

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# vault.hcl - Vault 使用 HSM 作為 seal
seal "pkcs11" {
  lib            = "/usr/lib/pkcs11/libsofthsm2.so"
  slot           = "0"
  pin            = "env:VAULT_HSM_PIN"
  key_label      = "vault-seal-key"
  hmac_key_label = "vault-hmac-key"
  generate_key   = "true"
}

storage "raft" {
  path = "/opt/vault/data"
  node_id = "vault-1"
}

listener "tcp" {
  address     = "0.0.0.0:8200"
  tls_disable = false
  tls_cert_file = "/opt/vault/tls/server.crt"
  tls_key_file  = "/opt/vault/tls/server.key"
}

api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 啟動 Vault 並初始化
export VAULT_HSM_PIN="hsm_pin_123"
vault server -config=vault.hcl

# 初始化 Vault(Auto-unseal with HSM)
vault operator init

# 使用 PKI Secrets Engine
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki

# 生成根 CA(金鑰儲存在 HSM 中)
vault write pki/root/generate/internal \
    common_name="Example Root CA" \
    ttl=87600h \
    key_type=rsa \
    key_bits=4096

# 設定 CRL 和 Issuing 端點
vault write pki/config/urls \
    issuing_certificates="https://vault.example.com:8200/v1/pki/ca" \
    crl_distribution_points="https://vault.example.com:8200/v1/pki/crl"

EJBCA 與 HSM 整合

1
2
3
4
5
6
7
8
# conf/web.properties
# HSM 加密 Token 設定
cryptotoken.p11.lib=/usr/lib/pkcs11/libCryptoki2_64.so
cryptotoken.p11.slot=0
cryptotoken.p11.attributesFile=/opt/ejbca/conf/p11ng.cfg

# 啟用 HSM 支援
cryptotoken.hardtoken.library=/usr/lib/pkcs11/libCryptoki2_64.so
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 使用 EJBCA CLI 建立 Crypto Token
ejbca.sh cryptotoken create \
    --token "ProductionHSM" \
    --type "PKCS11CryptoToken" \
    --lib "/usr/lib/pkcs11/libCryptoki2_64.so" \
    --slot "0" \
    --pin "hsm_pin"

# 生成 CA 金鑰對
ejbca.sh cryptotoken generatekeypair \
    --token "ProductionHSM" \
    --keypairalias "rootca" \
    --keyspec "RSA4096"

# 建立 CA
ejbca.sh ca init \
    --caname "Enterprise Root CA" \
    --dn "CN=Enterprise Root CA,O=Example Corp,C=TW" \
    --tokenType "org.cesecore.keys.token.PKCS11CryptoToken" \
    --tokenName "ProductionHSM" \
    --keyspec "RSA4096" \
    --keytype "RSA" \
    --signaturealgorithm "SHA512WithRSA" \
    --validity "7300"

cert-manager 與 HSM 整合(Kubernetes)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# hsm-issuer.yaml
apiVersion: v1
kind: Secret
metadata:
  name: hsm-credentials
  namespace: cert-manager
type: Opaque
data:
  pin: <base64-encoded-pin>
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: hsm-issuer
spec:
  ca:
    secretName: hsm-ca-key-pair
---
# 使用外部 HSM 簽署的 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: hsm-signer-config
  namespace: cert-manager
data:
  pkcs11-config: |
    {
      "library": "/usr/lib/pkcs11/libCryptoki2_64.so",
      "slot": 0,
      "tokenLabel": "ProductionToken",
      "keyLabel": "issuer-key"
    }    
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 部署使用 HSM 簽署憑證的應用程式
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: app-certificate
  namespace: production
spec:
  secretName: app-tls
  duration: 8760h  # 1 year
  renewBefore: 720h  # 30 days
  subject:
    organizations:
      - Example Corp
  isCA: false
  privateKey:
    algorithm: RSA
    size: 2048
  usages:
    - server auth
    - client auth
  dnsNames:
    - app.example.com
    - "*.app.example.com"
  issuerRef:
    name: hsm-issuer
    kind: ClusterIssuer

7. 效能考量與最佳實務

HSM 效能指標

1
2
3
4
5
6
7
8
9
┌────────────────────────────────────────────────────────────────┐
│                    HSM 效能比較表                              │
├──────────────────┬───────────────┬───────────────┬────────────┤
│ 操作類型         │ RSA-2048     │ RSA-4096      │ ECDSA P-256│
├──────────────────┼───────────────┼───────────────┼────────────┤
│ 簽章 (次/秒)     │ 1,000-5,000  │ 200-500       │ 2,000-8,000│
│ 驗證 (次/秒)     │ 10,000+      │ 5,000+        │ 5,000+     │
│ 金鑰生成 (次/秒) │ 10-50        │ 2-10          │ 50-200     │
└──────────────────┴───────────────┴───────────────┴────────────┘

效能最佳化策略

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
#!/usr/bin/env python3
"""
HSM 效能最佳化範例 - 連線池與批次處理
"""

import threading
from queue import Queue
from PyKCS11 import *

class HSMConnectionPool:
    """HSM 連線池管理"""

    def __init__(self, lib_path, slot, pin, pool_size=10):
        self.lib_path = lib_path
        self.slot = slot
        self.pin = pin
        self.pool = Queue(maxsize=pool_size)
        self.pkcs11 = PyKCS11Lib()
        self.pkcs11.load(lib_path)

        # 初始化連線池
        for _ in range(pool_size):
            session = self._create_session()
            self.pool.put(session)

    def _create_session(self):
        """建立新的 HSM Session"""
        slots = self.pkcs11.getSlotList(tokenPresent=True)
        session = self.pkcs11.openSession(slots[self.slot], CKF_RW_SESSION)
        session.login(self.pin)
        return session

    def get_session(self, timeout=30):
        """從連線池取得 Session"""
        return self.pool.get(timeout=timeout)

    def return_session(self, session):
        """歸還 Session 到連線池"""
        self.pool.put(session)

    def close_all(self):
        """關閉所有連線"""
        while not self.pool.empty():
            session = self.pool.get()
            session.logout()
            session.closeSession()

class HSMSessionContext:
    """HSM Session 上下文管理器"""

    def __init__(self, pool):
        self.pool = pool
        self.session = None

    def __enter__(self):
        self.session = self.pool.get_session()
        return self.session

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.pool.return_session(self.session)
        return False

# 使用範例
def sign_with_pool(pool, data, key_label):
    """使用連線池進行簽署操作"""
    with HSMSessionContext(pool) as session:
        # 尋找私鑰
        objects = session.findObjects([
            (CKA_CLASS, CKO_PRIVATE_KEY),
            (CKA_LABEL, key_label)
        ])

        if not objects:
            raise Exception(f"Key not found: {key_label}")

        private_key = objects[0]
        mechanism = Mechanism(CKM_SHA256_RSA_PKCS)
        signature = session.sign(private_key, data, mechanism)

        return bytes(signature)

# 批次簽署範例
def batch_sign(pool, data_list, key_label, num_threads=4):
    """多執行緒批次簽署"""
    results = [None] * len(data_list)

    def worker(index, data):
        results[index] = sign_with_pool(pool, data, key_label)

    threads = []
    for i, data in enumerate(data_list):
        t = threading.Thread(target=worker, args=(i, data))
        threads.append(t)
        t.start()

        # 限制並行執行緒數
        if len(threads) >= num_threads:
            for t in threads:
                t.join()
            threads = []

    # 等待剩餘執行緒完成
    for t in threads:
        t.join()

    return results

最佳實務清單

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# HSM 部署最佳實務檢查清單
deployment_checklist:
  hardware:
    - 使用冗餘 HSM 配置(至少 2 台)
    - 確保 HSM 放置在安全的機房環境
    - 建立 HSM 實體存取控制程序

  network:
    - 使用專用網路 VLAN 隔離 HSM 流量
    - 啟用 TLS 1.3 進行 HSM 通訊
    - 設定防火牆規則限制 HSM 存取來源

  key_management:
    - 實施金鑰分離策略(生產/測試環境)
    - 定期備份 HSM 金鑰至安全位置
    - 建立金鑰輪替程序與時程表

  access_control:
    - 實施最小權限原則
    - 使用 M-of-N 認證機制保護重要操作
    - 定期審核 HSM 使用者權限

  monitoring:
    - 啟用 HSM 稽核日誌
    - 設定效能監控與告警閾值
    - 建立 HSM 異常事件回應程序

  disaster_recovery:
    - 記錄 HSM 配置與還原程序
    - 定期測試 HSM 故障切換
    - 確保備援 HSM 與主要 HSM 同步

監控與告警設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# prometheus-hsm-exporter.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hsm-exporter
spec:
  replicas: 1
  template:
    spec:
      containers:
      - name: hsm-exporter
        image: hsm-exporter:latest
        ports:
        - containerPort: 9101
        env:
        - name: HSM_PKCS11_LIB
          value: "/usr/lib/pkcs11/libCryptoki2_64.so"
        - name: HSM_SLOT
          value: "0"
        volumeMounts:
        - name: pkcs11-lib
          mountPath: /usr/lib/pkcs11
      volumes:
      - name: pkcs11-lib
        hostPath:
          path: /usr/lib/pkcs11
---
# Grafana Alert Rules
groups:
- name: hsm-alerts
  rules:
  - alert: HSMHighLatency
    expr: hsm_operation_duration_seconds{quantile="0.99"} > 0.1
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "HSM operation latency is high"
      description: "P99 latency is {{ $value }}s"

  - alert: HSMConnectionPoolExhausted
    expr: hsm_connection_pool_available == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "HSM connection pool exhausted"

  - alert: HSMAuthenticationFailure
    expr: increase(hsm_authentication_failures_total[5m]) > 5
    labels:
      severity: critical
    annotations:
      summary: "Multiple HSM authentication failures detected"

8. 合規性與稽核

合規標準對照

標準HSM 要求說明
PCI-DSSFIPS 140-2 Level 3+支付卡產業資料安全標準
eIDASCommon Criteria EAL4+歐盟電子簽章法規
HIPAAFIPS 140-2 Level 2+美國醫療資訊保護法
SOC 2 Type II實體安全控制服務組織控制報告
ISO 27001A.10.1 加密控制資訊安全管理系統

稽核日誌設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Luna HSM 稽核日誌設定
lunash:> audit config -parameter auditLevel -value 2
lunash:> audit config -parameter logRotationSize -value 100000
lunash:> audit config -parameter logPath -value /var/log/lunalogs

# 啟用詳細稽核
lunash:> audit config -parameter auditLoggerMask -value 0xFFFFFFFF

# 匯出稽核日誌
lunash:> audit export -file audit_export.log

稽核報告產生

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/env python3
"""
HSM 稽核報告產生器
"""

import json
from datetime import datetime, timedelta
from collections import defaultdict

class HSMAuditReporter:
    """HSM 稽核報告產生器"""

    def __init__(self, log_file):
        self.log_file = log_file
        self.events = []
        self._parse_logs()

    def _parse_logs(self):
        """解析稽核日誌"""
        with open(self.log_file, 'r') as f:
            for line in f:
                event = self._parse_event(line)
                if event:
                    self.events.append(event)

    def _parse_event(self, line):
        """解析單一稽核事件"""
        try:
            parts = line.strip().split('|')
            return {
                'timestamp': datetime.strptime(parts[0], '%Y-%m-%d %H:%M:%S'),
                'event_type': parts[1],
                'user': parts[2],
                'object': parts[3],
                'result': parts[4],
                'details': parts[5] if len(parts) > 5 else ''
            }
        except:
            return None

    def generate_summary(self, start_date, end_date):
        """產生摘要報告"""
        filtered = [e for e in self.events
                   if start_date <= e['timestamp'] <= end_date]

        summary = {
            'period': {
                'start': start_date.isoformat(),
                'end': end_date.isoformat()
            },
            'total_events': len(filtered),
            'events_by_type': defaultdict(int),
            'events_by_user': defaultdict(int),
            'failed_operations': [],
            'key_operations': []
        }

        for event in filtered:
            summary['events_by_type'][event['event_type']] += 1
            summary['events_by_user'][event['user']] += 1

            if event['result'] != 'SUCCESS':
                summary['failed_operations'].append(event)

            if event['event_type'] in ['KEY_GENERATE', 'KEY_DELETE', 'KEY_EXPORT']:
                summary['key_operations'].append(event)

        return summary

    def generate_compliance_report(self):
        """產生合規性報告"""
        report = {
            'generated_at': datetime.now().isoformat(),
            'hsm_info': self._get_hsm_info(),
            'access_control': self._check_access_control(),
            'key_management': self._check_key_management(),
            'audit_integrity': self._verify_audit_integrity(),
            'recommendations': []
        }

        return report

    def _get_hsm_info(self):
        """取得 HSM 資訊"""
        return {
            'model': 'Luna Network HSM 7',
            'firmware_version': '7.8.0',
            'fips_level': 'FIPS 140-2 Level 3',
            'serial_number': 'REDACTED'
        }

    def _check_access_control(self):
        """檢查存取控制"""
        auth_events = [e for e in self.events
                      if e['event_type'] in ['LOGIN', 'LOGOUT', 'AUTH_FAILED']]

        failed_logins = [e for e in auth_events if e['event_type'] == 'AUTH_FAILED']

        return {
            'total_authentications': len(auth_events),
            'failed_attempts': len(failed_logins),
            'unique_users': len(set(e['user'] for e in auth_events)),
            'compliance_status': 'PASS' if len(failed_logins) < 10 else 'REVIEW'
        }

    def _check_key_management(self):
        """檢查金鑰管理"""
        key_events = [e for e in self.events
                     if 'KEY' in e['event_type']]

        exports = [e for e in key_events if e['event_type'] == 'KEY_EXPORT']

        return {
            'total_key_operations': len(key_events),
            'key_exports': len(exports),
            'compliance_status': 'PASS' if len(exports) == 0 else 'REVIEW'
        }

    def _verify_audit_integrity(self):
        """驗證稽核日誌完整性"""
        return {
            'log_entries': len(self.events),
            'integrity_check': 'VERIFIED',
            'missing_sequences': 0
        }

    def export_report(self, output_file, format='json'):
        """匯出報告"""
        report = self.generate_compliance_report()

        with open(output_file, 'w') as f:
            if format == 'json':
                json.dump(report, f, indent=2, default=str)
            else:
                f.write(self._format_text_report(report))

    def _format_text_report(self, report):
        """格式化文字報告"""
        lines = [
            "=" * 60,
            "HSM 合規性稽核報告",
            "=" * 60,
            f"產生時間: {report['generated_at']}",
            "",
            "HSM 資訊:",
            f"  型號: {report['hsm_info']['model']}",
            f"  韌體版本: {report['hsm_info']['firmware_version']}",
            f"  FIPS 等級: {report['hsm_info']['fips_level']}",
            "",
            "存取控制檢查:",
            f"  認證次數: {report['access_control']['total_authentications']}",
            f"  失敗嘗試: {report['access_control']['failed_attempts']}",
            f"  狀態: {report['access_control']['compliance_status']}",
            "",
            "金鑰管理檢查:",
            f"  金鑰操作: {report['key_management']['total_key_operations']}",
            f"  金鑰匯出: {report['key_management']['key_exports']}",
            f"  狀態: {report['key_management']['compliance_status']}",
            "",
            "=" * 60
        ]
        return "\n".join(lines)

if __name__ == "__main__":
    reporter = HSMAuditReporter("/var/log/hsm/audit.log")

    # 產生最近 30 天的摘要
    end_date = datetime.now()
    start_date = end_date - timedelta(days=30)
    summary = reporter.generate_summary(start_date, end_date)
    print(json.dumps(summary, indent=2, default=str))

    # 匯出合規報告
    reporter.export_report("compliance_report.json")

金鑰備份與災難復原

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/bash
# HSM 金鑰備份程序

set -e

BACKUP_DIR="/secure/hsm-backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/hsm_backup_${DATE}.tar.gz.enc"

# 建立備份目錄
mkdir -p "${BACKUP_DIR}"

# 使用 Luna Backup HSM 進行備份
echo "開始 HSM 金鑰備份..."

# 匯出 Partition 內容
/usr/safenet/lunaclient/bin/cmu export \
    -slot 0 \
    -outputFile "/tmp/partition_backup_${DATE}.bin" \
    -wrap

# 加密備份檔案
openssl enc -aes-256-gcm \
    -salt \
    -pbkdf2 \
    -in "/tmp/partition_backup_${DATE}.bin" \
    -out "${BACKUP_FILE}" \
    -pass file:/secure/backup_key

# 計算校驗碼
sha256sum "${BACKUP_FILE}" > "${BACKUP_FILE}.sha256"

# 清理暫存檔案
rm -f "/tmp/partition_backup_${DATE}.bin"

# 上傳至異地備份
aws s3 cp "${BACKUP_FILE}" "s3://my-hsm-backups/$(basename ${BACKUP_FILE})" \
    --sse aws:kms \
    --sse-kms-key-id alias/hsm-backup-key

aws s3 cp "${BACKUP_FILE}.sha256" "s3://my-hsm-backups/$(basename ${BACKUP_FILE}).sha256" \
    --sse aws:kms \
    --sse-kms-key-id alias/hsm-backup-key

echo "HSM 金鑰備份完成: ${BACKUP_FILE}"

# 保留最近 30 天的本地備份
find "${BACKUP_DIR}" -type f -mtime +30 -delete

結論

硬體安全模組(HSM)是保護企業關鍵加密金鑰的最佳解決方案。透過本文的介紹,我們了解了:

  1. HSM 基本概念:提供 FIPS 140-2/140-3 認證的硬體級安全保護
  2. PKCS#11 標準:統一的加密裝置介面,支援多種程式語言整合
  3. 雲端 HSM 服務:AWS CloudHSM 和 Azure Dedicated HSM 提供便利的雲端部署選項
  4. 地端解決方案:Thales Luna HSM 提供最高等級的安全性與效能
  5. 系統整合:與 HashiCorp Vault、EJBCA、cert-manager 等工具無縫整合
  6. 效能最佳化:連線池、批次處理等技術提升效能
  7. 合規與稽核:滿足 PCI-DSS、eIDAS、HIPAA 等法規要求

選擇 HSM 解決方案時,應考慮以下因素:

  • 安全合規要求(FIPS 等級、認證標準)
  • 效能需求(簽署次數/秒、延遲要求)
  • 部署模式(雲端、地端、混合)
  • 整合複雜度(現有系統相容性)
  • 總擁有成本(硬體、授權、維護)

正確實施 HSM 可以大幅提升組織的資安防護等級,確保加密金鑰的機密性、完整性與可用性。


參考資源

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy