single.php

CryptAcquireContextでエラー(NTE_EXISTS)が発生する場合

MicrosoftのCryptoAPIを利用する場合には、最初の手続きとしてCryptAcquireContext関数を呼び出して必要となる鍵ペアを取得するところから始まります。

CyptoAPI

通常は以下のように最後の引数 dwFlags に0を渡して取得を行います。

CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)

すでに鍵ペアが存在する場合には、TRUEを返しますが、鍵ペアが取得できなかった場合には、戻り値NTE_BAD_KEYSETを返します。

また、取得できない場合には新しく鍵ペアを作成するために、同様にCryptAcquireContext関数の最後の引数 dwFlags にCRYPT_NEWKEYSETを渡して新しい鍵ペアを作成します。

CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)

この引数で新しい鍵ペアが作成され無事に、TRUEが返される訳ですが、TRUEが返されずにFALSEとなる場合があります。
GetLastError関数でエラー状態を確認すると主に次のエラーコードが取得されます。

  • NTE_BAD_KEYSET (0x80090016)
    鍵コンテナが存在しません。鍵コンテナへアクセスできません。Protected Storageサービスが実行されていません。
  • NTE_EXISTS (0x8009000F)
    鍵コンテナは既に存在しています。 鍵ペアを開くことができませんでした
  • NTE_KEYSET_NOT_DEF (0x80090019)
    暗号サービス プロバイダ (CSP) が正しく設定されていません。 CSP DLL (Rsabase.dll または Rsaenh.dll) に Regsvr32.exe を実行することで問題を解決する可能性があります。

NTE_KEYSET_NOT_DEFの場合には、CSPを再登録することで解決する場合がありますが、NTE_BAD_KEYSETやNTE_EXISTSの場合には、次のフォルダにあるファイルを削除することで問題が解決する場合があります。

解決手順

次の手順でフォルダ内のファイルを確認します。

  1. 次のフォルダーを開きます。
    C:\Users\<ログインしているユーザ名>\AppData\Roaming\Microsoft\Crypto\RSA\S-*-*-*-*-*
    ※S-*-*-*-*-*は、アカウントのSIDとなるため個々のマシンによって異なります。
    ※RSAフォルダー内には複数のフォルダがある場合もあります。
  2. フォルダー内に1つ以上の拡張子無しのファイルがあります。
    (このファイルが鍵ペアを管理しているファイルです)
    複数ある場合には対象となるアプリケーションによって異なる名前を付けた鍵ペアファイルが作成されている形になります。
  3. フォルダー内のファイルを別の場所に移動します。
    システムファイルである警告が出ますが「はい」を選択して続行します。
  4. 鍵ペアの新規作成を行います。
    CryptAcquireContext関数に dwFlags に CRYPT_NEWKEYSETを指定して実行します
    手順1.で開いているフォルダーに新しい鍵ペアファイル(拡張子無しのファイル)が作成されます。
  5. 手順3で複数のファイルを移動した場合にはファイルを元のフォルダに戻します。
    上書きの確認が出た場合には、上書きしてしまうと破損しているファイルが上書きされてしまうので「いいえ」を選択して上書きしないようにします。

以上の手順で、CryptAcquireContext関数がFALSEを返すことなく処理がされるようになると思います。

NTE_BAD_KEYSETの場合には、上記の鍵ペアが作成されるフォルダ(C:\Users\<ログインしているユーザ名>\AppData\Roaming\Microsoft\Crypto\RSA\S-*-*-*-*-*フォルダ)のアクセス権に問題があるため、共有やセキュリティを確認する必要があります。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です