利用公私钥实现无密码登录

1. 先用 SecureCRT 创建 Openssl 格式的 公私钥
2. 上传公钥到 $HOME/.ssh/authorized_keys
3. 修改 /etc/ssh/sshd_config

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys #这里是到用户根目录的相对路径

重启 sshd 服务
4. 在 SecureCRT 中设置使用密钥登录

PHP 的 OpenSSL 库

书接上回,在研究 XML 签名之前先研究一下 OpenSSL 库。

签名和原理

PHP 签名的函数原型是:

bool openssl_sign ( string $data , string &$signature , mixed $priv_key_id [, int $signature_alg ] )

大四时学的密码学全忘光了,用 Google CodeSearch 搜了一气 OpenSSL 的源代码才搞明白了签名的原理。

生成签名:

  1. 对 $data 按照 $signature_alg 设置的算法(默认是OPENSSL_ALGO_SHA1)进行 hash 运算
  2. 用私钥加密($priv_key_id)
  3. $signature 就是产生的签名数据,连同 $data 发送给接收方

可用的 hash 算法包括:

  • OPENSSL_ALGO_SHA1
  • OPENSSL_ALGO_MD5
  • OPENSSL_ALGO_MD4
  • OPENSSL_ALGO_MD2

验证:

  1. 用公钥解密签名数据
  2. 解密后的结果是 $data 的 hash 值,接受方再生成 $data 的 hash 值与之对比

签名验证算法

最常见的有两种:基于大数因子分解问题的数字签名(RSA),基于离散对数问题的数字签名(DSA),公私钥分别对应 ~/.ssh/id_rsa & ~/.ssh/id_rsa.pub 和 ~/.ssh/id_dsa & ~/.ssh/id_dsa.pub
二者区别在于 RSA 还可以用于加密,而 DSA 只能用于签名验证,二者签名效率相近,但 RSA 的验证要远快于 DSA。

所以 PHP 中使用 RSA,公私钥可以用 OpenSSL 工具包生成:

openssl genrsa 512 >id_rsa
openssl rsa -pubout id_rsa.pub

我在 .ssh 目录下的 RSA 公私钥是用 ssh-keygen 生成的,但在在这里做试验失败,可能于密钥长度有关系。

验证函数原型:

int openssl_verify  (  string $data  ,  string $signature  ,  mixed $pub_key_id  [,  int $signature_alg = OPENSSL_ALGO_SHA1  ] )

很好理解,$data 是接受方获取的数据,$signature 是一起发过来的签名,$pub_key_id 是校验用的公钥,$signature_alg 就是前面制定的 hash 算法了。

加密

函数原型:

int openssl_seal  ( string $data  , string &$sealed_data  , array &$env_keys  , array $pub_key_ids  )
  1. 用随机字符串加密 data ( RC4 加密算法)
  2. 用 pub_key_ids 里的公钥对共享密钥进行加密,将结果保存在 env_keys
  3. 将 env_keys 和 sealed_data 发送给接收方

解密

函数原型:

bool openssl_open  ( string $sealed_data  , string &$open_data  , string $env_key  , mixed $priv_key_id  )
  1. 私钥揭开 env_key
  2. 用 env_key 打开加密消息

用 PHP 创建公私钥

function get_key_pair() {
    $ret = array();
    $res = openssl_pkey_new();
    openssl_pkey_export($res, $ret['private_key']);
    $pub_key = openssl_pkey_get_details($res);
    $ret['public_key'] = $pub_key['key'];
    return $ret;
}

DSA 与 RSA 的区别

DSA 用于签名,而 RSA 可用于签名和加密。

DSA is faster in *signing*, but slower in *verifying*.
A DSA key of the same strength as RSA (1024 bits) generates a smaller signature.
An RSA 512 bit key has been cracked, but only a 280 DSA key.
It doesn’t matter because with Ssh only authentication is done using RSA or DSA algorithm, and then the “rest” is encoded using a (uh, was it block?) cipher like IDEA, DES, Blowfish, etc, etc after the authentication is done.
While SSH2 can use either DSA or RSA keys, SSH1 cannot. Ssh2 will also not use patented cypers like IDEA.