Import a private key using PKCS#11

2019-08-28 21:13发布

We're trying to import an RSA key pair using C# and PKCS#11 into our HSM. Importing the private key using:

    var privateKeyAttributes = new List<ObjectAttribute>();
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaId));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SENSITIVE, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_SIGN_RECOVER, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_UNWRAP, true));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS, privateKeyParams.Modulus));
    privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE_EXPONENT, privateKeyParams.D));
    var privateKeyHandle = session.CreateObject(privateKeyAttributes);

Fails with the error code CKR_TEMPLATE_INCONSISTENT. Unfortunately, it doesn't say what is inconsistent. I tried various other combinations of attributes and it always fails :-(

How to properly import the private key via PKCS#11?


Note: Importing the public key using very similar code works:

    var publicKeyAttributes = new List<ObjectAttribute>();
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, ckaId));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PUBLIC_KEY));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_VERIFY_RECOVER, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_WRAP, true));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_MODULUS, publicKeyParams.Modulus));
    publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, publicKeyParams.Exponent));
    var publicKeyHandle = session.CreateObject(publicKeyAttributes);

2条回答
乱世女痞
2楼-- · 2019-08-28 21:42

Unfortunately PKCS#11 API does not provide details which exact attribute from supplied template caused the error but many PKCS#11 libraries support some kind of internal logging mechanism which may reveal the real cause of error. Exact steps needed to enable logging should be present in the documentation provided by the PKCS#11 library vendor.

My guess is that you're receiving CKR_TEMPLATE_INCONSISTENT because you are setting CKA_SENSITIVE to true. Private key imported in plain form has already lost its "sensitivity" because it was exposed to an external environment. I'm successfully using following template in Pkcs11Interop.X509Store project:

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_LABEL, ...),
    new ObjectAttribute(CKA.CKA_ID, ...),
    new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_RSA),
    new ObjectAttribute(CKA.CKA_MODULUS, rsaPrivKeyParams.Modulus.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, rsaPrivKeyParams.PublicExponent.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_PRIVATE_EXPONENT, rsaPrivKeyParams.Exponent.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_PRIME_1, rsaPrivKeyParams.P.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_PRIME_2, rsaPrivKeyParams.Q.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_EXPONENT_1, rsaPrivKeyParams.DP.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_EXPONENT_2, rsaPrivKeyParams.DQ.ToByteArrayUnsigned()),
    new ObjectAttribute(CKA.CKA_COEFFICIENT, rsaPrivKeyParams.QInv.ToByteArrayUnsigned())
};
查看更多
混吃等死
3楼-- · 2019-08-28 22:05

The answer is: you can't directly import a private key into a SafeNet Luna HSM. You have to first encrypt (wrap) the private key and can only then transfer it to the HSM. See PKCS#11 unwrap private key to HSM for an answer on how to do this.

查看更多
登录 后发表回答