PHP Conference Japan 2024

ssh2_auth_pubkey_file

(PECL ssh2 >= 0.9.0)

ssh2_auth_pubkey_file使用公開金鑰進行驗證

說明

ssh2_auth_pubkey_file(
    資源 $session,
    字串 $username,
    字串 $pubkeyfile,
    字串 $privkeyfile,
    字串 $passphrase = ?
): 布林值

使用從檔案讀取的公開金鑰進行驗證。

參數

session

一個 SSH 連線連結識別碼,由呼叫 ssh2_connect() 取得。

username

pubkeyfile

公開金鑰檔案必須採用 OpenSSH 格式。它看起來應該像這樣:

ssh-rsa AAAAB3NzaC1yc2EAAA....NX6sqSnHA8= rsa-key-20121110

私鑰檔案

通行詞組

如果 私鑰檔案 已加密(應該加密),則必須提供 通行詞組

回傳值

成功時回傳 true,失敗時回傳 false

範例

範例 #1 使用公開金鑰進行驗證

<?php
$connection
= ssh2_connect('shell.example.com', 22, array('hostkey'=>'ssh-rsa'));

if (
ssh2_auth_pubkey_file($connection, 'username',
'/home/username/.ssh/id_rsa.pub',
'/home/username/.ssh/id_rsa', 'secret')) {
echo
"公開金鑰驗證成功\n";
} else {
die(
'公開金鑰驗證失敗');
}
?>

注意事項

注意:

底層的 libssh 函式庫不完全支援部分驗證。也就是說,如果您需要同時提供公開金鑰和密碼,則此函式會顯示為驗證失敗。在這種特殊情況下,此呼叫的失敗可能只是表示驗證尚未完成。您需要忽略此失敗並繼續呼叫 ssh2_auth_password() 以完成驗證。

新增註釋

使用者貢獻的註釋 11 則註釋

Aurelien Marchand
2 年前
我們合作的供應商要求同時使用密碼驗證和公開/私鑰驗證。

經過大量的痛苦和測試,我們採取了以下方法來使其運作,繞過安裝 phpseclib 的需要

<?php

$server
= "subdomain.example.com";
$username = "username";
$password = "password";
$path_to_public_key = "file.pub";
$path_to_private_key = "file.priv"; // 重要:權限必須設定為 0600!!
$path_to_needed_file = "/path/to/file/needed.txt";

$ssh2 = ssh2_connect($server);
@
ssh2_auth_pubkey_file($ssh2,$username,$path_to_public_key,$path_to_private_key); // 這會回傳一個警告,但這是正常的,可以忽略
ssh2_auth_password($ssh2,$username,$password);
$sftp = ssh2_sftp($ssh2);
$file = fopen("ssh2.sftp://" . intval($sftp). $path_to_needed_file,"r");
$content = fread($file,1024);
fclose($file);
ssh2_disconnect($ssh2);

echo
$content;
?>
miloslav dot hula at gmail dot com
4 年前
如果您遇到 RSA 金鑰問題,請檢查私鑰檔案內容是否以

-----BEGIN RSA PRIVATE KEY-----

開頭,而不是以

-----BEGIN OPENSSH PRIVATE KEY-----

開頭。第一種金鑰可以透過以下指令產生:

ssh-keygen -m PEM -t rsa -f mykey
mrpetovan at gmail dot com
8 年前
請注意金鑰檔案路徑中的波浪符號 (~),因為它們會觸發以下警告(在偵錯建置時):

PHP 警告:字串未以零結尾 (ZZZZZZZZZZZZZZZZZZ1wjj*=?<) (來源:Zend/zend_execute.h:81) 位置:未知 行號:0

儘管驗證會成功。

