|
以下の節では、Oracle Tuxedo ATMI アプリケーションのセキュリティをコーディングする方法について説明します。
セキュリティのプログラミングとは、アプリケーション トランザクション モニタ インタフェース (ATMI) アプリケーション用のセキュリティ コードを記述する作業です。アプリケーション プログラマは、プログラムのロジックを表すコードを記述するほか、ATMI を使用して、アプリケーション コードを Oracle Tuxedo トランザクション モニタにリンクします。ATMI プログラミング インタフェースを使用すると、Oracle Tuxedo トランザクション モニタで制御される、アプリケーション クライアントとアプリケーション サーバ間の通信を実現できます。ATMI には、C および COBOL 用の実装があります。
次の図に示すように、アプリケーション プログラマは、ATMI 関数を使用して、ユーザを認証したり、ユーザによるアクセスを制御したり、公開鍵による暗号化の技術をアプリケーションに組み込むことができます。ただし、図が示すとおり、監査およびリンク レベルの暗号化を行うための ATMI 関数は、アプリケーション レベルでは用意されていません。監査は、Oracle Tuxedo のシステム レベルで実行されます。また、リンク レベルの暗号化は、アプリケーション管理者側でコンフィグレーションします。

Oracle Tuxedo システムには、セキュリティのニーズに応じた、さまざまな ATMI 関数が用意されています。
セキュリティ コードを記述するため、アプリケーション プログラマには次の権限が必要です。
必要なライブラリおよびコマンドにアクセスするには、環境内で、TUXCONFIG、TUXDIR、APPDIR、およびその他の環境変数を設定する必要があります。詳細については、『Oracle Tuxedo アプリケーション実行時の管理』の「環境変数の設定」を参照してください。
アプリケーション管理者は、ディレクトリおよびファイルのパーミッションを設定します。必要なパーミッションを取得するには、担当の管理者に問い合わせてください。
クライアント プログラムには、アプリケーションまたはコンピュータ以外からのデータを収集したり、データをメッセージに組み込んだり、処理対象のメッセージをサーバに転送する、という役割があります。ユーザは、現金自動預入支払機 (ATM)、データ入力端末、およびグラフィックス用デバイスなどを使用することにより、クライアント プログラムを利用します。
デフォルトの認証および認可では、5 つのセキュリティ レベルのうち、いずれかをアプリケーションに設定できます。最も低いセキュリティ レベルでは、認証は行われません。最も高いセキュリティ レベルでは、アクセス制御リストの機能により、サービスを実行し、イベントをポストし、アプリケーション キューのメッセージをキューに登録 (または登録解除) するユーザが決定されます。ATMI アプリケーションに対するセキュリティ レベルの設定は、アプリケーション管理者の役割です。
クライアント プログラムを ATMI アプリケーションに参加させるため、アプリケーション プログラマは、次の 2 つのタスクを実行する必要があります。
次の擬似コードは、基本的なクライアント プログラムの動作を示しています。セキュリティ関連の文は太字で示します。
main()
{
tpchkauth() を呼び出してアプリケーションのセキュリティ レベルをチェックget usrname, cltnameアプリケーション パスワードの入力を要求ユーザ固有のパスワードの入力を要求TPINIT バッファを割り当て最初のクライアント ID を TPINIT バッファに格納tpinit() を呼び出してアプリケーションのクライアントとして登録allocate buffer
do while true {
ユーザ入力データをバッファに格納
サービス要求を送信
応答を受信
ユーザに応答を返信 }
アプリケーションを終了
}
上のリスト内の大部分の文は、C または COBOL の ATMI 関数によって実装されます。ただし、ここでは C 言語の実装だけを示しています。
C 言語で記述されたクライアント プログラムは、tpinit(3c) を使用して、ATMI アプリケーションに設定されたセキュリティ レベルに準拠し、アプリケーションに参加します。tpinit() の引数は、TPINIT バッファに対するポインタです。COBOL アプリケーションの場合、クライアント プログラムは TPINITIALIZE(3cbl) を呼び出し、引数として TPINFDEF-REC レコードに対するポインタを取ります。
Oracle Tuxedo システムには、さまざまなアプリケーションに対応できるように記述された一般的なクライアント プログラム用の ATMI 関数が用意されています。クライアントは、この ATMI 関数を使用して、参加先の ATMI アプリケーションに必要なセキュリティ レベルを決定できます。この ATMI 関数は、tpchkauth(3c) (C) または TPCHKAUTH(3cbl) (COBOL) であり、デフォルトの認証および認可を使用する ATMI アプリケーションで実行されます。tpchkauth() 関数および TPCHKAUTH() 関数は、カスタマイズした認証または認可を使用する ATMI アプリケーションでも使用できますが、使用方法は、カスタマイズしたセキュリティ機能がどのように実装されているかに応じて異なります。ここでは、主にデフォルトの認証および認可の場合について説明します。
C を使用するアプリケーション プログラマは、tpchkauth() を使用してアプリケーションのセキュリティ レベルをチェックしてから、tpinit(3c) を呼び出します。これで、クライアント プログラムは、tpinit() 呼び出しに必要な ATMI アプリケーション パスワードとユーザ認証データの入力を要求できます。tpchkauth() は引数なしで呼び出されます。
COBOL を使用するアプリケーション プログラマは、同じ目的で TPCHKAUTH() を使用してから、TPINITIALIZE(3cbl) を呼び出します。TPCHKAUTH(3cbl) と TPINITIALIZE(3cbl) の構文および機能は、tpchkauth(3c) と tpinit(3c) の場合と同じです。
tpchkauth() 関数 (TPCHKAUTH() ルーチン) を呼び出すと、次のいずれかの値が返されます。
TPNOAUTH
TPSYSAUTH
TPINIT バッファ (C の場合) または TPINFDEF-REC レコード (COBOL の場合) のパスワード フィールドに格納します。TPSYSAUTH は、セキュリティ レベルが APP_PW のときに返されます。
TPINIT バッファまたは TPINFDEF-REC レコードに格納されるようにクライアント プログラムを記述します。パスワードは、画面に表示されないようにします。
ud() を使用すると、フィールド化バッファが標準入力から読み取られ、サービスに送信されます。
TPAPPAUTH
TPINIT バッファ (C の場合) または TPINFDEF-REC レコード (COBOL の場合) のデータ フィールド内の認証サービスに渡す値を指定するよう要求されます。TPAPPAUTH は、セキュリティ レベルが USER_AUTH、ACL、または MANDATORY_ACL のときに返されます。
AUTHSVR サーバが提供する、アプリケーションの認証サービスに関するその他の情報を記述して、クライアント プログラムのコードを作成します。AUTHSVR は、クライアント名やユーザ名などのユーザ固有の認証情報を検証して、クライアント プログラムが ATMI アプリケーションに参加できるかどうかを判別するサーバであり、管理者がコンフィグレーションします。
セキュリティが設定された ATMI アプリケーションでは、TPINIT バッファ (C の場合) または TPINFDEF-REC レコード (COBOL の場合) を使用して、Oracle Tuxedo システムにセキュリティ情報を渡す必要があります。TPINIT バッファは、特殊な型付きバッファであり、クライアントが ATMI アプリケーションに参加しようとするときに、クライアントの ID および認証情報をシステムに渡すためにクライアント プログラムで使用されます。COBOL の場合は、TPINFDEF-REC レコードが使用されます。
TPINIT は atmi.h ヘッダ ファイルで定義され、TPINFDEF-REC は COBOL の COPY ファイルで定義されます。次の表は、それぞれの構造体を示しています。
次の表では、TPINIT バッファおよび TPINFDEF-REC レコードのフィールドを示します。
クライアント プログラムは、tpalloc(3c) を呼び出して TPINIT バッファを割り当てます。次は、8 バイトのアプリケーション固有のデータを tpinit() に渡す準備を行い、クライアントが ATMI アプリケーションに参加できるようにするサンプル コードです。
.
.
.
TPINIT *tpinfo;
.
.
.
if ((tpinfo = (TPINIT *)tpalloc("TPINIT",(char *)NULL,
TPINITNEED(8))) == (TPINIT *)NULL){
Error Routine
}
.
.
.
tpinit(tpinfo) /* ATMI アプリケーションに参加する */
.
.
.
ワークステーション クライアントが tpinit() 関数または TPINITIALIZE() ルーチンを呼び出して ATMI アプリケーションに参加すると、次の主なイベントが発生します。
min-max 値を交換します。これらの値は、開始側のワークステーション クライアントと対象側の WSH との間でリンクを確立するために使用されます。LLE については、「リンク レベルの暗号化」を参照してください。TPINIT バッファまたは TPINFDEF-REC レコードから対象側の WSH に転送されると、認証は成功します。usrname、cltname、および flags の 3 つのフィールド値を含む別のバッファを対象側の WSH に送信し、認証済みのワークステーション クライアントに関するこれらの情報が確実に伝わるようにします。
ネイティブ クライアントが tpinit() 関数または TPINITIALIZE() ルーチンを呼び出して ATMI アプリケーションに参加すると、認証だけが行われます。基本的に、ネイティブ クライアントは、自分自身を認証します。
次の図は、ワークステーション クライアントの TPINIT バッファからデータを転送する様子を示します。TPINFDEF-REC レコードからデータを転送する場合にもこの図が当てはまります。

