1

既存のライブラリは必要なアルゴリズムをサポートしていないため、PHP で JWE トークンを復号化するコードを作成しようとしています ( A128CBC+HS256、非推奨のアルゴリズムです)。

私の問題は、「連結キー導出関数」を使用するコンテンツ暗号化キーを生成する方法を理解できないことです (ここのセクション 5.8.1 を参照してください: http://csrc.nist.gov/publications/nistpubs/800-56A/ SP800-56A_Revision1_Mar08-2007.pdf )。関数の記号と説明が頭をよぎります。

JOSE JSON Web アルゴリズム ドラフト 06に基づいて値を取得しています。

これまでのところ、コードの関連部分は次のようになります。

// Derive CBC encryption & integrity keys
$shaSize = 256;
$encryptionKeySize = $shaSize / 2;
$integrityKeySize = $shaSize;

// Calculate the key derivation using Concat KDF for the content 
// encryption key
$encryptionSegments = [
    $masterKey,         // Z
    $encryptionKeySize, // keydatalen
    $this->packInt32sBe($encryptionKeySize) . utf8_encode('A128CBC+HS256'), // AlgorithmID
    $this->packInt32sBe(0), // PartyUInfo
    $this->packInt32sBe(0), // PartyUInfo
    'Encryption',           // SuppPubInfo
    $this->packInt32sBe(1), // SuppPrivInfo
];

// Calculate the SHA256 digest
$cek = hex2bin(hash('sha256', implode('', $encryptionSegments)));

おそらく関連する、ビッグエンディアン整数を取得するための私の関数:

public function packInt32sBe($n)
{
    if (pack('L', 1) === pack('N', 1)) {
        return pack('l', $n);
    }

    return strrev(pack('l', $n));
}

ここに示されていない唯一の変数$masterKeyは、復号化されたコンテンツ マスター キーです。

4

2 に答える 2

3

私はこれを解決することになりました。それが他の誰かに役立つかどうかはわかりませんが、念のために:

// Derive CBC encryption & integrity keys
$shaSize = 256;
$encryptionKeySize = $shaSize / 2;
$integrityKeySize = $shaSize;

// Calculate the key derivation using Concat KDF for the content 
// encryption key
$encryptionSegments = [
    $this->packInt32sBe(1), 
    $cmk,                              // Z
    $this->packInt32sBe($encryptionKeySize) . utf8_encode('A128CBC+HS256'), // AlgorithmID
    $this->packInt32sBe(0), // PartyUInfo
    $this->packInt32sBe(0), // PartyUInfo
    'Encryption',           // SuppPubInfo
];

// Calculate the SHA256 digest, and then get the first 16 bytes of it
$cek = substr(hex2bin(hash('sha256', implode('', $encryptionSegments))), 0, 16);

ここで唯一不明な変数$cmkは、私のコンテンツ マスター キー (別名 "Z" 値) です。この特定のケースでは、XBOX One トークン要求からマスター キーを復号化してマスター キーを取得しました。

于 2014-11-04T19:42:57.347 に答える
1

これは、同じ仕様による私自身の実装ですが、ドラフト #39 です。

<?php

class ConcatKDF
{
    public static function generate($Z, $encryption_algorithm, $encryption_key_size, $apu = "", $apv = "")
    {
        $encryption_segments = array(
            self::toInt32Bits(1),                                                   // Round number 1
            $Z,                                                                     // Z (shared secret)
            self::toInt32Bits(strlen($encryption_algorithm)).$encryption_algorithm, // Size of algorithm and algorithm
            self::toInt32Bits(strlen($apu)).$apu,                                   // PartyUInfo
            self::toInt32Bits(strlen($apv)).$apv,                                   // PartyVInfo
            self::toInt32Bits($encryption_key_size),                                // SuppPubInfo (the encryption key size)
            "",                                                                     // SuppPrivInfo
        );

        return substr(hex2bin(hash('sha256', implode('', $encryption_segments))), 0, $encryption_key_size/8);
    }

    private static function toInt32Bits($value)
    {
        return hex2bin(str_pad(dechex($value), 8, "0", STR_PAD_LEFT));
    }
}

使い方はとても簡単です:

ConcatKDF::generate("The shared key here", 'A128CBC+HS256', 128);

apu および apv パラメータがある場合:

ConcatKDF::generate("Another shared key here", 'A128GCM', 128, "Alice", "Bob");
于 2015-01-03T20:43:42.487 に答える