2020-06-07 06:25:59 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Leenooks\OpenPGP;
|
|
|
|
|
|
|
|
use Leenooks\OpenPGP;
|
|
|
|
|
|
|
|
class S2K
|
|
|
|
{
|
|
|
|
public $type, $hash_algorithm, $salt, $count;
|
|
|
|
|
|
|
|
function __construct($salt='BADSALT',$hash_algorithm=10,$count=65536,$type=3)
|
|
|
|
{
|
|
|
|
$this->type = $type;
|
|
|
|
$this->hash_algorithm = $hash_algorithm;
|
|
|
|
$this->salt = $salt;
|
|
|
|
$this->count = $count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static function parse(&$input)
|
|
|
|
{
|
|
|
|
$s2k = new self;
|
|
|
|
|
2020-06-18 12:03:56 +00:00
|
|
|
switch($s2k->type = ord($input[0])) {
|
2020-06-07 06:25:59 +00:00
|
|
|
case 0:
|
2020-06-18 12:03:56 +00:00
|
|
|
$s2k->hash_algorithm = ord($input[1]);
|
2020-06-07 06:25:59 +00:00
|
|
|
$input = substr($input,2);
|
|
|
|
break;
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 1:
|
2020-06-18 12:03:56 +00:00
|
|
|
$s2k->hash_algorithm = ord($input[1]);
|
2020-06-07 06:25:59 +00:00
|
|
|
$s2k->salt = substr($input,2,8);
|
|
|
|
$input = substr($input,10);
|
|
|
|
break;
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 3:
|
2020-06-18 12:03:56 +00:00
|
|
|
$s2k->hash_algorithm = ord($input[1]);
|
2020-06-07 06:25:59 +00:00
|
|
|
$s2k->salt = substr($input,2,8);
|
2020-06-18 12:03:56 +00:00
|
|
|
$s2k->count = OpenPGP::decode_s2k_count(ord($input[10]));
|
2020-06-07 06:25:59 +00:00
|
|
|
$input = substr($input,11);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $s2k;
|
|
|
|
}
|
|
|
|
|
|
|
|
function to_bytes()
|
|
|
|
{
|
|
|
|
$bytes = chr($this->type);
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
switch($this->type) {
|
|
|
|
case 0:
|
|
|
|
$bytes .= chr($this->hash_algorithm);
|
|
|
|
break;
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 1:
|
|
|
|
if (strlen($this->salt) != 8)
|
|
|
|
throw new Exception('Invalid salt length');
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
$bytes .= chr($this->hash_algorithm);
|
|
|
|
$bytes .= $this->salt;
|
|
|
|
break;
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 3:
|
|
|
|
if (strlen($this->salt) != 8)
|
|
|
|
throw new Exception('Invalid salt length');
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
$bytes .= chr($this->hash_algorithm);
|
|
|
|
$bytes .= $this->salt;
|
|
|
|
$bytes .= chr(OpenPGP::encode_s2k_count($this->count));
|
|
|
|
break;
|
|
|
|
}
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
return $bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
function raw_hash($s)
|
|
|
|
{
|
2020-06-18 12:03:56 +00:00
|
|
|
return hash(strtolower(SignaturePacket::$hash_algorithms[$this->hash_algorithm]),$s,true);
|
2020-06-07 06:25:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function sized_hash($s,$size)
|
|
|
|
{
|
|
|
|
$hash = $this->raw_hash($s);
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
while(strlen($hash) < $size) {
|
|
|
|
$s = "\0".$s;
|
|
|
|
$hash .= $this->raw_hash($s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return substr($hash,0,$size);
|
|
|
|
}
|
|
|
|
|
|
|
|
function iterate($s)
|
|
|
|
{
|
|
|
|
if (strlen($s) >= $this->count)
|
|
|
|
return $s;
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
$s = str_repeat($s,ceil($this->count/strlen($s)));
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
return substr($s,0,$this->count);
|
|
|
|
}
|
|
|
|
|
|
|
|
function make_key($pass,$size)
|
|
|
|
{
|
|
|
|
switch($this->type) {
|
|
|
|
case 0:
|
|
|
|
return $this->sized_hash($pass, $size);
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 1:
|
|
|
|
return $this->sized_hash($this->salt . $pass, $size);
|
2020-06-18 12:03:56 +00:00
|
|
|
|
2020-06-07 06:25:59 +00:00
|
|
|
case 3:
|
|
|
|
return $this->sized_hash($this->iterate($this->salt . $pass), $size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|