Z会コラボのサマーウォーズの暗号を解いてみた

Takuya Kobayashi⛰
2024.06.27

サマーウォーズの劇場公開から15周年!健二が解いた“あの問題”に挑戦!「Solve Me」キャンペーンの問題を解いてみました。

問題はこちら:

Z会 on Twitterより: https://x.com/zkai/status/1806130340375003357

10ケタの数字が5行。
画像の下部の「https://www.zkai.co.jp/???_????_????_???_?????」にアクセスすれば答えが得られる様子。

この問題を解読するには二つのアプローチがあります。

  • 数学的アプローチ
  • ハッキング的アプローチ

数学的アプローチ

数字を2ケタで区切ると最大の数字がアルファベットの文字数と同じ26なので、単純なROT13と思いました。pythonで適当にコードを書いて、一通りシフトしてみましたがそれっぽい答えは得られず。

ヒントを見てみると、アルファベットと数字の対応表【暗号化ルール】y=mod(ax+b,27)とありました。
それと、意味深な日時。06.27 18:00 06.28 12:00 06.28 18:00これは次のヒントの発表日時ですね。

これだけではいまいち分からないので、もう一つのヒント:
「AI」を暗号化すると「ZA」

これでひらめきました。

y=mod(ax+b,27)のabを求める必要があります。
「AI」を「ZA」に変換するには、以下のような変換が行われたはずです:

  • 01 → 26 (A → Z)
  • 09 → 01 (I → A)

式にすると:
{mod(a⋅1+b,27)=26
mod(a⋅9+b,27)=1​

a+b≡26(mod27)
よって、b≡26−a(mod27)

次に、下の方程式を代入して a を求めます:
9a+b≡1(mod27)

ここに b=26−aを代入すると:
9a+(26−a)≡1(mod27)

解くと:
8a+26≡1(mod27)
8a≡−25(mod27)
8a≡2(mod27)(27−25=2)

a を求めるためには、8の逆元を求めます。逆元は、8と27の間で最小の自然数 k を使って
8k≡1(mod27)

拡張ユークリッドのアルゴリズムで解けます。
8の逆元は、8−1≡17(mod27)

これを使うと、
a≡2⋅17(mod27)
a≡34(mod27)
a≡7(mod27)

よって、a=7,b=19 です。

次のpythonコードで解読できます:

def decrypt(y, a=7, b=19, mod=27):
    a_inv = pow(a, -1, mod)
    x = (a_inv * (y - b)) % mod
    return x

def num_to_char(num):
    if num == 0:
        return '_'
    else:
        return chr(num + ord('a') - 1)

message = [
    [24, 21, 0, 19, 2],
    [26, 14, 1, 13, 19],
    [18, 16, 10, 20, 17],
    [19, 26, 10, 0, 19],
    [2, 1, 10, 26, 1]
]

for row in message:
    for num in row:
        decrypt_num = decrypt(num)
        print( num_to_char(decrypt_num) ,end='' )

https://www.zkai.co.jp/the_magic_words_are_miraiで解読成功ページにアクセスできます。

ハッキング的アプローチ

Z会のHPのソースを見てみると、YoastSEOプラグインのタグやwp-contentなどのディレクトリ構造からWordPressで構築されている事が分かります。

WordPressにはREST APIが用意されており、エンドポイントにリクエストを送ることで記事の取得が可能です。
YoastSEOでnoindex,nofollowに設定してもREST APIからは削除されません。

次のエンドポイントで固定ページの一覧が取得できます。
https://www.zkai.co.jp/wp-json/wp/v2/pages

取得した情報の中に解読成功ページのURLがあります。
https://www.zkai.co.jp/the_magic_words_are_mirai/

REST APIから固定ページを10件取得するpythonコード:

import requests

wordpress_url = 'https://www.zkai.co.jp'

endpoint = f'{wordpress_url}/wp-json/wp/v2/pages'
response = requests.get(endpoint)
if response.status_code == 200:
    pages = response.json()
    for page in pages:
        title = page['title']['rendered']
        url = page['link']
        print(f'Title: {title}\nURL: {url}\n')
else:
    print(f'Failed to retrieve pages: {response.status_code}')

出力:

Title: 解読成功サイト
URL: https://www.zkai.co.jp/the_magic_words_are_mirai/

Title: 解読成功おめでとう!
URL: https://www.zkai.co.jp/deciphering-completed/

Title: Z会グループ|『サマーウォーズ』15周年特別コラボ
URL: https://www.zkai.co.jp/home/cm/summerwars15th/

Title: 2024年7月1日更新:個人情報の開示等の手続きについて
URL: https://www.zkai.co.jp/home/policy/20240701detail/

Title: 2024年7月1日更新:【株式会社増進会ホールディングス】 個人情報保護方針、個人情報の取り扱いについて
URL: https://www.zkai.co.jp/home/policy/20240701zoshinkai/

Title: 2024年7月1日更新:【株式会社Z会ソリューションズ】 個人情報保護方針、個人情報の取り扱いについて
URL: https://www.zkai.co.jp/home/policy/20240701zs/

Title: 2024年7月1日更新:【株式会社Z会エデュース】 個人情報保護方針、個人情報の取り扱いについて
URL: https://www.zkai.co.jp/home/policy/20240701educe/

Title: 2024年7月1日更新:【株式会社Z会】 個人情報保護方針、個人情報の取り扱いについて
URL: https://www.zkai.co.jp/home/policy/20240701privacy/

Title: 公民連携推進事業
URL: https://www.zkai.co.jp/home/koumin/

Title: 新・Z会専用タブレット(中高生対象)
URL: https://www.zkai.co.jp/tablet-chuukou/spec/

おわり

金曜ロードショーで見るたびに涙出そう。