无法使用 pkcs11js 生成 32 字节的 AES Secret
Cannot generate 32 bytes AES Secret using pkcs11js
我想用下面的代码生成一个 32 字节的 AES 密钥。我正在使用节点模块 pkcs11js,因为我需要连接到 HSM。但是,当我打印密钥的长度时,它显示的是 8 而不是 32。
var path = require('path');
var pkcs11js = require("pkcs11js");
var crypto = require('crypto');
process.env['SOFTHSM2_CONF'] = path.resolve(__dirname, '../softhsm2.conf');
var pkcs11 = new pkcs11js.PKCS11();
pkcs11.load("/usr/local/Cellar/softhsm/2.4.0/lib/softhsm/libsofthsm2.so");
pkcs11.C_Initialize();
const _pkcs11FindObjects = (pkcs11, pkcs11Session, pkcs11Template) => {
pkcs11.C_FindObjectsInit(pkcs11Session, pkcs11Template);
var objs = [];
var obj = pkcs11.C_FindObjects(pkcs11Session);
while (obj) {
objs.push(obj);
obj = pkcs11.C_FindObjects(pkcs11Session);
}
pkcs11.C_FindObjectsFinal(pkcs11Session);
return objs;
}
const _pkcs11Login = (slotNumber, pin) => {
let s = null;
try {
const slots = pkcs11.C_GetSlotList(true);
const slot = slots[slotNumber];
var token_info = pkcs11.C_GetTokenInfo(slot);
s = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);
pkcs11.C_Login(s, 1, pin);
return s;
} catch (e) {
if (s != null) {
pkcs11.C_CloseSession(s);
}
pkcs11.C_Finalize();
}
}
const _findAESKey = (session, ski) => {
var secretKeyHandle = _pkcs11FindObjects(pkcs11, session, [{
type: pkcs11js.CKA_ID,
value: ski
},
{
type: pkcs11js.CKA_CLASS,
value: pkcs11js.CKO_SECRET_KEY
}
]);
if (secretKeyHandle.length == 1) {
return secretKeyHandle[0];
} else {
return null;
}
}
const _createAESKey = (session, ski) => {
let key = _findAESKey(session, ski);
if (key && key !== null) {
console.log('Key already exists. No need to re-create');
return;
}
var template = [{
type: pkcs11js.CKA_ID,
value: ski
},
{
type: pkcs11js.CKA_CLASS,
value: pkcs11js.CKO_SECRET_KEY
},
{
type: pkcs11js.CKA_TOKEN,
value: true
},
{
type: pkcs11js.CKA_LABEL,
value: "My AES Key"
},
{
type: pkcs11js.CKA_VALUE_LEN,
value: 32
},
{
type: pkcs11js.CKA_ENCRYPT,
value: true
},
{
type: pkcs11js.CKA_DECRYPT,
value: true
},
{
type: pkcs11js.CKA_PRIVATE,
value: true
}
];
pkcs11.C_GenerateKey(session, {
mechanism: pkcs11js.CKM_AES_KEY_GEN
}, template);
}
let session = _pkcs11Login(0, '98765432');
_createAESKey(session, `9Rf3uJ7CEdKIhUvQu/2KN8hK0Kce0zYfPXSc8xAK4Oc=`);
let key = _findAESKey(session, `9Rf3uJ7CEdKIhUvQu/2KN8hK0Kce0zYfPXSc8xAK4Oc=`);
console.log(`key length: ${key.length}`); //key length: 8
原因是我想使用下面的函数加密数据,它要求密钥长度为 32。
const encryptString = (s, secret) => {
const iv = crypto.randomBytes(16).toString('hex').slice(0, 16);
const cipher = crypto.createCipheriv('aes-256-ctr', secret, iv);
const encrypted = cipher.update(String(s), 'utf8', 'hex') + cipher.final('hex');
return iv + encrypted;
}
let e = encryptString('shezhuan sauce', key);
console.log(`encrypted string: ${e}`);
以上代码会产生无效密钥长度错误。
根据此处的答案:https://github.com/PeculiarVentures/pkcs11js/issues/34,我可以通过获取 CKA_VALUE 属性来提取密钥,但我需要在密钥生成期间设置以下内容:{ pkcs11js.CKA_EXTRACTABLE, value: true }
.我明白这当然违背了 HSM 不暴露秘密的目的。
这里的核心问题是所使用的机制不受 SoftHSM 支持,这就是为什么只使用 get/set 属性方法的原因。可以在不将值设置为可提取的情况下获取值的长度,但前提是 HSM/PKCS11 实现支持该机制。
我想用下面的代码生成一个 32 字节的 AES 密钥。我正在使用节点模块 pkcs11js,因为我需要连接到 HSM。但是,当我打印密钥的长度时,它显示的是 8 而不是 32。
var path = require('path');
var pkcs11js = require("pkcs11js");
var crypto = require('crypto');
process.env['SOFTHSM2_CONF'] = path.resolve(__dirname, '../softhsm2.conf');
var pkcs11 = new pkcs11js.PKCS11();
pkcs11.load("/usr/local/Cellar/softhsm/2.4.0/lib/softhsm/libsofthsm2.so");
pkcs11.C_Initialize();
const _pkcs11FindObjects = (pkcs11, pkcs11Session, pkcs11Template) => {
pkcs11.C_FindObjectsInit(pkcs11Session, pkcs11Template);
var objs = [];
var obj = pkcs11.C_FindObjects(pkcs11Session);
while (obj) {
objs.push(obj);
obj = pkcs11.C_FindObjects(pkcs11Session);
}
pkcs11.C_FindObjectsFinal(pkcs11Session);
return objs;
}
const _pkcs11Login = (slotNumber, pin) => {
let s = null;
try {
const slots = pkcs11.C_GetSlotList(true);
const slot = slots[slotNumber];
var token_info = pkcs11.C_GetTokenInfo(slot);
s = pkcs11.C_OpenSession(slot, pkcs11js.CKF_RW_SESSION | pkcs11js.CKF_SERIAL_SESSION);
pkcs11.C_Login(s, 1, pin);
return s;
} catch (e) {
if (s != null) {
pkcs11.C_CloseSession(s);
}
pkcs11.C_Finalize();
}
}
const _findAESKey = (session, ski) => {
var secretKeyHandle = _pkcs11FindObjects(pkcs11, session, [{
type: pkcs11js.CKA_ID,
value: ski
},
{
type: pkcs11js.CKA_CLASS,
value: pkcs11js.CKO_SECRET_KEY
}
]);
if (secretKeyHandle.length == 1) {
return secretKeyHandle[0];
} else {
return null;
}
}
const _createAESKey = (session, ski) => {
let key = _findAESKey(session, ski);
if (key && key !== null) {
console.log('Key already exists. No need to re-create');
return;
}
var template = [{
type: pkcs11js.CKA_ID,
value: ski
},
{
type: pkcs11js.CKA_CLASS,
value: pkcs11js.CKO_SECRET_KEY
},
{
type: pkcs11js.CKA_TOKEN,
value: true
},
{
type: pkcs11js.CKA_LABEL,
value: "My AES Key"
},
{
type: pkcs11js.CKA_VALUE_LEN,
value: 32
},
{
type: pkcs11js.CKA_ENCRYPT,
value: true
},
{
type: pkcs11js.CKA_DECRYPT,
value: true
},
{
type: pkcs11js.CKA_PRIVATE,
value: true
}
];
pkcs11.C_GenerateKey(session, {
mechanism: pkcs11js.CKM_AES_KEY_GEN
}, template);
}
let session = _pkcs11Login(0, '98765432');
_createAESKey(session, `9Rf3uJ7CEdKIhUvQu/2KN8hK0Kce0zYfPXSc8xAK4Oc=`);
let key = _findAESKey(session, `9Rf3uJ7CEdKIhUvQu/2KN8hK0Kce0zYfPXSc8xAK4Oc=`);
console.log(`key length: ${key.length}`); //key length: 8
原因是我想使用下面的函数加密数据,它要求密钥长度为 32。
const encryptString = (s, secret) => {
const iv = crypto.randomBytes(16).toString('hex').slice(0, 16);
const cipher = crypto.createCipheriv('aes-256-ctr', secret, iv);
const encrypted = cipher.update(String(s), 'utf8', 'hex') + cipher.final('hex');
return iv + encrypted;
}
let e = encryptString('shezhuan sauce', key);
console.log(`encrypted string: ${e}`);
以上代码会产生无效密钥长度错误。
根据此处的答案:https://github.com/PeculiarVentures/pkcs11js/issues/34,我可以通过获取 CKA_VALUE 属性来提取密钥,但我需要在密钥生成期间设置以下内容:{ pkcs11js.CKA_EXTRACTABLE, value: true }
.我明白这当然违背了 HSM 不暴露秘密的目的。
这里的核心问题是所使用的机制不受 SoftHSM 支持,这就是为什么只使用 get/set 属性方法的原因。可以在不将值设置为可提取的情况下获取值的长度,但前提是 HSM/PKCS11 实现支持该机制。