2

pkcs11 標準を使用してデジタル署名を作成したいと考えています。スマート カードに公開鍵と秘密鍵のペアが既に保存されているとします。このキーは、次のコードを使用して生成されました。

byte[] ckaId = session.GenerateRandom(20);

// Prepare attribute template of new public key
var publicKeyAttributes = new List<ObjectAttribute>();
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, false));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
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_BITS, 1024));
publicKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PUBLIC_EXPONENT, new byte[] { 0x01, 0x00, 0x01 }));

// Prepare attribute template of new private key
var privateKeyAttributes = new List<ObjectAttribute>();
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_PRIVATE, true));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, PKCS11Settings.ApplicationName));
privateKeyAttributes.Add(new ObjectAttribute(CKA.CKA_ID, ckaId));
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));

// Specify key generation mechanism
Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS_KEY_PAIR_GEN);

// Generate key pair
session.GenerateKeyPair(mechanism, publicKeyAttributes, privateKeyAttributes, out publicKeyHandle, out privateKeyHandle);

これで、これらのキーを使用してデータに署名できるようになりました。例えば:

var mechanism = new Mechanism(CKM.CKM_RSA_PKCS);
byte[] byteContent = (ConvertUtils.Utf8StringToBytes("Hello World!!!"));
byte[] signature = session.Sign(mechanism, derivedKey, byteContent);

このコードは、キーを作成して C_sign メソッドで使用する場合に最適です。

しかし、既存のキーにアクセスして同様の操作を行うにはどうすればよいでしょうか? 私が理解しているように、C_Derrive() メソッドを使用して既存の秘密鍵から秘密鍵を導出し、それを C_Sign() メソッドで使用する必要があります。この目的のために、次のコードを書きました。

// Prepare attribute template of new key
List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_SECRET_KEY));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_KEY_TYPE, CKK.CKK_DES3));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_ENCRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_DERIVE, true));
objectAttributes.Add(new ObjectAttribute(CKA.CKA_EXTRACTABLE, true));

// Specify key generation mechanism
Mechanism mechanism = new Mechanism(CKM.CKM_RSA_PKCS);

// Generate key
ObjectHandle baseKey = session.GenerateKey(mechanism, objectAttributes);

byte[] dt = session.GenerateRandom(24);

// Specify mechanism parameters
var mechanismParams = new CkKeyDerivationStringData(dt);

// Specify derivation mechanism with parameters
Mechanism mech = new Mechanism(CKM.CKM_RSA_PKCS, mechanismParams);

// Derive key
ObjectHandle derivedKey = session.DeriveKey(mech, baseKey, null);


byte[] byteContent = (ConvertUtils.Utf8StringToBytes("Hello World!"));
byte[] signature = session.Sign(mech, derivedKey, byteContent);

しかし、このコードを実行すると、次のエラーがスローされます。

メソッド C_GenerateKey が CKR_MECHANISM_INVALID を返しました

私が間違っていることと、この問題を解決する方法を誰か教えてもらえますか?

4

2 に答える 2

0

最初に、pkcs-11v2-20.pdf を数回参照すると思うので、まだコピーを持っていない場合は入手してください (役立つ例も付いています)。

第 2 に、私は C# プログラマーではないため、残念ながら以下は疑似コードにすぎません。

まず、CKR_MECHANISM_INVALID の問題に対処しましょう。標準によれば、CKM.CKM_RSA_PKCS は C_DeriveKey には使用できません (12 章、表 34)。

そして今、目の前にある問題: あなたはすでにスマート カードにキー ペアを持っています (そして必要に応じてセッションを開き、ログインしています)。いくつかの例を示します)、探しているキーの種類の属性テンプレートを C_FindObjectsInit に提供します。

// look for key allowing signing and decrypting
var searchCriteria = new List<ObjectAttribute>();
searchCriteria.Add(new ObjectAttribute(CKA.CKA_DECRYPT, true));
searchCriteria.Add(new ObjectAttribute(CKA.CKA_SIGN, true));

// initialize the search. The number is actually the number of search attributes.
session.FindObjectsInit(searchCriteria, 2);
...
session.FindObjects(out privateKeyHandle, ...);
... 
session.FindObjectsFinal();

// we found the requested private key, now sign the message
session.Sign(..., privateKeyHandle,...);

最後のスニペットで試したキーの導出は、スマート カードとアプリケーションが非対称暗号化を使用して 1 つまたは 2 つの共有秘密キーを導出する必要があるシナリオ (たとえば、安全なメッセージング用) を対象としています。

それが役に立ったことを願っています。

于 2016-10-25T22:19:13.660 に答える