私は恐ろしい X9.24 仕様の研究に多くの時間を費やしましたが、最終的にベンダーの例で暗号化と復号化の両方が機能するようになり、マーケティングはすぐにベンダーを切り替えることを決定しました。それは標準なので、誰の実装も同じだと思うでしょう。私は望む。とにかく、物事の実装方法にはバリエーションがあります。細字を勉強して、反対側と同じように作業していることを確認する必要があります。
しかし、それはあなたの質問ではありません。
まず、クレジット カードからデータ トラックを解読する必要がある場合、元の超秘密の Base Derivation Key に基づいてデータを解読するキーを作成することに関心があるでしょう。これは MAC の生成とは何の関係もなく、その恐ろしい仕様を渡す際にのみ言及されています。そのキー シリアル番号とデバイス ID の IPEK を生成し、HSM からの完全なキー シリアル番号のカウンター部分にビットが設定されている場合は、仕様から「非可逆キー生成プロセス」を繰り返し適用する必要があります。
私のコードのその部分は次のようになります: (投稿での長いリストについては申し訳ありません。)
/*
* Bit "zero" set (this is a 21 bit register)(ANSI counts from the left)
* This will be used to test each bit of the encryption counter
* to decide when to find another key.
*/
testBit=0x00100000;
/*
* We have to "encrypt" the IPEK repeatedly to find the current key
* (See Section A.3). Each time we encrypt (generate a new key),
* we need to use the all prior bits to the left of the current bit.
* The Spec says we will have a maximum of ten bits set at any time
* so we should not have to generate more than ten keys to find the
* current encryption key.
*/
cumBits=0;
/*
* For each of the 21 possible key bits,
* if it is set, we need to OR that bit into the cumulative bit
* variable and set that as the KSN count and "encrypt" again.
* The encryption we are using the goofy ANSI Key Generation
* subroutine from page 50.
*/
for(int ii=0; ii<21; ii++)
{
if( (keyNumber&testBit) != 0)
{
char ksr[10];
char eightByte[8]={0};
cumBits |= testBit;
ksn.count=cumBits; /* all bits processed to date */
memcpy(ksr, &ksn,10); /* copy bit structure to char array*/
memcpy(crypt,&ksr[2],8); /* copy bytes 2 through 9 */
/*
* Generate the new Key overwriting the old.
* This will apply the "Non-reversible Key Generation Process"
* to the lower 64 bits of the KSN.
*/
keyGen(&key, &crypt, &key);
}
testBit>>=1;
}
keyNumber は ksn からの現在のカウンターです ksn は、HSM crypt からの 80 ビット キー シリアル番号を含む 80 ビット構造です 64 ビット データ ブロックです 私は openSSL を使用しているので、DES_cblock 型を持っています。key は 128 ビットの double DES_cblock 構造体です。keyGen ルーチンは、仕様の 50 ページにある「非可逆鍵生成プロセス」ローカル サブルーチンからほぼそのままです。
この最後に、キー変数には、復号化に使用できるキーがほとんど含まれます。仕様を書いた男たちは、私たちを緊張させないように、いくつかの「バリアント」動作をキーに追加しました。キーをクレジット カード トラックなどのデータ ストリームの復号化に使用する場合は、バイト 5 と 13 を 0xFF で XOR し、トリプル DES でキー自体を暗号化する必要があります (ECB モード)。私のコードは次のようになります:
DOUBLE_KEY keyCopy;
char *p;
p=(char*)&key;
p[ 5]^=0xff;
p[13]^=0xff;
keyCopy=key;
des3(&keyCopy, (DES_cblock *)&key.left, &key.left);
des3(&keyCopy, (DES_cblock *)&key.right, &key.right);
これを使用して PIN ブロックを復号化する場合は、バイト 7 と 15 を 0xFF で XOR する必要があります。(これがストリーム モードにも適用されるべきではないことは 100% 確信が持てませんが、私のベンダーは除外しています。)
PIN ブロックの場合は、ECB モードの 3-DES で暗号化されます。データ ストリームの場合は、初期化ベクトルがゼロの CBC モードで暗号化されます。
(私は仕様をあまり気にしないと言いましたか?) サーバー側 (上記) が持っているキーを記憶して拒否する場合、暗号化側を非ハードウェアの改ざん防止セキュリティ モジュールで使用できることに注意するのは興味深いことです。以前に使用されています。技術はかなりきれいです。ANSI 仕様にはまだ足りない部分がありますが、技術は問題ありません。
幸運を。/ボブ・ブライアン