本人对SSH不是很了解,比如一般linux在设置ssh(rsa)登入的时候 会在 authorizedkeys文件中设置多个公钥。github也是如此,可以在用户设置下设置多个不同的公钥。当一个用户用ssh自己的私钥发起请求时,ssh服务器是如何确定哪一个公钥是与当前访问用户的私钥是匹配的(个人觉得不太可能是循环所有公钥去一个个验证)。
我不明白你的意思,不过我设置都是在kangle里面设置。
当然是循环一个个去匹配,这个验证就是这么处理的,这个只有最开始建立连接的时候处理一次。
说下我对ssh的理解。
每个用户有自己的ssh公钥和私钥(使用ssh-keygen创建),一般保存在用户home目录下的.ssh目录中。用户通过ssh客户端远程登录ssh服务器时,是向服务器发送他自己的公钥(私钥只有用户自己知道,是不公开的)。authorized_keys
中保存的是其他客户机的ssh公钥,从而这些公钥对应的客户机可以实现无密码登录ssh服务器。
openssh auth-rsa.c文件 不知道这个函数是否说明是循环处理比对的
static int
rsa_key_allowed_in_file(struct passwd *pw, char *file,
const BIGNUM *client_n, Key **rkey)
{
char *fp, line[SSH_MAX_PUBKEY_BYTES];
int allowed = 0, bits;
FILE *f;
u_long linenum = 0;
Key *key;
debug("trying public RSA key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
return 0;
/*
* Go though the accepted keys, looking for the current key. If
* found, perform a challenge-response dialog to verify that the
* user really has the corresponding private key.
*/
key = key_new(KEY_RSA1);
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
char *cp;
char *key_options;
int keybits;
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/*
* Check if there are options for this key, and if so,
* save their starting address and skip the option part
* for now. If there are no options, set the starting
* address to NULL.
*/
if (*cp < '0' || *cp > '9') {
int quoted = 0;
key_options = cp;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
} else
key_options = NULL;
/* Parse the key from the line. */
if (hostfile_read_key(&cp, &bits, key) == 0) {
debug("%.100s, line %lu: non ssh1 key syntax",
file, linenum);
continue;
}
/* cp now points to the comment part. */
/*
* Check if the we have found the desired key (identified
* by its modulus).
*/
if (BN_cmp(key->rsa->n, client_n) != 0)
continue;
/* check the real bits */
keybits = BN_num_bits(key->rsa->n);
if (keybits < 0 || bits != keybits)
logit("Warning: %s, line %lu: keysize mismatch: "
"actual %d vs. announced %d.",
file, linenum, BN_num_bits(key->rsa->n), bits);
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
continue;
debug("matching key found: file %s, line %lu %s %s",
file, linenum, key_type(key), fp);
free(fp);
/* Never accept a revoked key */
if (auth_key_is_revoked(key))
break;
/* We have found the desired key. */
/*
* If our options do not allow this key to be used,
* do not send challenge.
*/
if (!auth_parse_options(pw, key_options, file, linenum))
continue;
if (key_is_cert_authority)
continue;
/* break out, this key is allowed */
allowed = 1;
break;
}
/* Close the file. */
fclose(f);
/* return key if allowed */
if (allowed && rkey != NULL)
*rkey = key;
else
key_free(key);
return allowed;
}