| 注意 : | 上の図に示す認可手順は、ネイティブ クライアントが ATMI アプリケーションに参加しようとする場合も基本的に同じです。ただし、ネットワーク リンクや WSH は無関係です。ネイティブ クライアントは、自分自身を認証するためです。 |
上の図では、デフォルトの認証を使用するか、またはカスタマイズした認証を使用するかにより、Oracle Tuxedo システムに送信される情報が異なる点に注意してください。デフォルトの認証の場合、cltname、grpname、および flags の各フィールドの値が、プラグイン インタフェース以外の方法で、ワークステーション クライアントのデフォルトの認証プラグインに送信されます。一方、カスタマイズした認証の場合、クライアント プログラムの作成者は、これらの値のほか、data フィールドで選択した可変長の別の値を組み込むこともできます。
デフォルトの認証を使用する場合、ワークステーション クライアントの認証プラグインでは、passwd/ PASSWD フィールドが使用され、ネットワーク経由で転送される情報が暗号化されます。このとき、暗号化アルゴリズムとして、56 ビットの DES (Data Encryption Standard) が使用されます。対象側の WSH にある認証プラグインでは、TUXCONFIG ファイルに格納されているアプリケーション パスワードを使用して、この情報を復号化します。ネイティブ クライアントの場合は、単に、passwd/ PASSWD フィールドの値と、TUXCONFIG ファイルに格納されているアプリケーション パスワードが比較されます。
| 注意 : | ワークステーション クライアントでは、passwd/ PASSWD フィールドの値が、認証プラグイン インタフェース以外の方法で、認証プラグインに送信されます。WSH では、TUXCONFIG ファイルに格納されたアプリケーション パスワードが、アプリケーションの起動時に、認証プラグイン インタフェースによって認証プラグインに送信されます。 |
ワークステーション クライアントの認証に成功すると、tpinit() 関数は、最後の処理として、usrname、cltname、および flags の 3 つのフィールド値を含む別のバッファを WSH に送信し、認証済みのワークステーション クライアントに関するこれらの情報が確実に伝わるようにします。TPINITIALIZE() ルーチンの場合も、最後の処理として、同様の情報を含む別のバッファを送信します。カスタマイズした認証プラグインでは、認証手順でこれらの情報が WSH に送信されない場合がありますが、WSH 側ではレポートを作成するとき、つまり tmadmin(1) printclient (pclt) コマンドを呼び出すときにこれらの情報を必要とします。
ワークステーションまたはネイティブ クライアントは、セキュリティ チェックにパスすると、サービス要求を発行したり、応答を受信することができます。
対象の ATMI アプリケーションの SECURITY が NONE に設定されているか、または何も設定されていない場合に、クライアントが、tpinit() または TPINITIALIZE() を呼び出す前にサービス要求 (または ATMI 関数) を呼び出すと、Oracle Tuxedo システムは、NULL パラメータで tpinit() または TPINITIALIZE() を自動的に呼び出します。この操作により、次のような結果になります。
対象の ATMI アプリケーションの SECURITY が APP_PW、USER_AUTH、ACL、または MANDATORY_ACL に設定されている場合に、クライアントが、tpinit() または TPINITIALIZE() を呼び出す前にサービス要求 (または ATMI 関数) を呼び出すと、そのサービス要求は拒否されます。
公開鍵によるセキュリティは、エンド ツー エンドのデジタル署名およびデータの暗号化で構成されています。これらの 2 つの機能は、Oracle Tuxedo の ATMI 関数で実現できます。インターネット上でアプリケーションを使用する場合は、公開鍵でセキュリティ保護された ATMI アプリケーションの方が、保護されていないアプリケーションより安全です。
エンド ツー エンドのデジタル署名とデータの暗号化は、メッセージ ベースのデジタル署名およびメッセージ ベースの暗号化の機能によって実現できます。これらの機能は、PKCS-7 標準に基づいています。PKCS-7 は、RSA Laboratories が主要な通信会社の協力のもとに開発した、PKCS (Public-Key Cryptography Standards) という規格の 1 つです。
メッセージ ベースのデジタル署名では、送信者の ID を特定のメッセージ バッファとバインドすることにより、データの整合性を保ち、送信者がメッセージを送信した事実を否認できないようにします。メッセージ ベースの暗号化では、指定した受信者だけがメッセージを復号化できるため、メッセージの機密性が保たれます。
デジタル署名および暗号化は、ATMI のメッセージ バッファ単位で行われます。したがって、これらの機能は、既存の ATMI のプログラミング インタフェースおよび通信パラダイムと互換性があります。メッセージ バッファは、署名することも暗号化することもできます。メッセージ バッファに関連するデジタル署名の数と暗号化エンベロープの数の間に、関係を成立させる必要はありません。
| 注意 : | 各暗号化エンベロープには、メッセージの受信者を識別し、受信者がメッセージを復号化するために必要な情報が含まれています。 |
公開鍵によるセキュリティの ATMI は、次の処理を行う関数群です。
公開鍵によるセキュリティの ATMI インタフェースには、C および COBOL の 2 つの実装があります。ただし、Oracle Tuxedo の COBOL 言語バインドでは、メッセージ バッファがサポートされません。したがって、個別のバッファに対する明示的な署名、暗号化、およびクエリ操作は、COBOL のアプリケーションでは使用できません。一方、鍵管理のインタフェースでは、COBOL 言語バインドがサポートされているため、AUTOSIGN モードで署名を生成したり、AUTOENCRYPT モードで暗号化エンベロープを生成できます。署名の自動検証機能または自動復号化機能に関するすべての操作は、COBOL のクライアント プロセスおよびサーバ プロセスに適用できます。
| 注意 : | COBOL の TPKEYDEF レコードは、メッセージ ベースのデジタル署名と暗号化操作を実行するための公開鍵とプライベート キーの管理に使用されます。TPKEYDEF レコードの詳細については、『Tuxedo COBOL リファレンス』の紹介部分にある「COBOL 言語 ATMI の戻り値とその他の定義」を参照してください。 |
次の表は、公開鍵によるセキュリティの ATMI をまとめたものです。各関数については、『Oracle Tuxedo C リファレンス』および『Tuxedo COBOL リファレンス』も参照してください。
|
|
|
|
tpkey_close() を使用して直ちに解放してください。
メッセージ ベースのデジタル署名では、エンド ツー エンドの認証が行われ、メッセージの整合性が保たれます。この機能のしくみについては、「ATMI PKCS-7 のエンド ツー エンドのデジタル署名」の図を参照してください。
Oracle Tuxedo のメッセージ バッファにデジタル署名を追加するには、送信側のプロセスまたはユーザがメッセージ バッファに署名します。この署名には、メッセージ バッファの内容から得た、暗号法的に安全なチェックサムと、署名者のローカル クロックに基づいたタイムスタンプが含まれています。
このメッセージ バッファに対するアクセス権がある場合は、署名者の署名が本物であるかどうか、メッセージ バッファの内容が変更されていないかどうか、およびタイムスタンプが検証者のローカル クロックで受け付ける時刻の範囲内かどうかを検証できます。さらに、時間に依存しない、サード パーティによる検証を行うと、メッセージの非否認性を保証できます。つまり、送信側のプロセスまたはユーザは、メッセージを送信した事実を否認したり、メッセージが改ざんされたと主張することはできません。
次のフローチャートでは、署名付きメッセージを送信するコードを記述する手順を示します。

