我想用下面的代码生成一个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}`);
上面的代码将产生无效的密钥长度错误。
答案 0 :(得分:1)
基于这里的答案:https://github.com/PeculiarVentures/pkcs11js/issues/34,我能够通过获取CKA_VALUE属性来提取秘密密钥,但是我需要在密钥生成过程中设置以下内容:{ pkcs11js.CKA_EXTRACTABLE, value: true }
。我了解这当然会破坏HSM的目的,即不公开秘密。
答案 1 :(得分:1)
这里的核心问题是SoftHSM不支持所使用的机制,这就是为什么仅使用get / set属性方法的原因。只有在HSM / PKCS11实现支持该机制的情况下,才可以将值的长度设置为可提取,而无需将其设置为可提取。