PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.4 3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / 3rdparty / phpseclib3 / System / SSH / Agent / Identity.php
backup / src / JetBackup / 3rdparty / phpseclib3 / System / SSH / Agent Last commit date
.htaccess 1 year ago Identity.php 1 year ago index.html 1 year ago web.config 1 year ago
Identity.php
309 lines
1 <?php
2
3 /**
4 * Pure-PHP ssh-agent client.
5 *
6 * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
7 *
8 * PHP version 5
9 *
10 * @author Jim Wigginton <terrafrost@php.net>
11 * @copyright 2009 Jim Wigginton
12 * @license http://www.opensource.org/licenses/mit-license.html MIT License
13 * @link http://phpseclib.sourceforge.net
14 */
15
16 declare(strict_types=1);
17
18 namespace phpseclib3\System\SSH\Agent;
19
20 use phpseclib3\Common\Functions\Strings;
21 use phpseclib3\Crypt\Common\PrivateKey;
22 use phpseclib3\Crypt\Common\PublicKey;
23 use phpseclib3\Crypt\DSA;
24 use phpseclib3\Crypt\EC;
25 use phpseclib3\Crypt\RSA;
26 use phpseclib3\Exception\RuntimeException;
27 use phpseclib3\Exception\UnsupportedAlgorithmException;
28 use phpseclib3\System\SSH\Agent;
29 use phpseclib3\System\SSH\Common\Traits\ReadBytes;
30
31 /**
32 * Pure-PHP ssh-agent client identity object
33 *
34 * Instantiation should only be performed by \phpseclib3\System\SSH\Agent class.
35 * This could be thought of as implementing an interface that phpseclib3\Crypt\RSA
36 * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
37 * The methods in this interface would be getPublicKey and sign since those are the
38 * methods phpseclib looks for to perform public key authentication.
39 *
40 * @author Jim Wigginton <terrafrost@php.net>
41 * @internal
42 */
43 class Identity implements PrivateKey
44 {
45 use ReadBytes;
46
47 // Signature Flags
48 // See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3
49 public const SSH_AGENT_RSA2_256 = 2;
50 public const SSH_AGENT_RSA2_512 = 4;
51
52 /**
53 * Key Object
54 *
55 * @var PublicKey
56 * @see self::getPublicKey()
57 */
58 private $key;
59
60 /**
61 * Key Blob
62 *
63 * @var string
64 * @see self::sign()
65 */
66 private $key_blob;
67
68 /**
69 * Socket Resource
70 *
71 * @var resource
72 * @see self::sign()
73 */
74 private $fsock;
75
76 /**
77 * Signature flags
78 *
79 * @var int
80 * @see self::sign()
81 * @see self::setHash()
82 */
83 private $flags = 0;
84
85 /**
86 * Curve Aliases
87 *
88 * @var array
89 */
90 private static $curveAliases = [
91 'secp256r1' => 'nistp256',
92 'secp384r1' => 'nistp384',
93 'secp521r1' => 'nistp521',
94 'Ed25519' => 'Ed25519',
95 ];
96
97 /**
98 * Default Constructor.
99 *
100 * @param resource $fsock
101 */
102 public function __construct($fsock)
103 {
104 $this->fsock = $fsock;
105 }
106
107 /**
108 * Set Public Key
109 *
110 * Called by \phpseclib3\System\SSH\Agent::requestIdentities()
111 */
112 public function withPublicKey(PublicKey $key): Identity
113 {
114 if ($key instanceof EC) {
115 if (is_array($key->getCurve()) || !isset(self::$curveAliases[$key->getCurve()])) {
116 throw new UnsupportedAlgorithmException('The only supported curves are nistp256, nistp384, nistp512 and Ed25519');
117 }
118 }
119
120 $new = clone $this;
121 $new->key = $key;
122 return $new;
123 }
124
125 /**
126 * Set Public Key
127 *
128 * Called by \phpseclib3\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
129 * but this saves a small amount of computation.
130 */
131 public function withPublicKeyBlob(string $key_blob): Identity
132 {
133 $new = clone $this;
134 $new->key_blob = $key_blob;
135 return $new;
136 }
137
138 /**
139 * Get Public Key
140 *
141 * Wrapper for $this->key->getPublicKey()
142 *
143 * @param string $type optional
144 */
145 public function getPublicKey(string $type = 'PKCS8'): PublicKey
146 {
147 return $this->key;
148 }
149
150 /**
151 * Sets the hash
152 */
153 public function withHash(string $hash): Identity
154 {
155 $new = clone $this;
156
157 $hash = strtolower($hash);
158
159 if ($this->key instanceof RSA) {
160 $new->flags = 0;
161 switch ($hash) {
162 case 'sha1':
163 break;
164 case 'sha256':
165 $new->flags = self::SSH_AGENT_RSA2_256;
166 break;
167 case 'sha512':
168 $new->flags = self::SSH_AGENT_RSA2_512;
169 break;
170 default:
171 throw new UnsupportedAlgorithmException('The only supported hashes for RSA are sha1, sha256 and sha512');
172 }
173 }
174 if ($this->key instanceof EC) {
175 switch ($this->key->getCurve()) {
176 case 'secp256r1':
177 $expectedHash = 'sha256';
178 break;
179 case 'secp384r1':
180 $expectedHash = 'sha384';
181 break;
182 //case 'secp521r1':
183 //case 'Ed25519':
184 default:
185 $expectedHash = 'sha512';
186 }
187 if ($hash != $expectedHash) {
188 throw new UnsupportedAlgorithmException('The only supported hash for ' . self::$curveAliases[$this->key->getCurve()] . ' is ' . $expectedHash);
189 }
190 }
191 if ($this->key instanceof DSA) {
192 if ($hash != 'sha1') {
193 throw new UnsupportedAlgorithmException('The only supported hash for DSA is sha1');
194 }
195 }
196 return $new;
197 }
198
199 /**
200 * Sets the padding
201 *
202 * Only PKCS1 padding is supported
203 */
204 public function withPadding(int $padding): Identity
205 {
206 if (!$this->key instanceof RSA) {
207 throw new UnsupportedAlgorithmException('Only RSA keys support padding');
208 }
209 if ($padding != RSA::SIGNATURE_PKCS1 && $padding != RSA::SIGNATURE_RELAXED_PKCS1) {
210 throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures');
211 }
212 return $this;
213 }
214
215 /**
216 * Determines the signature padding mode
217 *
218 * Valid values are: ASN1, SSH2, Raw
219 */
220 public function withSignatureFormat(string $format): Identity
221 {
222 if ($this->key instanceof RSA) {
223 throw new UnsupportedAlgorithmException('Only DSA and EC keys support signature format setting');
224 }
225 if ($format != 'SSH2') {
226 throw new UnsupportedAlgorithmException('Only SSH2-formatted signatures are currently supported');
227 }
228
229 return $this;
230 }
231
232 /**
233 * Returns the curve
234 *
235 * Returns a string if it's a named curve, an array if not
236 *
237 * @return string|array
238 */
239 public function getCurve()
240 {
241 if (!$this->key instanceof EC) {
242 throw new UnsupportedAlgorithmException('Only EC keys have curves');
243 }
244
245 return $this->key->getCurve();
246 }
247
248 /**
249 * Create a signature
250 *
251 * See "2.6.2 Protocol 2 private key signature request"
252 *
253 * @param string $message
254 * @throws RuntimeException on connection errors
255 * @throws UnsupportedAlgorithmException if the algorithm is unsupported
256 */
257 public function sign($message): string
258 {
259 // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
260 $packet = Strings::packSSH2(
261 'CssN',
262 Agent::SSH_AGENTC_SIGN_REQUEST,
263 $this->key_blob,
264 $message,
265 $this->flags
266 );
267 $packet = Strings::packSSH2('s', $packet);
268 if (strlen($packet) != fwrite($this->fsock, $packet)) {
269 throw new RuntimeException('Connection closed during signing');
270 }
271
272 $length = current(unpack('N', $this->readBytes(4)));
273 $packet = $this->readBytes($length);
274
275 [$type, $signature_blob] = Strings::unpackSSH2('Cs', $packet);
276 if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
277 throw new RuntimeException('Unable to retrieve signature');
278 }
279
280 if (!$this->key instanceof RSA) {
281 return $signature_blob;
282 }
283
284 [$type, $signature_blob] = Strings::unpackSSH2('ss', $signature_blob);
285
286 return $signature_blob;
287 }
288
289 /**
290 * Returns the private key
291 *
292 * @param array $options optional
293 */
294 public function toString(string $type, array $options = []): string
295 {
296 throw new RuntimeException('ssh-agent does not provide a mechanism to get the private key');
297 }
298
299 /**
300 * Sets the password
301 *
302 * @return never
303 */
304 public function withPassword(?string $password = null): PrivateKey
305 {
306 throw new RuntimeException('ssh-agent does not provide a mechanism to get the private key');
307 }
308 }
309