これらの手順およびメッセージ バッファが署名されるしくみについては、以下の節を参照してください。
まず、tpkey_open(3c) 関数または TPKEYOPEN(3cbl) ルーチンを呼び出して、送信側のプロセスが、署名者のプライベート キーおよび関連するデジタル証明書を使用できるようにします。プライベート キーは厳しくセキュリティ保護されているため、プライベート キーを所有することは、署名者の ID を所有することと同等の意味があります。
署名者のプライベート キーにアクセスするため、送信側のプロセスは、署名者として動作する権限があることを証明する必要があります。証明の条件は、公開鍵のプラグイン インタフェースの実装によって異なります。デフォルトの公開鍵の実装では、呼び出しプロセス側が秘密のパスワードを入力する必要があります。
送信側のプロセスが tpkey_open() を呼び出してキー ハンドルをオープンするとき、TPKEY_SIGNATURE フラグまたは TPKEY_AUTOSIGN フラグを指定して、そのキー ハンドルがメッセージ バッファのデジタル署名に使用されることを示します。通常、クライアントは tpinit() を呼び出した後でこの呼び出しを行い、サーバは tpsvrinit() を呼び出して初期化を行うときにこの呼び出しを行います。
TPKEY_AUTOSIGN フラグを使用してキー ハンドルをオープンすると、署名の自動生成が可能になります。以降、送信側のプロセスは、メッセージ バッファが送信されるたびに、メッセージ バッファに自動的に署名します。TPKEY_AUTOSIGN フラグを使用すると、次の 3 つの利点があります。
次のサンプル コードでは、署名者のキー ハンドルをオープンする方法を示します。TPKEY は、atmi.h ヘッダ ファイルで定義される特殊なデータ型です。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY sdo_key;
char *sdo_location;
.
.
.
if (tpkey_open(&sdo_key, “sdo”, sdo_location,
NULL, 0, TPKEY_SIGNATURE) == -1) {
(void) fprintf(stderr, “tpkey_open sdo failed
tperrno=%d(%s)\n”, tperrno, tpstrerror(tperrno));
exit(1);
}
.
.
.
}
署名者のキー ハンドルの情報を取得して、キーの有効性を確認することができます。そのためには、tpkey_getinfo(3c) 関数または TPKEYGETINFO(3cbl) ルーチンを呼び出します。返される情報の中には、暗号サービス プロバイダに固有の情報も含まれていますが、主要な属性は、すべてのプロバイダで共通です。
デフォルトの公開鍵の実装では、メッセージ バッファの署名を計算するための次の署名モードがサポートされています。
メッセージ ダイジェスト アルゴリズムは DIGEST_ALG のキー属性によって制御され、公開鍵署名は SIGNATURE_ALG のキー属性によって制御されます。サポートされている公開鍵のサイズは 512 ~ 2048 ビットであり、安全性とパフォーマンスを実現するためには十分な範囲です。公開鍵のサイズは、SIGNATURE_BITS キー属性によって制御されます。
デフォルトの公開鍵の実装では、上記のアルゴリズムおよびキー サイズの範囲で作成されたデジタル証明書の署名だけが認識されます。
次のサンプル コードでは、署名者のキー ハンドルに関する情報を取得する方法を示します。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY sdo_key;
char principal_name[PNAME_LEN];
long pname_len = PNAME_LEN;
.
.
.
if (tpkey_getinfo(sdo_key, “PRINCIPAL”,
principal_name, &pname_len, 0) == -1) {
(void) fprintf(stdout, “Unable to get information
about principal: %d(%s)\n”,
tperrno, tpstrerror(tperrno));
.
.
.
exit(1);
}
.
.
.
}
署名者のキー ハンドルに関連付けられたオプション属性を設定するには、tpkey_setinfo(3c) 関数または TPKEYSETINFO(3cbl) ルーチンを呼び出します。キー ハンドル属性は、暗号サービス プロバイダによって異なります。
次のサンプル コードでは、署名者のキー ハンドルに関連付けられた情報を変更する方法を示します。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY sdo_key;
static const unsigned char sha1_objid[] = {
0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
};
.
.
.
if (tpkey_setinfo(sdo_key, “DIGEST_ALG”, (void *) sha1_objid,
sizeof(sha1_objid), 0) == -1) {
(void) fprintf(stderr, “tpkey_setinfo failed
tperrno=%d(%s)\n”,
tperrno, tpstrerror(tperrno));
return(1);
}
.
.
.
}
型付きメッセージ バッファを割り当てるには、tpalloc(3c) 関数を呼び出します。続いて、バッファにメッセージを指定します。
メッセージ バッファにデジタル署名のマークを付ける (登録する) には、tpsign(3c) 関数を呼び出します。この関数を呼び出すと、署名者のキー ハンドルのコピーがメッセージ バッファに添付されます。TPKEY_AUTOSIGN フラグを指定してキーをオープンすると、tpsign() を明示的に呼び出さなくても、デジタル署名を添付するメッセージには自動的にマークが付きます。署名パラメータは保存され、後で使用するためにバッファに関連付けられます。
| 注意 : | COBOL のアプリケーションでは、AUTOSIGN 設定のメンバーを使用してデジタル署名を作成します。「TPKEYOPEN(3cbl)」を参照してください。 |
次のサンプル コードは、デジタル署名を添付するメッセージ バッファにマークをつける方法を示しています。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY sdo_key;
char *sendbuf, *rcvbuf;
.
.
.
if (tpsign(sendbuf, sdo_key, 0) == -1) {
(void) fprintf(stderr, “tpsign failed tperrno=%d(%s)\n”,
tperrno, tpstrerror(tperrno));
tpfree(rcvbuf);
tpfree(sendbuf);
tpterm();
(void) tpkey_close(sdo_key, 0);
exit(1);
}
.
.
.
}
メッセージ バッファにデジタル署名のマークを付けた後、以下のいずれかの C 関数または COBOL ルーチンを使用して、メッセージ バッファを送信します。
tpkey_close(3c) 関数または TPKEYCLOSE(3cbl) ルーチンを呼び出して、署名者のキー ハンドルとそれに関連付けられたすべてのリソースを解放します。
デジタル署名の添付は、メッセージ バッファが送信される直前に、公開鍵ソフトウェアによって行われます。デジタル署名されたバッファが複数回送信される場合は、送信のたびに新しい署名が生成されます。したがって、デジタル署名を行うメッセージ バッファにマークを付けた後で、そのメッセージ バッファを変更することができます。
公開鍵ソフトウェアは、次の 3 段階の手順でデジタル署名を生成します。
digest[ ] という表記法は、メッセージ ダイジェスト アルゴリズム (この場合は MD5 または SHA-1) を使用して [ ] 内のハッシュ値が計算されることを示します。{ }key という表記法は、key を使用して { } 内が暗号化または復号化されることを示します。この場合、計算されたハッシュ値は、署名者のプライベート キーを使用して暗号化されます。
デジタル署名には、ローカル システムのクロックに基づいたタイムスタンプが組み込まれます。このようなタイムスタンプを組み込むことにより、受信者が署名を検証するときに、タイムスタンプ値の改ざんが検出されます。さらに、デジタル署名付きメッセージが宛先にルーティングされるとき、そのメッセージにはタイムスタンプのコピーが添付されます。
タイムスタンプは、秒単位まで表記されます。また、タイムスタンプは、PKCS-9 の SigningTime 形式で表記されます。
1 つのメッセージ バッファには、複数の署名を関連付けることができます。つまり、1 つのメッセージ バッファに対して、任意の数の署名者が同時に署名できます。署名できるのは、ユーザまたはプロセスです。各署名者は、自分のプライベート キーを使用してメッセージ バッファに署名します。
署名が異なる場合は、別のメッセージ ダイジェスト アルゴリズムまたはデジタル署名アルゴリズムを使用している可能性があります。同じメッセージ ダイジェストおよびデジタル署名アルゴリズムを使用した署名が 2 つある場合、ハッシュ値はどちらか 1 つだけに対してだけ計算されます。
デジタル署名付きのメッセージ バッファは、SignedData というメッセージ タイプのバージョン 1 として、PKCS-7 形式で表現されます。Oracle Tuxedo システムで使用されるメッセージ タイプ SignedData は、次の項目で構成されます。
次の図に示すように、メッセージの内容は、SignedData というメッセージ タイプによって包含されています。

