[英]How to implement a concat KDF for use with JOSE/JWE/JWT
我正在嘗試編寫代碼來解密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
,它是解密的內容主密鑰。
我確實解決了這個問題。 不確定是否會幫助其他人,但以防萬一:
// 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令牌請求中解密來獲得主密鑰。
這是我根據相同規范的實現,但草案#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");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.