ピースペース

PKIカードの証明書を読む

leave a comment »

今回実際に行ったのは、HPKIカードに格納されている利用者証明書のSubject-SNを読む。
のだが、住基カードやマイナンバーカードもだいたい同じように読めると思う。たぶん。

戸惑ったのは、スマートカードやPKIに関する様々な標準規約について、
それらがどうゆう関係で関連しているのか?や、
その規約を実装したライブラリがどの範囲を担当しているの?
などの理解に時間がかかった。

ある規約Aがある規約Bを前提に決められている場合、
規約Aの説明は規約Bは当然のこととして書かれているので、
規約Bを知らないと規約Aの説明を理解することはできない。
何が何で何が何でないかもわからない。という状況から始めて、
悶々しながら進んでいくうち霧は徐々に晴れてくる。のだ。
とはいえ、その先にまた霧に包まれた広大な世界が見えてくるのだが;

さて、HPKIカードに格納されている電子証明書を読み取る手順はPKCS#11に従う。
ので、PKCS#11を実装したモジュールが必要になる。
でもってそれは、PKIカードベンダー(カード発行者)によって提供される。おそらく。
で、dotNetからそのライブラリを使用するには、pkcs11interropが使えた。
https://www.pkcs11interop.net/

サンプルコードをまねて、だいたいこんな感じで証明書のSubject属性が読めた。

using (Pkcs11 pkcs11 = new Pkcs11(pkcs11LibraryPath, true))
{
               var result = new ReadResult();
               var slot = GetUsableSlot(pkcs11);
               if (slot == null)
               {
                   result.Error = "HPKIカードをセットして下さい。";
                   return result;
               }

               // Open ReadOnly session
               using (Session session = slot.OpenSession(true))
               {
                   // Prepare attribute template that defines search criteria
                   List<ObjectAttribute> objectAttributes = new List<ObjectAttribute>();
                   objectAttributes.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_CERTIFICATE));
                   objectAttributes.Add(new ObjectAttribute(CKA.CKA_TOKEN, true));
                   objectAttributes.Add(new ObjectAttribute(CKA.CKA_LABEL, "HPKI END ENTITY CERTIFICATE"));

                   // Initialize searching
                   session.FindObjectsInit(objectAttributes);
                   // Get search results
                   List<ObjectHandle> foundObjects = session.FindObjects(2);
                   var cert = foundObjects.FirstOrDefault();
                   if (cert == null)
                   {
                       result.Error = "読取できませんでした(証明書が不明)";
                       return result;
                   }

                   // 証明書からSubjectを抜き出す
                   List<CKA> attributes = new List<CKA>();
                   attributes.Add(CKA.CKA_SUBJECT);
                   var subject = session.GetAttributeValue(cert, attributes).FirstOrDefault();
                   if (subject == null)
                   {
                       result.Error = "読取できませんでした(Subject属性が不明)";
                       return result;
                   }

                   var bytes = subject.GetValueAsByteArray();

                   // Terminate searching
                   session.FindObjectsFinal();

読み込んだSubjectはDERエンコードされているのでデコードする必要がある。
これはPKCS#11の担当範囲外だ。

pkcs11interropには、WaitForSlotEventというメソッドもあるが、
利用するHPKIのPKCS#11カードドライバにその実装がないので使えない。
ので、ここは、PC/SCのSCardMonitorを使用する。
https://github.com/danm-de/pcsc-sharp

これもサンプルコードをまねて、カードのInsertedイベントを捉えることができた。
SCardMonitor.CardInsertedイベントは、別スレッドで実行されるので、
このイベントでカードを読んでUIを更新する場合は、
ISynchronizeInvokeを使ってセットしておいたUI更新ActionをInvokeする必要がある。
非同期処理も依然霧がかかったままの状態でいる。
毎度、なんとかせねば!と思いつつ… なんとかしてない;;

Written by nasu38yen

2016年7月21日 @ 3:25 PM

カテゴリー: .NET

Tagged with

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。