署名付きメッセージ バッファを受信するための ATMI アプリケーション コードは必要ありません。公開鍵ソフトウェアは、添付されたデジタル署名を自動的に検証し、そのメッセージを受信側のプロセスに渡します。
受信側のプロセスの代わりに動作する公開鍵ソフトウェアは、署名付きメッセージ バッファを受信すると、次のタスクを実行します。
| 注意 : | 添付されたデジタル署名をどれも検証できない場合、受信側のプロセスは、メッセージ バッファを受け取りません。さらに、受信側のプロセスは、メッセージ バッファをまったく認識しません。 |
公開鍵ソフトウェアは、クライアント プロセス、サーバ プロセス、またはメッセージ バッファの内容を読み取るシステム プロセスに署名付きメッセージ バッファがあると、メッセージに添付されたデジタル署名を自動的に検証します。ただし、パイプ役として機能するシステム プロセス (メッセージの内容は読み取らない) の場合、メッセージに添付されたデジタル署名は検証されません。たとえば、ブリッジおよびワークステーション ハンドラ (WSH) は、パイプ役として機能するシステム プロセスの例です。
署名に記録されたタイムスタンプは、非同期のクロックに基づいているため、特に、PC またはパーソナル コンピュータで署名が行われた場合は、完全に信頼できません。ただし、遠い過去または将来を示すタイムスタンプが記録された要求を、サーバサイドで拒否することができます。タイムスタンプに基づいて要求を拒否する機能を使用すると、リプレイ攻撃から保護することができます。
メッセージ バッファが入力パラメータとして ATMI 関数 (tpacall() など) に渡された場合、公開鍵ソフトウェアは、メッセージにあらかじめ添付された署名を検証してから、メッセージを転送します。この動作によって、複数のプロセスからの署名を付けた情報を、安全かつ確実に転送することができます。
サーバサイドで、受信したメッセージ バッファを変更して転送すると、元の署名は無効になります。この場合、公開鍵ソフトウェアは、無効な署名を検出して破棄します。このプロセスの例については、「入力バッファの暗号化エンベロープを破棄する」を参照してください。
メッセージ バッファが出力パラメータとして ATMI 関数 (tpgetreply() など) に渡された場合、公開鍵ソフトウェアは、このバッファに関連付けられた署名の情報を削除します。削除する情報には、保留中の署名 (メッセージ バッファに登録された署名)、およびバッファを前回使用したユーザの署名が含まれます。
この操作が正常に終了すると、新しい署名の情報が新しいバッファの内容に関連付けられる場合があります。
メッセージ ベースの暗号化では、エンド ツー エンドでデータの機密性が保たれます。この機能のしくみについては、「ATMI PKCS-7 のエンド ツー エンドの暗号化」の図を参照してください。
メッセージは、送信側のプロセスを離れる直前に暗号化され、その状態は受信側のプロセスで受信されるまで保持されます。メッセージは、オペレーティング システムのメッセージ キュー、システム プロセス、ディスク ベース キューなどの中継ポイントのほか、サーバ間のネットワーク リンクで転送される間もオペークです。
次のフローチャートでは、暗号化されたメッセージを送信するコードを記述する手順を示します。

