我试图通过PKCS#11互操作将RSA私钥传输到我的HSM(SafeNet eToken),然后在HSM上将其解包。
这是我的代码(已更新):
session.Login(CKU.CKU_USER, pin);
var x509Certificate = new X509Certificate2(File.ReadAllBytes(path), "", X509KeyStorageFlags.Exportable);
var privateKey = x509Certificate.PrivateKey as RSACryptoServiceProvider;
var keyPair = DotNetUtilities.GetRsaKeyPair(privateKey);
byte[] privateKeyBytes;
using (var memoryStream = new MemoryStream())
{
using (TextWriter streamWriter = new StreamWriter(memoryStream))
{
var pemWriter = new PemWriter(streamWriter);
pemWriter.WriteObject(keyPair.Private);
streamWriter.Flush();
}
privateKeyBytes = memoryStream.GetBuffer();
}
// Create temporary DES3 key for wrapping/unwrapping
var tempKeyAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3),
new ObjectAttribute(CKA.CKA_ENCRYPT, true),
new ObjectAttribute(CKA.CKA_UNWRAP, true)
};
var tempKey = session.GenerateKey(new Mechanism(CKM.CKM_DES3_KEY_GEN), tempKeyAttributes);
var encrypted =
session.Encrypt(new Mechanism(CKM.CKM_DES3_ECB), tempKey, privateKeyBytes);
string label = "private1";
// Define how the new RSA private key should look like on the HSM
var privateKeyAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY),
new ObjectAttribute(CKA.CKA_TOKEN, true),
new ObjectAttribute(CKA.CKA_PRIVATE, true),
new ObjectAttribute(CKA.CKA_MODIFIABLE, true),
new ObjectAttribute(CKA.CKA_SENSITIVE, false),
new ObjectAttribute(CKA.CKA_LABEL, label),
new ObjectAttribute(CKA.CKA_ID, Encoding.ASCII.GetBytes(label)),
new ObjectAttribute(CKA.CKA_ALWAYS_AUTHENTICATE, false),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA),
};
var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_ECB), tempKey,
encrypted, privateKeyAttributes);
//results in: Method C_UnwrapKey returned CKR_WRAPPED_KEY_INVALID
但是它不起作用-失败,Net.Pkcs11Interop.Common.Pkcs11Exception: Method C_UnwrapKey returned CKR_TEMPLATE_INCONSISTENT
。
(已更新) 现在,结果为CKR_WRAPPED_KEY_INVALID。 但是,如果我使用SafeNet手动导入相同的PFX文件,则不会发生错误-一切似乎都很好。
有什么想法吗?也许有些参数我用错了吗?
答案 0 :(得分:3)
最后完成该操作的代码:
var x509Certificate = new X509Certificate2(File.ReadAllBytes(path), "",
X509KeyStorageFlags.Exportable);
var privateKey = x509Certificate.PrivateKey as RSACryptoServiceProvider;
if (privateKey == null) throw new Exception($"Private key is null for {x509Certificate.SerialNumber}");
var privateKeyParams = privateKey.ExportParameters(true);
session.Login(CKU.CKU_USER, pin);
// Create temporary DES3 key for wrapping/unwrapping
var tempKeyAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3),
new ObjectAttribute(CKA.CKA_ENCRYPT, true),
new ObjectAttribute(CKA.CKA_DECRYPT, true),
new ObjectAttribute(CKA.CKA_UNWRAP, true),
new ObjectAttribute(CKA.CKA_WRAP, true)
};
// Preparing unencrypted private key
var unencryptedPrivateKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
new RsaPrivateCrtKeyParameters(
new BigInteger(1, privateKeyParams.Modulus),
new BigInteger(1, privateKeyParams.Exponent),
new BigInteger(1, privateKeyParams.D),
new BigInteger(1, privateKeyParams.P),
new BigInteger(1, privateKeyParams.Q),
new BigInteger(1, privateKeyParams.DP),
new BigInteger(1, privateKeyParams.DQ),
new BigInteger(1, privateKeyParams.InverseQ))).GetEncoded();
var tempKey = session.GenerateKey(new Mechanism(CKM.CKM_DES3_KEY_GEN), tempKeyAttributes);
var result = new MemoryStream();
var stream = new MemoryStream(unencryptedPrivateKey);
//Encrypting
session.Encrypt(new Mechanism(CKM.CKM_DES3_ECB), tempKey, stream,
result);
var encrypted = result.ToArray();
string label = x509Certificate.SerialNumber;
// Define how the new RSA private key should look like on the HSM
var privateKeyAttributes = new List<ObjectAttribute>
{
new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY),
new ObjectAttribute(CKA.CKA_TOKEN, true),
new ObjectAttribute(CKA.CKA_PRIVATE, true),
new ObjectAttribute(CKA.CKA_MODIFIABLE, true),
new ObjectAttribute(CKA.CKA_SENSITIVE, false),
new ObjectAttribute(CKA.CKA_LABEL, label),
new ObjectAttribute(CKA.CKA_ID, Encoding.ASCII.GetBytes(label)),
new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA)
};
var privateKeyHandle = session.UnwrapKey(new Mechanism(CKM.CKM_DES3_ECB), tempKey,
encrypted, privateKeyAttributes);
return privateKeyHandle;