pssht  latest
SSH server library written in PHP
RSA.php
1 <?php
2 
3 /*
4 * This file is part of pssht.
5 *
6 * (c) François Poirotte <clicky@erebot.net>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 
12 namespace fpoirotte\Pssht\Key\SSH;
13 
18 {
20  const DER_HEADER = "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14";
21 
23  protected $n;
24 
26  protected $e;
27 
29  protected $d;
30 
47  public function __construct($n, $e, $d = null)
48  {
49  $this->n = $n;
50  $this->e = $e;
51  $this->d = $d;
52  }
53 
54  public static function getName()
55  {
56  return 'ssh-rsa';
57  }
58 
59  public function serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
60  {
61  $encoder->encodeString(self::getName());
62  $encoder->encodeMpint($this->e);
63  $encoder->encodeMpint($this->n);
64  }
65 
66  public static function unserialize(\fpoirotte\Pssht\Wire\Decoder $decoder, $private = null)
67  {
68  $e = $decoder->decodeMpint();
69  $n = $decoder->decodeMpint();
70 
71  if (!isset($e, $n)) {
72  throw new \InvalidArgumentException();
73  }
74  return new static($n, $e, $private);
75  }
76 
77  public function sign($message)
78  {
79  if ($this->d === null) {
80  throw new \RuntimeException();
81  }
82 
83  $bits = strlen(gmp_strval($this->n, 2));
84  $H = sha1($message, true);
85  $T = self::DER_HEADER . $H;
86  $tLen = strlen($T);
87  $emLen = ($bits + 7) >> 3;
88  if ($emLen < $tLen + 11) {
89  throw new \RuntimeException();
90  }
91  $PS = str_repeat("\xFF", $emLen - $tLen - 3);
92  $EM = gmp_init(bin2hex("\x00\x01" . $PS . "\x00" . $T), 16);
93  if (gmp_cmp($EM, $this->n) >= 0) {
94  throw new \RuntimeException();
95  }
96  $s = str_pad(
97  gmp_strval(gmp_powm($EM, $this->d, $this->n), 16),
98  $emLen * 2,
99  '0',
100  STR_PAD_LEFT
101  );
102  return pack('H*', $s);
103  }
104 
105  public function check($message, $signature)
106  {
107  // Decode given signature.
108  $bits = strlen(gmp_strval($this->n, 2));
109  $emLen = ($bits + 7) >> 3;
110  if (strlen($signature) !== $emLen) {
111  throw new \InvalidArgumentException();
112  }
113  $s = gmp_init(bin2hex($signature), 16);
114  if (gmp_cmp($s, $this->n) >= 0) {
115  throw new \InvalidArgumentException();
116  }
117  $m = gmp_powm($s, $this->e, $this->n);
118  $EM = bin2hex(pack('H*', str_pad(gmp_strval($m, 16), $emLen * 2, '0', STR_PAD_LEFT)));
119 
120  // Generate actual signature.
121  $H = sha1($message, true);
122  $T = self::DER_HEADER . $H;
123  $tLen = strlen($T);
124  if ($emLen < $tLen + 11) {
125  throw new \RuntimeException();
126  }
127  $PS = str_repeat("\xFF", $emLen - $tLen - 3);
128  $EMb = bin2hex("\x00\x01" . $PS . "\x00" . $T);
129 
130  // Compare the two.
131  return ($EM === $EMb);
132  }
133 }
__construct($n, $e, $d=null)
Definition: RSA.php:47
check($message, $signature)
Definition: RSA.php:105
const DER_HEADER
DER header for RSA.
Definition: RSA.php:20
$e
Public exponent.
Definition: RSA.php:26
serialize(\fpoirotte\Pssht\Wire\Encoder $encoder)
Definition: RSA.php:59
$d
Private exponent.
Definition: RSA.php:29
static getName()
Return the name of the algorithm.
Definition: RSA.php:54