これらの手順およびメッセージ バッファが暗号化されるしくみについては、以下の節を参照してください。
まず、tpkey_open(3c) 関数または TPKEYOPEN(3cbl) ルーチンを呼び出して、送信側のプロセスが、対象受信者のデジタル証明書を使用できるようにします。対象受信者とは、クライアント、サービス、サーバ グループ、ゲートウェイ グループ、サーバ マシン、または複数のサーバを含むドメイン全体のことです。
送信側のプロセスが tpkey_open() を呼び出してキー ハンドルをオープンするとき、TPKEY_ENCRYPT フラグまたは TPKEY_AUTOENCRYPT フラグを指定して、そのキー ハンドルがメッセージ バッファの暗号化に使用されることを示します。通常、クライアントは tpinit() を呼び出した後でこの呼び出しを行い、サーバは tpsvrinit() を呼び出して初期化を行うときにこの呼び出しを行います。
TPKEY_AUTOENCRYPT フラグを使用してキー ハンドルをオープンすると、暗号化の自動処理が可能になります。以降、送信側のプロセスは、メッセージ バッファが送信されるたびに、メッセージ バッファを自動的に暗号化します。TPKEY_AUTOENCRYPT フラグを使用すると、次の 3 つの利点があります。
次のサンプル コードでは、暗号化キー ハンドルをオープンする方法を示します。TPKEY は、atmi.h ヘッダ ファイルで定義される特殊なデータ型です。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY tu_key;
.
.
.
if (tpkey_open(&tu_key, “TOUPPER”, NULL,
NULL, 0, TPKEY_ENCRYPT) == -1) {
(void) fprintf(stderr, “tpkey_open tu failed
tperrno=%d(%s)\n”, tperrno, tpstrerror(tperrno));
exit(1);
}
.
.
.
}
暗号化キー ハンドルの情報を取得して、キーの有効性を確認することができます。そのためには、tpkey_getinfo(3c) 関数または TPKEYGETINFO(3cbl) ルーチンを呼び出します。返される情報の中には、暗号サービス プロバイダに固有の情報も含まれていますが、主要な属性は、すべてのプロバイダで共通です。
デフォルトの公開鍵の実装では、バルク データを暗号化するための 3 つのアルゴリズムがサポートされています。
暗号化のレベルは、ENCRYPT_BITS のキー属性によって制御され、アルゴリズムは ENCRYPT_ALG のキー属性によって制御されます。ENCRYPT_ALG で固定キー長によるアルゴリズムが設定されると、ENCRYPT_BITS の値が自動的に調整されます。
次のサンプル コードでは、暗号化キー ハンドルに関する情報を取得する方法を示します。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY tu_key;
char principal_name[PNAME_LEN];
long pname_len = PNAME_LEN;
.
.
.
if (tpkey_getinfo(tu_key, “PRINCIPAL”,
principal_name, &pname_len, 0) == -1) {
(void) fprintf(stdout, “Unable to get information
about principal: %d(%s)\n”,
tperrno, tpstrerror(tperrno));
.
.
.
exit(1);
}
.
.
.
}
暗号化キー ハンドルに関連付けられたオプション属性を設定するには、tpkey_setinfo(3c) 関数または TPKEYSETINFO(3cbl) ルーチンを呼び出します。キー ハンドル属性は、暗号サービス プロバイダによって異なります。
次のサンプル コードでは、暗号化キー ハンドルに関連付けられた情報を変更する方法を示します。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY tu_key;
static const unsigned char rc2_objid[] = {
0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02
};
.
.
.
if (tpkey_setinfo(tu_key, “ENCRYPT_ALG”, (void *) rc2_objid,
sizeof(rc2_objid), 0) == -1) {
(void) fprintf(stderr, “tpkey_setinfo failed
tperrno=%d(%s)\n”,
tperrno, tpstrerror(tperrno));
return(1);
}
.
.
.
}
型付きメッセージ バッファを割り当てるには、tpalloc(3c) 関数を呼び出します。続いて、バッファにメッセージを指定します。
メッセージ バッファに暗号化のマークを付ける (登録する) には、tpseal(3c) 関数を呼び出します。この関数を呼び出すと、暗号化キー ハンドルのコピーがメッセージ バッファに添付されます。TPKEY_AUTOENCRYPT フラグを使用してキーをオープンすると、tpseal() を明示的に呼び出さなくても、暗号化するメッセージには自動的にマークが付きます。
| 注意 : | COBOL のアプリケーションでは、AUTOENCRYPT 設定のメンバーを使用してメッセージ バッファを暗号化します。「TPKEYOPEN(3cbl)」を参照してください。 |
次のサンプル コードは、暗号化するメッセージ バッファにマークを付ける方法を示しています。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY tu_key;
char *sendbuf, *rcvbuf;
.
.
.
if (tpseal(sendbuf, tu_key, 0) == -1) {
(void) fprintf(stderr, “tpseal failed tperrno=%d(%s)\n”,
tperrno, tpstrerror(tperrno));
tpfree(rcvbuf);
tpfree(sendbuf);
tpterm();
(void) tpkey_close(tu_key, 0);
exit(1);
}
.
.
.
}
メッセージ バッファに暗号化のマークを付けた後、以下のいずれかの C 関数または COBOL ルーチンを使用して、メッセージ バッファを送信します。
tpkey_close(3c) 関数または TPKEYCLOSE(3cbl) ルーチンを呼び出して、暗号化キー ハンドルとそれに関連付けられたすべてのリソースを解放します。
公開鍵ソフトウェアは、メッセージ バッファが送信される直前に、メッセージを暗号化して暗号化エンベロープを添付します。暗号化エンベロープにより、対象受信者はメッセージを復号化できます。封印されたバッファが複数回送信される場合は、送信のたびに暗号化が実行されます。したがって、暗号化するメッセージ バッファにマークを付けた後で、そのメッセージ バッファを変更することができます。
公開鍵ソフトウェアは、次の手順に従って、メッセージ バッファの内容を暗号化し、暗号化メッセージの受信者用の暗号化エンベロープを生成します。
{ }key という表記法は、key を使用して { } 内が暗号化または復号化されることを示します。ステップ 1 では、セッション キーを使用してメッセージ バッファが暗号化され、ステップ 2 では、受信者の公開鍵を使用してセッション キーが暗号化されます。
1 つのメッセージ バッファには、複数の暗号化エンベロープを関連付けることができます。つまり、異なるプライベート キーを持つ複数の受信者が、暗号化されたメッセージを受信し、復号化することができます。受信者となるのは、ユーザまたはプロセスです。メッセージが複数の受信者に対して暗号化されると、メッセージは一度だけ暗号化されますが、セッション キーは各受信者の公開鍵で暗号化されます。暗号化されたメッセージには、すべての暗号化エンベロープが添付されます。
1 つのメッセージ バッファに複数の暗号化エンベロープが関連付けられた場合、すべての暗号化エンベロープは、そのアルゴリズムに対して同じ対称鍵アルゴリズムと同じキー サイズを使用しなければなりません。
暗号化されたメッセージ バッファは、EnvelopedData というメッセージ タイプのバージョン 0 として、PKCS-7 形式で表現されます。Oracle Tuxedo システムで使用されるメッセージ タイプ EnvelopedData は、次の項目で構成されます。
次の図は、EnvelopedData メッセージ タイプの場合のエンベロープの階層を示します。SignedData メッセージ タイプは、メッセージに 1 つまたは複数のデジタル署名が関連付けられている場合にのみ、この階層に含まれます。