<?php
$ssh_conn
= ssh2_connect('test.host.com', 22, array('hostkey' => 'ssh-rsa'));
ssh2_auth_pubkey_file($ssh_conn, 'user', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa')
?>

以上程式碼會拋出警告。

<?php
$ssh_conn
= ssh2_connect('test.host.com', 22, array('hostkey' => 'ssh-rsa'));
ssh2_auth_pubkey_file($ssh_conn, 'user', '/home/user/.ssh/id_rsa.pub', '/home/user/.ssh/id_rsa')
?>

以上程式碼無法正常運作。

如果您想動態替換波浪號 (~),可以使用 posix_getpwuid (https://php.dev.org.tw/manual/en/function.posix-getpwuid.php)
nerak-spelled-backwards at modo dot coop
11 年前
這個函式在某些 Linux 安裝環境下存在一個已知錯誤 (https://bugs.php.net/bug.php?id=58573):如果您使用 libgcrypt 編譯 libssh2,則無法加密您的私鑰。根據錯誤頁面的說明,解決方案是使用 OpenSSL 重新建置 libssh2。(或者不要加密您的私鑰,但這似乎有些不負責任。)

這不是錯誤報告——這個錯誤顯然已經在修復中——而是一則給其他人的注意事項,因為我花了至少一個小時在 Google 上搜尋才意識到問題不在我自己的程式碼。
Christophe
4 年前
使用者應該注意錯誤 78661 https://bugs.php.net/bug.php?id=78661

截至 2020 年 12 月,在某些 Linux 發行版上(至少 Debian 10 和 Ubuntu 20.04),儘管 SSH daemon 會接受連線,但 ssh2_auth_pubkey_file 函式仍然會頑固地回報錯誤。

我花了幾個小時才意識到我的程式碼是正確的,但函式有錯誤。如果您遇到這個錯誤,您可以嘗試改用 https://php.dev.org.tw/ssh2_auth_password⋯⋯如果適用的話。
christian at cvj dot se
12 年前
在我的 Linux Debian 伺服器上執行 PHP 與另一台 Linux Debian 伺服器通訊時,我遇到了讓 RSA 運作的問題。DSA 可以直接使用。我透過在終端機中執行以下操作使其運作:

* ssh-keygen -t rsa
.... PUBFILE
* ssh-keygen -f PUBFILE -e
輸出

id_rsa.pub =
ssh-rsa 輸出 [註解]
max
13 年前
您必須使用以下指令格式化公鑰:

# ssh-keygen -f id_rsa.pub -i
輸出:"ssh-rsa <您的金鑰資料>"

這對我來說很有效。
deepakssn@gmailcom
14 年前
設定公鑰驗證

1. 使用 Putty 登入到您想要連線的 Unix 伺服器。
2. mkdir .ssh(ssh 前面有一個點)
3. cd .ssh
4. ssh-keygen -t rsa mykey
5. 輸入通行詞組:test
6. ls -al -> 您會找到兩個檔案:mykey 和 mykey.pub
7. cat mykey.pub >>authorized_keys
8. cat mykey
9. 將您在螢幕上看到的內容複製到記事本並儲存為 "c:\mykey"(含引號)
10. cat mykey.pub
11. 將您在螢幕上看到的內容複製到記事本並儲存為 "c:\mykey.pub"(含引號)

<?php

function my_ssh_disconnect($reason, $message, $language)
{
printf("Server disconnected with reason code [%d] and message: %s\n", $reason, $message);
}

//Open a connection forcing 3des-cbc when sending packets, any strength aes cipher when receiving packets, no compression in either direction, and Group1 key exchange.
$methods = array(
'kex' => 'diffie-hellman-group1-sha1',
'client_to_server' => array(
'crypt' => 'aes256-cbc',
'comp' => 'none',
'mac' => 'hmac-sha1'),
'server_to_client' => array(
'crypt' => 'aes256-cbc',
'comp' => 'none',
'mac' => 'hmac-sha1'));

$callbacks = array('disconnect' => 'my_ssh_disconnect');

// Function to run a command on the unix server

function run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command)
{
$connection = ssh2_connect($ssh_host, 22, $methods, $callbacks);
if (!
$connection) die('Connection failed');
if (
ssh2_auth_pubkey_file($connection, $user_name, $keyfilename.".pub", $keyfilename, 'test'))
{
echo
"Public Key Authentication Successful as user: $user_name";
}
else
{
die(
'Public Key Authentication Failed');
}

$stream = ssh2_exec($connection, $ssh_command);
$i=0;
stream_set_blocking($stream, true);
$line = stream_get_line($stream, 1024, "\n");
while (!
feof($stream))
{
echo
$line.' ';
$line = stream_get_line($stream, 1024, "\n");
$i++;
}
echo
"Count : ".$i;
flush();
unset(
$stream);
}

function
my_ssh_disconnect($reason, $message, $language)
{
printf("Server disconnected with reason code [%d] and message: %s\n",
$reason, $message);
}

// Main Code

$user_name = "USERID";
$keydir = "c:\\";
$search_string = 'needle';
$keyfilename= $keydir.'mykey';
$ssh_host = "foo.bar.com";
$ssh_command = 'grep "'.$search_string.'" /haystack/*.log';
run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command);

$ssh_command = 'ls -al';
run_cmd($ssh_host, $user_name, $keyfilename, $ssh_command);
?>
anjo2
13 年前
使用 rsa 金鑰可能會無法運作,使用 dsa 金鑰的相容性較佳。

Linux
ssh-keygen -t dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh/
chmod -R 600 ~/.ssh/*

PHP
<?php
$methods
= array(
'kex' => 'diffie-hellman-group1-sha1',
'hostkey' => 'ssh-dss',
'client_to_server' => array(
'crypt' => '3des-cbc',
'mac' => 'hmac-md5',
'comp' => 'none'),
'server_to_client' => array(
'crypt' => '3des-cbc',
'mac' => 'hmac-md5',
'comp' => 'none'));
$connect = ssh2_connect('127.0.0.1', 22, $methods);
if(
ssh2_auth_pubkey_file($connect, 'username', '~/.ssh/id_dsa.pub', '~/.ssh/id_dsa'))
{
echo
"公開金鑰驗證成功\n";
}
else
{
echo
"公開金鑰驗證失敗\n";
}
?>
gramo dot gnu at gmail dot com
15 年前
我曾經在使用這個函式時遇到一個惱人的問題,每次嘗試執行它時,都會回傳

使用者 <user> 使用公開金鑰驗證失敗

但是當我嘗試直接使用以下指令連線到伺服器時
ssh <user>@<domain>
卻一切正常...

經過多次嘗試後,我發現本機檔案的讀取權限被 Apache 使用者 (檔案儲存在 /home/<user>/.ssh 目錄下) 所限制。

因此,如果您也遇到這個問題,只需建立一個 Apache 可以讀取的新目錄,並將金鑰放在該目錄中。

我的完整操作步驟如下 (Linux 和 Apache 同時作為伺服器和客戶端)

首先,我建立一個 Apache 可以讀取的目錄

mkdir ~/.newssh_keys
chmod 777 ~/.newssh_keys

(這是一個安全問題,因此您可能需要考慮如何使其更安全。)

然後,我在本機伺服器上建立金鑰,選擇 ~/.newssh_keys/id_dsa 作為儲存金鑰的檔案

ssh-keygen -t dsa
...
輸入儲存金鑰的檔案 (/home/<user>/.ssh/id_dsa): ~/.newssh_keys/id_dsa
...

然後,我必須更改私密金鑰的權限
(這是一個安全問題,因此您可能需要考慮如何使其更安全。)

chmod 644 ~/.newssh_keys/id_dsa

我將公開金鑰複製到伺服器的 .ssh 目錄中
client$ scp id_dsa.pub <remoteuser>@<server_domain>:~/.ssh/

然後,我使用傳統的 ssh 連線到伺服器,以便將公開金鑰附加到 authorized_keys2 檔案的末尾

server$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys2

最後,刪除公開金鑰以保持整潔
server$ rm ~/.ssh/id_dsa.pub

最後,我將這段程式碼用在我的 PHP 腳本中

<?php
// 為了確保 Apache 可以讀取公鑰
// (除錯後移除此段)
$pub_key = file_get_contents('~/.newssh_keys/id_dsa.pub');
print
"<pre>";
var_export($pub_key);
print
"</pre>";

// 為了檢查私鑰
// (除錯後移除此段)
$prv_key = file_get_contents('~/.newssh_keys/id_dsa');
print
"<pre>";
var_export($prv_key);
print
"</pre>";

// 最後是連線程式碼
$connection = ssh2_connect('<伺服器網域>', 22, array('hostkey', 'ssh-dss'));
if (
ssh2_auth_pubkey_file($connection, '<伺服器使用者>',
'~/.newssh_keys/id_dsa.pub',
'~/.newssh_keys/id_dsa')) {
echo
"公鑰驗證成功\n";
} else {
echo
"公鑰驗證失敗";
}
?>
tekiedude at gmail dot com
17 年前
這可能非常不安全,但如果您處於封閉環境中,您可以自行承擔風險運行它。

我試圖從伺服器 A 取得對伺服器 B 的 SSH 存取權,但伺服器 A 以 'apache' 身分執行 Apache,而且
我需要伺服器 B 上由 root 擁有的檔案。所以我需要某種方法讓 Apache 使用者以 root 身分連線到
伺服器 B。以下是我所做的(兩台伺服器都執行 Linux - 尤其是 CentOS4)

1. ssh-keygen -t rsa -f id_rsa 產生金鑰,不使用密碼
2. 將 id_rsa.pub 檔案附加到伺服器 B 的 /root/.ssh/authorized_keys2
3. 將 id_rsa 和 id_rsa.pub 檔案複製到像 /var/www/.ssh/ 這樣的目錄
(恰好是 CentOS 上 Apache 的家目錄)
4. chown -R apache.apache /var/www/.ssh

然後您可以像這樣連線
$connection = ssh2_connect($server, 22, array('hostkey' => 'ssh-rsa'));
if (ssh2_auth_pubkey_file($connection, 'root',
'/var/www/.ssh/id_rsa.pub',
'/var/www/.ssh/id_rsa')) {
echo "成功!";
}
else
{
echo "失敗 :-(";
}
To Top