我有一个要求包装在HSMRSAPrivate ateKey,这样它可以发送到微软CA的密钥存档,我不知道采取什么方法。
问题是微软RSA密钥格式是专有的,似乎不受我公司使用的pkcs11或nCipherHSM支持。
http://msdn.microsoft.com/en-us/library/cc250013.aspx
如果这只是一个RSAPriateKey,那么在HSM中生成密钥对、在HSM中加载包装密钥、包装RSAPriateKey并提取包装的密钥字节就很简单了。显然,由于不支持这种密钥blob格式,我需要采取不同的方法。
我的第一个想法是扩展RSAPrivate ateKey并覆盖getEncoded()方法以返回这种专有密钥格式。我使用的是IAIK pkcs11包装器,它为Java中的pkcs11提供了高级API,并且支持创建供应商定义的密钥类型。然而,供应商定义密钥的接口似乎只是为了方便扩展客户端代码中的内置密钥类型而存在,实际上不允许在HSM中修改密钥编码。
第二个想法是使用pkcs11数据对象,简单地将其视为密钥blob,然后使用包装密钥对其进行加密。这里同样的问题是,为了将私钥字节复制到数据对象中,似乎我需要将私钥字节提取到应用程序代码中,然后从那里创建数据对象,这就违背了将密钥放在HSM中的全部意义。
我正在寻找这些方法的替代方案,或者也许pkcs11中有一些我忽略的功能可以让我做到这一点?任何见解都将不胜感激。
我同意这看起来像是nShield HSM不支持的数据格式(不过,可能值得与支持团队仔细检查)。
假设是这种情况,只有一种方法可以安全地做到这一点——必须使用低得多的API加载私钥,并将其传递给在HSM中运行的一些定制代码(利用CodeSafe技术),这将公开密钥材料,将其转换为必要的格式,并用包装密钥包装它。
任何其他方法都将导致主机上的密钥暴露。此外,如果您生成的密钥具有合理的(默认)权限,则如果不编写使用管理员卡组的定制代码,无论如何都无法公开密钥。
我建议你就这个问题联系支持团队。你甚至可以联系一些友好的顾问,咳,他们可以帮助你解决这个问题。
你可能想做的是使用PKCS#11包装器。我有点困惑,当你从Java与HSM交互时(因为你提到IAIK或. Net,因为你想导出到Microsoft RSAPrivate ateKey)。无论如何,PKCS11包装器(IAIK为Java,NCryptoki为.Net)将允许您使用PKCS#11 v2.30与HSM通信,确保检查包装器中支持的版本和HSM规范,因为版本之间可能存在不兼容。
PKCS#11允许您使用C_GenerateKeyPair函数在HSM中生成RSA密钥对。您必须指定一个机制(RSA_PKCS_KEY_PAIR_GEN)并提供两个模板,一个用于私钥,一个用于公钥。确保私钥的CKA_WRAP属性设置为true。
要在HSM中加载包装键,函数C_CreateObject可以与模板结合使用。
然后,您可以使用C_WrapKey函数将RSA密钥与您导入HSM的密钥包装起来。首先使用C_FindObjectsInit、C_FindObjects和C_FindObjectsFinal检索要包装的密钥和包装密钥的句柄。然后使用适当的机制和两个句柄调用C_WrapKey函数。
如果这是一种不受支持的专有格式,您可能必须在HSM中运行专有代码才能做到这一点。许多HSM允许您运行专有代码,但您需要HSM提供商的支持才能首先加载代码。此外,在HSM中运行您自己的代码可能会破坏安全认证(FIPS或通用标准)。
否则,您将不得不从HSM中检索私钥,在安全的环境中将其转换为正确的格式,并使用HSM的正常加密工具对其进行包装。这当然会将私钥暴露在HSM之外。
您也可以询问Microsoft是否有首选解决方案。