我正在使用最新的 AWS 云 HSM 以及带有 PKCS11Interop c# 库的 PKCS 供应商库。尝试从AWS PKCS Samples
模拟 CKM.CKM_RSA_AES_KEY_WRAP 的示例代码
包装 AES 256 密钥时出现以下错误。
Net.Pkcs11Interop.Common.Pkcs11Exception:“方法 C_WrapKey 返回 CKR_ARGUMENTS_BAD”在 Net.Pkcs11Interop.HighLevelAPI80.Session.WrapKey(IMechanism 机制,IObjectHandle wrappingKeyHandle,IObjectHandle keyHandle)
我的示例代码
public ActionResult<string> WrapUnwrap(string keyAlias)
{
using (IPkcs11Library pkcs11Library = Settings.Factories.Pkcs11LibraryFactory.LoadPkcs11Library(Settings.Factories, Settings.Pkcs11LibraryPath, Settings.AppType))
{
// Find first slot with token present
ISlot slot = Helpers.GetUsableSlot(pkcs11Library);
// Open RW session
using (ISession session = slot.OpenSession(SessionType.ReadWrite))
{
// Login as normal user
session.Login(CKU.CKU_USER, Settings.NormalUserPin);
// Generate asymetric key pair
IObjectHandle publicKey = null;
IObjectHandle privateKey = null;
GenerateRSAKeyPair(session, out publicKey, out privateKey);
//Generate symmetric key : AES 256
var keyToWrap = GenerateAESKey(session);
// Specify wrapping mechanism
var oaepParams = session.Factories.MechanismParamsFactory.CreateCkRsaPkcsOaepParams(
ConvertUtils.UInt64FromCKM(CKM.CKM_SHA256),
ConvertUtils.UInt64FromCKG(CKG.CKG_MGF1_SHA256),
ConvertUtils.UInt64FromUInt32(CKZ.CKZ_DATA_SPECIFIED),
null);
var rsaParams = session.Factories.MechanismParamsFactory.CreateCkRsaAesKeyWrapParams(256, oaepParams);
IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_AES_KEY_WRAP);
// Wrap key
byte[] wrappedKey = session.WrapKey(mechanism, publicKey, keyToWrap);
if (wrappedKey == null)
throw new Exception("Failed to wrap key.");
// Define attributes for unwrapped key
List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_AES));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_EXTRACTABLE, true));
// Unwrap key
IObjectHandle unwrappedKey = session.UnwrapKey(mechanism, privateKey, wrappedKey, objectAttributes);
session.DestroyObject(privateKey);
session.DestroyObject(publicKey);
session.DestroyObject(keyToWrap);
session.DestroyObject(unwrappedKey);
session.Logout();
}
}
return Ok();
}
private static void GenerateRSAKeyPair(ISession session, out IObjectHandle publicKeyHandle, out IObjectHandle privateKeyHandle)
{
// The CKA_ID attribute is intended as a means of distinguishing multiple key pairs held by the same subject
byte[] ckaId = session.GenerateRandom(20);
// Prepare attribute template of new public key
List<IObjectAttribute> publicKeyAttributes = new List<IObjectAttribute>();
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
//publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, false)); // Throws InvalidAttribute Value
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP, true));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODULUS_BITS, 2048));
publicKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));
// Prepare attribute template of new private key
List<IObjectAttribute> privateKeyAttributes = new List<IObjectAttribute>();
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
//privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
privateKeyAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_UNWRAP, true));
// Specify key generation mechanism
IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_X9_31_KEY_PAIR_GEN);
// Generate key pair
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);
}
private static IObjectHandle GenerateAESKey(ISession session, string keyAlias = null)
{
byte[] ckaId = null;
if (string.IsNullOrEmpty(keyAlias))
ckaId = session.GenerateRandom(20);
else
ckaId = Encoding.UTF8.GetBytes(keyAlias);
// Generate symetric key
// Prepare attribute template of new key
List<IObjectAttribute> objectAttributes = new List<IObjectAttribute>();
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_AES));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_VALUE_LEN, 32));// means 256 bit
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DECRYPT, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PRIVATE, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_EXTRACTABLE, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, ckaId));
//objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_WRAP_WITH_TRUSTED, false));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_DESTROYABLE, true));
objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_TOKEN, true));
//objectAttributes.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_SIGN, false));
// Specify key generation mechanism
IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_AES_KEY_GEN);
// Generate key
IObjectHandle generatedKey = session.GenerateKey(mechanism, objectAttributes);
return generatedKey;
}