3.17 Mechanism系统:密码算法的“配方库“
Mechanism是什么?
在PKCS#11中,Mechanism(机制)是密码算法的“配方“。
每个Mechanism定义了:
- 算法类型:RSA签名、AES加密、SHA哈希等
- 算法参数:密钥长度、IV、盐值等
- 使用方式:签名、加密、哈希、密钥生成等
Mechanism是PKCS#11“提供机制而非策略“原则的核心体现:标准定义了可用的机制,部署者选择使用哪些机制。
CK_MECHANISM结构
Mechanism用一个结构体表示:
/* CK_MECHANISM结构定义 */
typedef struct CK_MECHANISM {
CK_MECHANISM_TYPE type; /* 机制类型(如CKM_RSA_PKCS) */
CK_VOID_PTR pParameter; /* 机制参数(如IV、Salt等) */
CK_ULONG ulParameterLen; /* 参数长度 */
} CK_MECHANISM;
使用示例:
/* 无参数的机制 */
CK_MECHANISM mechanism = {CKM_RSA_PKCS, NULL_PTR, 0};
rv = C_SignInit(hSession, &mechanism, hPrivateKey);
/* 有参数的机制 */
CK_RSA_PKCS_PSS_PARAMS pssParams = {
CKM_SHA256, /* 哈希算法 */
CKG_MGF1_SHA256, /* MGF算法 */
32 /* 盐值长度 */
};
CK_MECHANISM mechanism = {CKM_RSA_PKCS_PSS, &pssParams, sizeof(pssParams)};
rv = C_SignInit(hSession, &mechanism, hPrivateKey);
CK_MECHANISM_TYPE:机制的标识符
PKCS#11规范定义了100余种机制类型(规范第6章):
分类概览:
机制类型分类:
CKM_RSA_* RSA相关机制(约15种)
CKM_DSA_* DSA相关机制(约5种)
CKM_ECDSA_* ECDSA相关机制(约5种)
CKM_ECDH_* ECDH相关机制(约5种)
CKM_DH_* DH相关机制(约5种)
CKM_AES_* AES相关机制(约20种)
CKM_DES_* DES相关机制(约15种)
CKM_SHA* SHA哈希机制(约30种)
CKM_HMAC* HMAC机制(约30种)
CKM_*_KEY_PAIR_GEN 密钥生成机制
CKM_*_KEY_DERIVE 密钥派生机制
CKM_*_WRAP 密钥包装机制
查询支持的机制
应用程序可以查询Token支持的机制:
C_GetMechanismList:
CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE_PTR pMechanismList,
CK_ULONG_PTR pulCount);
C_GetMechanismInfo:
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo);
/* CK_MECHANISM_INFO结构 */
typedef struct CK_MECHANISM_INFO {
CK_ULONG ulMinKeySize; /* 最小密钥长度 */
CK_ULONG ulMaxKeySize; /* 最大密钥长度 */
CK_FLAGS flags; /* 机制标志 */
} CK_MECHANISM_INFO;
/* flags可能值 */
#define CKF_HW 0x00000001 /* 硬件实现 */
#define CKF_ENCRYPT 0x00000100 /* 可用于加密 */
#define CKF_DECRYPT 0x00000200 /* 可用于解密 */
#define CKF_DIGEST 0x00000400 /* 可用于哈希 */
#define CKF_SIGN 0x00000800 /* 可用于签名 */
#define CKF_SIGN_RECOVER 0x00001000 /* 可用于可恢复签名 */
#define CKF_VERIFY 0x00002000 /* 可用于验证 */
#define CKF_VERIFY_RECOVER 0x00004000 /* 可用于可恢复验证 */
#define CKF_GENERATE 0x00008000 /* 可生成密钥 */
#define CKF_GENERATE_KEY_PAIR 0x00010000 /* 可生成密钥对 */
#define CKF_DERIVE 0x00020000 /* 可派生密钥 */
#define CKF_WRAP 0x00040000 /* 可包装密钥 */
#define CKF_UNWRAP 0x00080000 /* 可解包密钥 */
示例代码:
/* 查询Token支持的机制 */
CK_ULONG mechCount;
CK_MECHANISM_TYPE_PTR mechList;
CK_MECHANISM_INFO mechInfo;
CK_RV rv;
// 1. 获取机制数量
rv = C_GetMechanismList(slotID, NULL_PTR, &mechCount);
if (rv != CKR_OK) {
printf("获取机制数量失败\n");
return;
}
// 2. 分配内存,获取机制列表
mechList = malloc(mechCount * sizeof(CK_MECHANISM_TYPE));
rv = C_GetMechanismList(slotID, mechList, &mechCount);
// 3. 打印每个机制的详细信息
for (CK_ULONG i = 0; i < mechCount; i++) {
rv = C_GetMechanismInfo(slotID, mechList[i], &mechInfo);
printf("机制 %08x:\n", mechList[i]);
printf(" 密钥长度: %lu-%lu\n", mechInfo.ulMinKeySize, mechInfo.ulMaxKeySize);
printf(" 硬件实现: %s\n", (mechInfo.flags & CKF_HW) ? "是" : "否");
printf(" 可签名: %s\n", (mechInfo.flags & CKF_SIGN) ? "是" : "否");
printf(" 可加密: %s\n", (mechInfo.flags & CKF_ENCRYPT) ? "是" : "否");
}
free(mechList);
常用机制详解
RSA机制:
| 机制 | 描述 | 用途 |
|---|---|---|
| CKM_RSA_PKCS_KEY_PAIR_GEN | RSA密钥对生成 | 生成RSA密钥 |
| CKM_RSA_PKCS | PKCS#1 v1.5签名/加密 | 签名、加密 |
| CKM_RSA_PKCS_PSS | RSASSA-PSS签名 | 更安全的签名 |
| CKM_RSA_PKCS_OAEP | RSAES-OAEP加密 | 更安全的加密 |
| CKM_RSA_X_509 | X.509原始RSA | 不推荐 |
CKM_RSA_PKCS_PSS参数:
typedef struct CK_RSA_PKCS_PSS_PARAMS {
CK_MECHANISM_TYPE hashAlg; /* 哈希算法(如CKM_SHA256) */
CK_RSA_PKCS_MGF_TYPE mgf; /* MGF掩码生成函数(如CKG_MGF1_SHA256) */
CK_ULONG sLen; /* 盐值长度 */
} CK_RSA_PKCS_PSS_PARAMS;
AES机制:
| 机制 | 描述 | 模式 |
|---|---|---|
| CKM_AES_KEY_GEN | AES密钥生成 | 密钥生成 |
| CKM_AES_ECB | AES ECB模式 | 无IV |
| CKM_AES_CBC | AES CBC模式 | 需要16字节IV |
| CKM_AES_CBC_PAD | AES CBC+PKCS#7填充 | 需要16字节IV |
| CKM_AES_CTR | AES CTR模式 | 需要计数器参数 |
| CKM_AES_GCM | AES GCM模式 | 需要IV和AAD |
CKM_AES_CBC参数:
CK_BYTE iv[16] = {0x00, 0x01, 0x02, ...}; /* 16字节IV */
CK_MECHANISM mechanism = {CKM_AES_CBC, iv, 16};
CKM_AES_GCM参数:
typedef struct CK_GCM_PARAMS {
CK_BYTE_PTR pIv; /* IV指针 */
CK_ULONG ulIvLen; /* IV长度 */
CK_ULONG ulIvBits; /* IV位数(通常与ulIvLen*8相同) */
CK_BYTE_PTR pAAD; /* AAD(附加认证数据) */
CK_ULONG ulAADLen; /* AAD长度 */
CK_ULONG ulTagBits; /* 认证标签位数(如128) */
} CK_GCM_PARAMS;
ECDSA机制:
| 机制 | 描述 | 用途 |
|---|---|---|
| CKM_EC_KEY_PAIR_GEN | EC密钥对生成 | 生成ECDSA密钥 |
| CKM_ECDSA | ECDSA签名 | 签名原始数据 |
| CKM_ECDSA_SHA1 | SHA1后ECDSA签名 | 签名哈希后数据 |
| CKM_ECDSA_SHA256 | SHA256后ECDSA签名 | 签名哈希后数据 |
SHA机制:
| 机制 | 描述 | 输出长度 |
|---|---|---|
| CKM_SHA_1 | SHA-1哈希 | 20字节 |
| CKM_SHA256 | SHA-256哈希 | 32字节 |
| CKM_SHA384 | SHA-384哈希 | 48字节 |
| CKM_SHA512 | SHA-512哈希 | 64字节 |
HMAC机制:
/* HMAC机制 */
CK_MECHANISM mechanism = {CKM_SHA256_HMAC, NULL_PTR, 0};
rv = C_SignInit(hSession, &mechanism, hHmacKey);
rv = C_Sign(hSession, data, dataLen, hmac, &hmacLen);
密钥生成机制
RSA密钥生成:
CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 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)},
// 其他属性...
};
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_SENSITIVE, &bTrue, sizeof(bTrue)},
{CKA_EXTRACTABLE, &bFalse, sizeof(bFalse)},
// 其他属性...
};
rv = C_GenerateKeyPair(hSession, &mechanism,
publicKeyTemplate, 2,
privateKeyTemplate, 2,
&hPublicKey, &hPrivateKey);
AES密钥生成:
CK_MECHANISM mechanism = {CKM_AES_KEY_GEN, NULL_PTR, 0};
CK_ULONG keyLen = 32; /* 256位 */
CK_ATTRIBUTE keyTemplate[] = {
{CKA_VALUE_LEN, &keyLen, sizeof(keyLen)},
{CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType)},
{CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass)},
};
rv = C_GenerateKey(hSession, &mechanism, keyTemplate, 3, &hKey);
密钥派生机制
ECDH密钥派生:
CK_ECDH1_DERIVE_PARAMS ecdhParams = {
CKD_NULL, /* KDF类型 */
NULL_PTR, /* 共享数据 */
0, /* 共享数据长度 */
otherPublicKey, /* 对方公钥数据 */
otherPubKeyLen /* 公钥长度 */
};
CK_MECHANISM mechanism = {CKM_ECDH1_DERIVE, &ecdhParams, sizeof(ecdhParams)};
CK_ATTRIBUTE derivedKeyTemplate[] = {
{CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass)},
{CKA_KEY_TYPE, &aesKeyType, sizeof(aesKeyType)},
{CKA_VALUE_LEN, &keyLen, sizeof(keyLen)},
};
rv = C_DeriveKey(hSession, &mechanism, hPrivateKey, derivedKeyTemplate, 3, &hDerivedKey);
HKDF密钥派生(v3.0新增):
/* CK_HKDF_PARAMS简化展示(完整定义请参考PKCS#11规范) */
typedef struct CK_HKDF_PARAMS {
CK_BBOOL bExtract; /* 是否执行Extract步骤 */
CK_BBOOL bExpand; /* 是否执行Expand步骤 */
CK_MECHANISM_TYPE prfHashMechanism; /* PRF哈希机制(如CKM_SHA256) */
CK_ULONG ulSaltType; /* 盐值来源类型 */
CK_BYTE_PTR pSalt; /* 盐值数据 */
CK_ULONG ulSaltLen; /* 盐值长度 */
CK_OBJECT_HANDLE hSaltKey; /* 盐值密钥对象(可选) */
CK_BYTE_PTR pInfo; /* Info数据 */
CK_ULONG ulInfoLen; /* Info长度 */
} CK_HKDF_PARAMS;
/* 基础用法示例 */
CK_HKDF_PARAMS hkdfParams = {
TRUE, /* 执行Extract */
TRUE, /* 执行Expand */
CKM_SHA256, /* SHA-256作为PRF */
CKZ_SALT_SPECIFIED, /* 使用pSalt提供的盐值 */
salt, saltLen, /* 盐值 */
CK_INVALID_HANDLE, /* 不使用hSaltKey */
info, infoLen /* Info */
};
CK_MECHANISM mechanism = {CKM_HKDF_DERIVE, &hkdfParams, sizeof(hkdfParams)};
rv = C_DeriveKey(hSession, &mechanism, hBaseKey, template, 3, &hDerivedKey);
本篇小结
Mechanism是PKCS#11的“配方库“,定义了可用的密码算法:
CK_MECHANISM结构:
- type:机制类型(CKM_xxx)
- pParameter:机制参数(IV、Salt等)
- ulParameterLen:参数长度
机制查询:
- C_GetMechanismList:获取支持的机制列表
- C_GetMechanismInfo:获取机制详细信息
常用机制:
- RSA:CKM_RSA_PKCS、CKM_RSA_PKCS_PSS、CKM_RSA_PKCS_OAEP
- AES:CKM_AES_ECB、CKM_AES_CBC、CKM_AES_GCM
- ECDSA:CKM_ECDSA、CKM_ECDSA_SHA256
- SHA:CKM_SHA256、CKM_SHA512
- HMAC:CKM_SHA256_HMAC
- 密钥生成:CKM_RSA_PKCS_KEY_PAIR_GEN、CKM_AES_KEY_GEN
- 密钥派生:CKM_ECDH1_DERIVE、CKM_HKDF_DERIVE
下一节,我们将详细解析AES机制——ECB、CBC、GCM等模式的区别和用法。
【下集预告】
ECB是什么?为什么说不安全?
CBC是什么?IV如何使用?
GCM是什么?AEAD是什么?
下一节,AES机制详解。