2013-02-19 190 views
3

我使用libssh2來使聯網程序更安全。如果密鑰請求被接受,libssh2公鑰認證只需要密碼

我想我的程序以類似於OpenSSH客戶端ssh(1)的方式進行身份驗證。 OpenSSH客戶端只會要求服務器實際接受密鑰的密碼。

據我所知,從this link,SSH客戶端發送請求使用公鑰,如果接受,它可以解鎖使用密碼的私鑰。

libssh2提供了一個函數libssh2_userauth_publickey_fromfile,它使用私鑰和公鑰文件名以及密碼。使用這個函數是非常直接的,但這意味着即使公鑰沒有被服務器首先接受,我也必須獲得私鑰的密碼。對於擁有許多不同密鑰的用戶來說,這顯然是一個問題(我的程序目前正在迭代〜/ .ssh目錄中的密鑰文件)。

我曾嘗試閱讀libssh2函數的手冊頁,其中大多數對於我來說太簡短了,沒有對ssh協議的更詳細的瞭解。實際上some of them甚至還沒有被寫入。

任何人都可以告訴我如何只提示輸入密碼的密碼,這些密碼實際上是由ssh服務器使用libssh2接受的?

回答

3

經過RTFM和做了一些測試後,我發現libssh2_userauth_publickey_fromfile將返回一個不同的錯誤代碼,具體取決於密鑰未被服務器接受還是密碼錯誤。

因此,這是一個相當低效的解決方案(因爲它調用libssh2_userauth_publickey_fromfile,因此協議的所有密鑰交換部分至少需要兩次)。

int nAttempts = 3; // number of attempts the user gets at entering the passphrase 

// Try authenticating with an empty passphrase 
int err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,""); 
if (err == 0) 
{ 
    fprintf(stderr, "You shouldn't use keys with an empty passphrase!\n"); 
} 
else if (err == LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) 
{ 
    // if we get here it means the public key was initially accepted 
    // but the private key has a non-empty passphrase 
    char p[BUFSIZ]; 

    for (int i = 0; i < nAttempts; ++i) 
    { 
     get_passphrase(p); // assume this gets the passphrase 
     err = libssh2_userauth_publickey_fromfile(session, user, pub, priv,p); 
     if (err != LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED) break; 
    } 
} 

if (err != 0) 
{ 
    fprintf(stderr, "Authentication using key %s failed!\n", priv); 
} 

爲了完整起見,​​函數使用溶液來this question提示輸入密碼短語用戶。