Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage

間違いがあったらご指摘ください。

# 何が起こった

## コケるまでのところ

手許のマシンで Rails 5.2.0 を使って

```console
$ rails new hoge
```

してアプリを作った。

ファイルは Git で管理しており，リモートリポジトリーに push していった。

リモートリポジトリーから本番サーバー（VPS）上に clone した。

## コケるところ

本番サーバーにて。

```console
$ rails console
```

は問題ない。
ところが

```console
$ rails console -e production
```

だと例外


```
`validate_secret_key_base': Missing `secret_key_base` for 'production' environment, set this string with `rails credentials:edit` (ArgumentError)
```

が出る。

あー，そういえば Rails 5.1 までのときも production 環境では環境変数 `SECRET_KEY_BASE` が必要だったから，それに似た話か。
ともかく「`rails credentials:edit` をやれ」と言っているみたいなので，そうしよう。

```console
$ sudo rails credentials:edit
```

すると，

```
No $EDITOR to open file in.
```

と文句が出た。どうやら `EDITOR` という環境変数で，使うテキストエディターを指定しておかなければならないようだ。
そこで，vim を使うことにして，

```console
$ sudo EDITOR=vim rails credentials:edit
```

とやったら，今度は

```
ActiveSupport::MessageEncryptor::InvalidMessage
```

が出た。

これがさっぱり分からなかった。

# 原因は

Rails 5.2 が秘匿情報を扱う仕組みをよく理解していれば解決は早かったと思う。

## 秘匿情報を扱う仕組み

Rails には，`secret_key_base` のような値や，SMTP のパスワードなど，漏れてはマズい情報を取り扱う仕組みがある。

何が問題かというと，そういう情報たちも Git 管理下のファイルに書きたいのだけれど，そうするとリポジトリーが見られる人にはバレてしまう，ということ。

そこで，Rails 5.2 では，そういう情報を記述したテキストを暗号化し，その暗号化したファイルを Git で管理できるようにしている。
そしてその暗号を解くための鍵だけは Git 管理せずに取り扱う。
どうもそういうことらしい。

具体的に言うと，暗号化したあとのファイルは `config/credentials.yml.enc` に保存される。ファイル名で分かるとおり，YAML 形式で記述して暗号化したものだ。

鍵のほうは環境変数 `RAILS_MASTER_KEY` で与えるか，あるいは `config/master.key` ファイルで与える。

`rails credentials:edit` というのは，暗号化したファイルを復号して，指定のエディターで編集させ，その結果を再び暗号化して `config/credentials.yml.enc` に保存するためのコマンドらしい。

## で，なんでエラー？

`rails new` すると，`config/credentials.yml.enc` も `config/master.key` も自動的に作られる。

`config/master.key` のほうは，`.gitignore` によって，Git 管理せぬよう指定されている。

よって，本番サーバー上でプロジェクトのリポジトリーを clone しても，このファイルは付いてこないわけだ。

つまり，この状態では本番サーバー上で暗号化ファイルが復号できない。だから `secret_key_base` の値も得られない。
と，そういうことのようだ。

そこで，`rails credentials:edit` を促されるわけだが，このコマンドは，鍵が存在しないとき，勝手に鍵を生成して `config/master.key` に保存してくれちゃったりするらしい。

ところが，新しく生成された鍵は，既存の `config/credentials.yml.enc` の復号には当然ながら使えない。
**玄関の鍵を紛失して，鍵屋が別の鍵を持ってきても開くわけないものな。**

それが

```
ActiveSupport::MessageEncryptor::InvalidMessage
```

の言わんとすることらしい。


# 解決

原因が分かったので，`rails new` した環境の `config/master.key` の中身をコピーして，本番サーバーの `config/master.key` に持ってきた。

これで本番サーバーでも production 環境で動くようになった。

# 参考（追記）

[Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)

# master.key を紛失したらどうなる？（2018-08-01 追記）

もし，鍵（master.key）を紛失してしまっていたらどうなるのか。
〔よくあるのが，新規のプロジェクトを生成したあと，リモートのリポジトリーに push し，元のファイルは削除して，改めてリモートから clone して開発を始めるような場合。〕

鍵が無かったらどうしようもない。だから絶対に無くしてはダメ。

ただ，例えば開発の初期で，credentials.yml に大したことが書かれておらず（`secret_key_base` 程度），捨ててもよいのであれば，再作成すればよい。

つまり，`config/credentials.yml.enc` をいったん削除して，

```console
$ sudo EDITOR=vim rails credentials:edit
```

のようにすれば，新しく `config/credentials.yml.enc` が作られる。
このとき，`config/master.key` は，存在していなければ作られるし，存在していればそれが使われる。

# sudo について（2022-02-05 追記）

この記事ではコマンドに `sudo` を付けたところがある。
もう何年も前なので正確に覚えていないが，`sudo` が付いているのは，ディレクトリーに書き込みパーミションが無い本番サーバー上で実験したときのコマンドをその場で手元にコピペして記事に利用したからだったと思う。

この記事を参考に `rails credentials:edit` を実行する方もいらっしゃると思うが，おそらくほとんどの場合，`sudo` は要らないはず。

「何となく付ける `sudo`」はしばしばろくな結果をもたらさないので，必要性をよく考えて判断していただけると嬉しい。