上の図に示すように、メッセージ バッファは、署名することも暗号化することもできます。メッセージ バッファに関連するデジタル署名の数と暗号化エンベロープの数の間に、関係を成立させる必要はありません。
メッセージ バッファに対して署名と暗号化の両方が実行されると、まず、暗号化されていないデータに対する署名が生成されます。次に、添付される署名の数および署名者の ID が、バルク データの暗号化機能により暗号化されます。
| 注意 : | 署名を検証する前に、メッセージのデータを復号化するための適切な復号化キーを使用できる状態にしておく必要があります。 |
暗号化されたメッセージを受信するためのコードを記述するには、次の手順に従います。
tpkey_open() を呼び出して、対象受信者のキー ハンドルをオープンします。tpkey_open を呼び出すと、受信者のプライベート キーおよびデジタル証明書に対するキー ハンドルが返されます。tpkey_getinfo() を呼び出して、復号化キー ハンドルに関する情報を取得します。tpkey_setinfo() を呼び出して、復号化キー ハンドルに関連付けられた情報を変更します。tpkey_close() を呼び出して、復号化キー ハンドルをクローズします。tpkey_close() を呼び出すと、キー ハンドルとそれに関連付けられたすべてのリソースが解放されます。
これらの手順およびメッセージ バッファが復号化されるしくみについては、以下の節を参照してください。
まず、tpkey_open(3c) 関数または TPKEYOPEN(3cbl) ルーチンを呼び出して、受信側のプロセスが、対象受信者のプライベート キーおよび関連するデジタル証明書を使用できるようにします。受信側のプロセスとは、クライアント、サービス、サーバ グループ、ゲートウェイ グループ、サーバ マシン、または複数のサーバを含むドメイン全体のことです。
アプリケーション管理者は、ATMI アプリケーションの UBBCONFIG ファイルをコンフィグレーションして、ATMI アプリケーションの起動時に復号化キー ハンドルを自動的にオープンするように指定できます。この方法では、サーバごとに使用できる復号化キー ハンドルは 1 つだけです。詳細については、「プラグインによる復号化キーの初期化」を参照してください。
起動時に受信側のプロセスの復号化キー ハンドルをオープンするように ATMI アプリケーションがコンフィグレーションされていない場合、受信側のプロセスは自身で tpkey_open() を呼び出します。または、受信側のプロセスは、別の tpkey_open() を呼び出して、別の復号化キー ハンドルをオープンすることもできます。
対象受信者のプライベート キーにアクセスするため、受信側のプロセスは、対象受信者として動作する権限があることを証明する必要があります。証明の条件は、公開鍵のプラグイン インタフェースの実装によって異なります。デフォルトの公開鍵の実装では、呼び出しプロセス側が秘密のパスワードを入力する必要があります。
受信側のプロセスが tpkey_open() を呼び出してキー ハンドルをオープンするとき、TPKEY_DECRYPT フラグを指定して、そのハンドルがメッセージ バッファの復号化に使用されることを示します。通常、クライアントは tpinit() を呼び出した後でこの呼び出しを行い、サーバは tpsvrinit() を呼び出して初期化を行うときにこの呼び出しを行います。
次のサンプル コードでは、復号化キー ハンドルをオープンする方法を示します。TPKEY は、atmi.h ヘッダ ファイルで定義される特殊なデータ型です。
TPKEY tu_key;
tpsvrinit(argc, argv)
int argc;
char **argv;
#endif
{
char *tu_location;
.
.
.
if (tpkey_open(&tu_key, “TOUPPER”, tu_location,
NULL, 0, TPKEY_DECRYPT) == -1) {
userlog(“Unable to open private key: %d(%s)”,
tperrno, tpstrerror(tperrno));
return(-1)
}
.
.
.
}
復号化キー ハンドルの情報を取得して、キーの有効性を確認することができます。そのためには、tpkey_getinfo(3c) 関数または TPKEYGETINFO(3cbl) ルーチンを呼び出します。返される情報の中には、暗号サービス プロバイダに固有の情報も含まれていますが、主要な属性は、すべてのプロバイダで共通です。
次のサンプル コードでは、復号化キー ハンドルに関する情報を取得する方法を示します。
TPKEY tu_key;
tpsvrinit(argc, argv)
int argc;
char **argv;
#endif
{
char principal_name[PNAME_LEN];
long pname_len = PNAME_LEN;
.
.
.
if (tpkey_getinfo(tu_key, “PRINCIPAL”,
principal_name, &pname_len, 0) == -1) {
(void) fprintf(stdout, “Unable to get information
about principal: %d(%s)\n”,
tperrno, tpstrerror(tperrno));
.
.
.
exit(1);
}
.
.
.
}
復号化キー ハンドルに関連付けられたオプション属性を設定するには、tpkey_setinfo(3c) 関数または TPKEYSETINFO(3cbl) ルーチンを呼び出します。キー ハンドル属性は、暗号サービス プロバイダによって異なります。
次のサンプル コードでは、復号化キー ハンドルに関連付けられた情報を変更する方法を示します。
TPKEY tu_key;
tpsvrinit(argc, argv)
int argc;
char **argv;
#endif
{
TM32U mybits = 128;
.
.
.
if (tpkey_setinfo(tu_key, “ENCRYPT_BITS”, &mybits,
sizeof(mybits), 0) == -1) {
(void) fprintf(stderr, “tpkey_setinfo failed
tperrno=%d(%s)\n”,
tperrno, tpstrerror(tperrno));
return(1);
}
.
.
.
}
tpkey_close(3c) 関数または TPKEYCLOSE(3cbl) ルーチンを呼び出して、復号化キー ハンドルとそれに関連付けられたすべてのリソースを解放します。
公開鍵ソフトウェアは、Oracle Tuxedo のクライアント プロセス、サーバ プロセス、またはメッセージ バッファの内容を読み取るシステム プロセスに暗号化されたメッセージ バッファがあると、そのメッセージ バッファを自動的に復号化します。復号化の自動処理を成功させるには、受信側のプロセスで、添付された暗号化エンベロープのいずれかで指定されている復号化キー (TPKEY_DECRYPT) をオープンしておく必要があります。
受信側のプロセスの代わりに動作する公開鍵ソフトウェアは、暗号化されたメッセージ バッファを受信すると、次のタスクを実行します。
| 注意 : | 添付されたデジタル署名をどれも検証できない場合、または、メッセージ バッファを復号化できない場合、受信側のプロセスはメッセージ バッファを受け取りません。さらに、受信側のプロセスは、メッセージ バッファをまったく認識しません。 |
ただし、パイプ役として機能するシステム プロセス (メッセージの内容は読み取らない) の場合、メッセージは復号化されません。たとえば、ブリッジおよびワークステーション ハンドラ (WSH) は、パイプ役として機能するシステム プロセスの例です。
WSH は、パイプ役の特殊な例です。データ依存型ルーティング用にコンフィグレーションされた WSH は、メッセージ バッファを受信するとそれを読み取り、バッファのルーティング方法を決定します。つまり、まず、公開鍵ソフトウェアは、受信したメッセージ バッファのコピーを作成し、そのコピーを復号化して WSH に渡します。WSH は、復号化されたコピーを解析し、そのメッセージ バッファをルーティングする方法を決定すると、元のメッセージ バッファをそのまま適切なサーバにルーティングします。データ依存型ルーティングと公開鍵セキュリティとの相互運用の詳細については、「データ依存型ルーティングとの互換性および相互運用性」を参照してください。
メッセージ バッファが入力パラメータとして ATMI 関数 (tpacall() など) に渡された場合、公開鍵ソフトウェアは、メッセージにあらかじめ添付された暗号化エンベロープを破棄します。この機能により、中継プロセスで変更された元のメッセージが、対象受信者側で受け取られないようにすることができます。
このプロセスの例として、次の図に示すシナリオを考えてみます。

この例は、Manager という名前のサーバ プロセスが、Employee というクライアント プロセスから、暗号化された署名付きメッセージ バッファを受信する様子を示しています。サーバは、受信したメッセージ バッファを復号化して読み取った後で、Purchasing サービス用に署名および封印し、Purchasing に送信します。
WSH プロセスには、データ依存型ルーティングがコンフィグレーションされています。これについては、「メッセージ バッファの復号化方法」を参照してください。公開鍵ソフトウェアは、WSH プロセスで既にオープンした復号化キーを使用して、受信したメッセージ バッファのコピーを復号化します。次に、復号化したメッセージのコピーを WSH に渡します。WSH は、復号化されたコピーを解析してから、受信したメッセージ バッファをそのまま Manager プロセスに転送します。
WSH プロセスにデータ依存型ルーティングがコンフィグレーションされていない場合、Employee プロセスは、WSH プロセスのメッセージ バッファに対して tpseal() を呼び出す必要はありません。また、WSH プロセスも復号化キーをオープンする必要はありません。
データ依存型ルーティングがコンフィグレーションされているかどうかにかかわらず、WSH はデジタル署名の検証を行いません。
Manager プロセスで受け取られると、公開鍵ソフトウェアは次の操作を行います。Manager は、tpenvelope() を繰り返し呼び出して、メッセージ バッファに関連付けられたデジタル署名と暗号化の情報を調べます。tpenvelope() からは、次の情報が返されます。Manager は、署名者の公開鍵を引数に指定して tpkey_getinfo() を呼び出し、署名者に関するさらに詳しい情報 (プリンシパル名など) を取得します。Manager は、署名者を確認し、Employee からの要求 (メッセージで指定) が有効であると判断すると、次の操作を行います。
公開鍵ソフトウェアは、メッセージが送信される直前に、次のタスクを実行します。
メッセージ バッファが出力パラメータとして ATMI 関数 (tpgetrply() など) に渡された場合、公開鍵ソフトウェアは、このバッファに関連付けられた暗号化の情報を削除します。削除する情報には、保留中の署名 (メッセージ バッファに登録された署名)、およびバッファを前回使用したユーザの署名が含まれます。
この操作が正常に終了すると、新しい暗号化の情報が、新しいバッファの内容に関連付けられる場合があります。
プロセスは、対象のメッセージ バッファを引数に指定して tpenvelope() 関数を呼び出すことにより、この情報を取得します。tpenvelope() については、『Oracle Tuxedo C リファレンス』の tpenvelope(3c) リファレンス ページを参照してください。
デジタル署名登録要求、デジタル署名、暗号化登録要求、およびメッセージ バッファに関連付けられている暗号化エンベロープの複数のオカレンスが同時に存在することがあります。これらのオカレンスは順番に格納され、最初の項目が 0 位置に、以降の項目は 0 に続く連続する位置に格納されます。tpenvelope() の occurrence 入力パラメータは、要求された項目を示します。occurrence の値が最後の項目の位置を過ぎると、tpenvelope() は TPENOENT エラー状態で異常終了します。TPENOENT が返されるまで tpenvelope() を繰り返し呼び出すことにより、すべての項目を調べることができます。
送信側のプロセスでは通常、デジタル署名および暗号化の情報は、メッセージが送信されるまで保留状態になっています。受信プロセスでは、デジタル署名が確認され、暗号化と復号化も既に行われています。
送信側のプロセスが発信メッセージ バッファを引数として tpenvelope() を呼び出すと、tpenvelope() は次のレポートを作成します。
TPSIGN_PENDING です。送信側のプロセスは、tpsign(3c) 関数を呼び出して、デジタル署名要求を明示的に登録します。TPSIGN_PENDING です。送信側のプロセスは、TPKEY_AUTOSIGN フラグを指定して tpkey_open(3c) を呼び出し、デジタル署名要求を暗黙的に登録します。TPSEAL_PENDING です。送信側のプロセスは、tpseal(3c) 関数を呼び出して、暗号化要求を明示的に登録します。TPSEAL_PENDING です。送信側のプロセスは、TPKEY_AUTOENCRYPT フラグを指定して tpkey_open() を呼び出し、暗号化要求を暗黙的に登録します。
tpenvelope() は、ステータスの情報のほか、デジタル署名または暗号化の登録要求に関連付けられたキー ハンドルも返します。プロセスは、キー ハンドルを引数として tpkey_getinfo(3c) 関数を呼び出し、キー ハンドルに関する詳しい情報を取得できます。
プロセスがメッセージ バッファを受信するときは、メッセージの内容だけを受信します。メッセージ バッファに関連付けられているデジタル署名や暗号化エンベロープは受信しません。受信側のプロセスは、tpenvelope() を呼び出して、添付されたデジタル署名や暗号化エンベロープに関する情報を取得する必要があります。
受信側のプロセスが受信メッセージ バッファを引数として tpenvelope() を呼び出すと、tpenvelope() は次のレポートを作成します。
TPSIGN_OKTPSIGN_TAMPERED_MESSAGE
メッセージ バッファの内容が変更されたため、デジタル署名は無効です。
TPSIGN_TAMPERED_CERT
署名者のデジタル証明書が変更されたため、デジタル署名は無効です。
TPSIGN_REVOKED_CERT
署名者のデジタル証明書が取り消されたため、デジタル署名は無効です。
TPSIGN_POSTDATED
タイムスタンプが遠い将来の時刻を示しているため、デジタル署名は無効です。
TPSIGN_EXPIRED_CERT
署名者のデジタル証明書の有効期限が切れたため、デジタル署名は無効です。
TPSIGN_EXPIREDTPSIGN_UNKNOWNTPSEAL_OKTPSEAL_TAMPERED_CERT
対象受信者のデジタル証明書が変更されたため、暗号化エンベロープは無効です。対象受信者は、メッセージ バッファを受信しません。
TPSEAL_REVOKED_CERT
対象受信者のデジタル証明書が取り消されたため、暗号化エンベロープは無効です。対象受信者は、メッセージ バッファを受信しません。
TPSEAL_EXPIRED_CERT
対象受信者のデジタル証明書の有効期限が切れたため、暗号化エンベロープは無効です。対象受信者は、メッセージ バッファを受信しません。
TPSEAL_UNKNOWN
対象受信者のデジタル証明書が不明な認証局 (CA) から発行されたため、暗号化エンベロープは無効です。対象受信者は、メッセージ バッファを受信しません。
tpenvelope() は、ステータスの情報のほか、デジタル署名または暗号化エンベロープに関連付けられたキー ハンドルも返します。プロセスは、キー ハンドルを引数として tpkey_getinfo(3c) 関数を呼び出し、キー ハンドルに関する詳しい情報を取得できます。
受信側のプロセスが、メッセージ バッファを受信した後で tpsign() を呼び出してデジタル署名要求を登録した場合、tpenvelope() は登録のステータスを TPSIGN_PENDING としてレポートします。同様に、受信側のプロセスが、メッセージ バッファを受信した後で tpseal() を呼び出して暗号化 (封印) 要求を登録した場合は、tpenvelope() は登録のステータスを TPSEAL_PENDING としてレポートします。
受信側のプロセスが署名付きメッセージ バッファを受信した後でその内容を変更すると、添付された署名は無効になります。その結果、tpenvelope() は署名を検証できないため、TPSIGN_TAMPERED_MESSAGE という署名ステータスをレポートします。
メッセージ バッファに複数のデジタル署名がある場合、公開鍵ソフトウェアは、tpenvelope() と同等の内部関数を呼び出して、各デジタル署名の状態を調べます。次に、特定の規則に従い、複数のデジタル署名の状態を合成した「コンポジット署名ステータス」を生成します。次の表は、コンポジット署名ステータスを生成する規則を示しています。
TPSIGN_OK または TPSIGN_UNKNOWN のコンポジット署名ステータスが付いていないメッセージ バッファは、受信されても破棄され、受信されなかったように扱われます。ATMI アプリケーションの UBBCONFIG ファイルの SIGNATURE_REQUIRED パラメータが Y (はい) に設定されている場合は、TPSIGN_OK のコンポジット署名ステータスが付いていないメッセージ バッファを受信しても破棄され、受信されなかったように扱われます。詳細については、「受信メッセージに対する署名ポリシーの適用」を参照してください。
ただし、前の段落で説明した署名付きメッセージ バッファの処理の例外は、tpimport(3c) 関数です。tpimport(3c) 関数は、コンポジット署名ステータスとは関係なく、受信したメッセージ バッファを送信します。
次のサンプル コードは、tpenvelope() を使用して、メッセージ バッファに関連付けられているデジタル署名と暗号化の情報を調べる方法を示します。
main(argc, argv)
int argc;
char *argv[];
#endif
{
TPKEY tu_key;
TPKEY sdo_key;
TPKEY output_key;
char *sendbuf, *rcvbuf;
int ret;
int occurrence = 0;
long status;
char principal_name[PNAME_LEN];
long pname_len = PNAME_LEN;
int found = 0;
.
.
.
output_key = NULL;
ret = tpenvelope(rcvbuf, 0, occurrence, &output_key,
&status, NULL, 0); while (ret != -1) {
if (status == TPSIGN_OK) {
if (tpkey_getinfo(output_key, “PRINCIPAL”,
principal_name, &pname_len, 0) == -1) {
(void) fprintf(stdout, “Unable to get information
about principal: %d(%s)\n”,
tperrno, tpstrerror(tperrno));
tpfree(sendbuf);
tpfree(rcvbuf);
tpterm();
(void) tpkey_close(tu_key, 0);
(void) tpkey_close(sdo_key, 0);
(void) tpkey_close(output_key, 0);
exit(1);
}/* リソースを必ず解放する */
(void) tpkey_close(output_key, 0);
output_key = NULL;
found = 1;
break;
}
/* リソースを必ず解放する */
(void) tpkey_close(output_key, 0);
output_key = NULL;
occurrence++;
ret = tpenvelope(rcvbuf, 0, occurrence, &output_key,
&status, NULL, 0);
}
.
.
.
}
外部化された表現とは、通常はバッファが送信される直前にメッセージ バッファに追加される Oracle Tuxedo のヘッダ情報が含まれないメッセージ バッファのことです。署名付きメッセージ バッファを外部化された表現に変換すると、署名付きデータを「パス スルー (通過)」させたり、署名付きバッファを長期間保存しておき、バッファ送信した事実を否認できないようにすることができます。また、復号化キーを使用しないで、暗号化されたメッセージ バッファを中継プロセス経由で伝送することもできます。
プロセスは、tpexport(3c) 関数を呼び出して、型付きメッセージ バッファを外部化された表現に変換します。メッセージ バッファに関連付けられた保留状態の署名は、そのメッセージ バッファが ATMI 関数によって別のプロセスに送信された場合のように、tpexport() が呼び出されたときに生成されます。同様に、メッセージ バッファに関連付けられた保留中の封印は、そのメッセージ バッファが ATMI 通信関数によって別のプロセスに送信された場合のように、tpexport() が呼び出されたときに生成されます。
外部化された表現のメッセージ バッファは、バイナリ形式の PKCS-7 形式で保存されます。文字列で指定する必要がある場合、呼び出しプロセスは、TPEX_STRING フラグを指定して tpexport() を呼び出す必要があります。
| 注意 : | 外部化された表現の型付きメッセージ バッファを作成する機能は、公開鍵セキュリティにユニークなものではありません。プロセスは、tpexport() を呼び出して型付きメッセージ バッファを外部化することができます。メッセージ バッファに対してデジタル署名または暗号化のマークが付けられているかどうかは無関係です。 |
受信側のプロセスは、tpimport(3c) 関数を呼び出して、外部化された表現のメッセージ バッファを型付きメッセージ バッファに変換します。tpimport() 関数も、必要に応じて復号化を行い、関連するデジタル署名があれば検証します。
次のサンプル コードは、tpexport() を使用して型付きメッセージ バッファを外部化された表現に変換する方法、および tpimport() を使用して外部化された表現を型付きメッセージ バッファに戻す方法を示します。
static void hexdump _((unsigned char *, long));
#define MAX_BUFFER 80000
main(argc, argv)
int argc;
char *argv[];
#endif
{
char *databuf;
char exportbuf[MAX_BUFFER];
long exportbuf_size = 0;
char *importbuf = NULL;
long importbuf_size = 0;
int go_on = 1;
.
.
.
exportbuf_size = 0;
while (go_on == 1) {
if (tpexport(databuf, 0, exportbuf, &exportbuf_size, 0)
== -1) {
if (tperrno == TPELIMIT) {
printf(“%d tperrno is TPELIMIT, exportbuf_size=%ld\n”,
__LINE__, exportbuf_size);
if (exportbuf_size > MAX_BUFFER) {
return(1);
}
}
else {
printf(“tpexport(%d) failed: tperrno=%d(%s)\n”,
__LINE__, tperrno, tpstrerror(tperrno));
return(1);
}
}
else {
go_on = 0;
}
}
.
.
.hexdump((unsigned char *) exportbuf, (long) exportbuf_size);
if (tpimport(exportbuf, exportbuf_size, &importbuf,
&importbuf_size, 0) == -1) {
printf(“tpimport(%d) failed: tperrno=%d(%s)\n”,
__LINE__, tperrno, tpstrerror(tperrno));
return(1);
}
.
.
.
}
|