論理学で矛盾からは任意の命題が導出できることの証明

1≠2かつ1=2ならば、P≠NPが証明できる」みたいな話*1

「矛盾(A∧¬A)からは何でも導ける(A∧¬A⇒B)」「あれ、A∧¬A⇔Fだから、F⇒Bとなって、F⇒B全体は真だけど、Bが真とは限らないのでは?」みたいな話になって混乱したのでメモ。

まとめ

Aより、A∨Bは真。¬AA∨Bより、B

詳細

: かつ、: または、: 否定、: ならば、: 同値、T: 真、F: 偽。

  1. A∧¬Aが真ならば、の定義から、A¬Aも真となる
  2. Aが真なので、A∨Bは真となる
  3. ¬Aが真であり、↑で示した通りA∨Bも真となる。A∨Bが真で(¬Aより)Aが偽なので、Bが真となるしかない

Aは真なの?偽なの?と思ってしまうが、それが矛盾なので仕方がない。仮定と既に示したことは以降の証明で使えるので、A¬Aも好きなときに使える。

F⇒Bが真というのは、の定義。これは正しい。一方で、A∧¬Aが真となるような体系は普通は考えない。何でも示せてしまってつまらないから? 何とかして扱ってみようという面白そうな話もあるらしい。

矛盾許容論理 - Wikipedia

*1:1=2から、P=NPらしい。1=2 - アンサイクロペディア

iPhone 6sを買った

今さらだけど、iPhone 6sを買ったので、つらつらと感想を。

3D Touch

MacBookの感圧タッチトラックパッドや、らくらくホンくらいの押し心地を期待していたけど、あんまり押した感じはしない。ちょっと残念。

デレステ

3D標準が余裕で動いて良い。しかし、画像の解像度が5sが基準になっているらしく、6sではぼやけてしまってとても残念。6s向けの解像度を用意してくれ🙏 親指派だけどこの画面のサイズでも問題は無い。

iPhone 5s

f:id:kusano_k:20160331012419p:plain

iPhone 6s

f:id:kusano_k:20160331012427p:plain

ドック

スマホにいちいちケーブルを挿すのが面倒なので、いつもたとえ別売でも公式のドックを買うようにしていた。このドックがなんと5000円もする。さすがに高すぎでは……。店員に持ってきてもらって値段を聞いて「やっぱりいいです……」と言ってしまったが、後から買ってきた。単なるライトニングケーブルの延長ではなく、中に基盤が入っていてドックにスピーカーを繋げるけど、その機能は要らないので安くしてほしい。ケーブルを挿すのもこのドックも面倒で美しくないと思う。アップルなんだから磁石とかを使ってスマートに充電できるようにしてほしい。

f:id:kusano_k:20160331011510j:plain:w480

slack

CPUの性能が向上しているからか、とても快適にサクサク閲覧できる。PCより快適。

ストラップ

スマホにカバーは付けたくないけど、ストラップは付けたい。5sではNETSUKEを使っていた。しっかりした作りで安心感があった。これの6s版を買おうと思ったけど、売り切れ。別会社で再販する予定はあるらしいけど、いつになるやら……。

結論

iPhone SEのほうが良かったかもしれんね(´・ω・`) デザインも6sの丸い感じよりは、5sの硬い感じのほうが好き。

虫を食べてきた

そんなにヤバイ写真ではないと思うけど、苦手な人は注意。

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

誘われた。
ゴキブリ食べた - 銀の人のメモ帳
に触発されたけど、この店は遠いので、
米とサーカス - 高田馬場/居酒屋 [食べログ]
に行くことにしたらしい。件のブログほどのインパクトは無い。

f:id:kusano_k:20160305002936j:plain:w640

アリ酒。独特の風味があるけど、これがアリのものなのかどうか分からない。アリはプツプツとした食感。

f:id:kusano_k:20160305002946j:plain:w640

イナゴの佃煮。実家で食べたことがある。

f:id:kusano_k:20160305002955j:plain:w640

蜂の子の佃煮。佃煮の味しかしない……。

f:id:kusano_k:20160305003008j:plain:w640

サソリ。エビフライの尻尾みたいな味を想像していた。手や足はたしかにそんな感じだけど、身の部分はレバーのような感じ。匂いが強いので、一緒に行った人皆これが一番マズいと言っていた。隣はバンブーワーム。スナック菓子みたいなサクサクとした食感。言われなければ虫だと気が付かなさそう。

f:id:kusano_k:20160305003017j:plain:w640

右から、ゲンゴロウ。私は食べていない。普通に食べられるとのこと。イナゴ。カイコ。カイコはオガクズのような風味で美味しくなかった。

f:id:kusano_k:20160305003024j:plain:w640

シカのキンタマの刺身。馬のタテガミのような油っぽい味。

f:id:kusano_k:20160305003031j:plain:w640

サソリのネギま。単品で頼むとネギが付くらしい。

f:id:kusano_k:20160305003041j:plain:w640

アリのチャーハン。アリが口の中でチクチクする以外は普通のチャーハンで、アリの味は分からない。

f:id:kusano_k:20160305003048j:plain:w640

冬虫夏草酒。虫の部分は蝉。ここからお猪口に注いで提供される。冬虫夏草の味がするのかどうか良く分からない。

f:id:kusano_k:20160305003057j:plain:w640

うるか2種盛り。鮎の内臓と卵巣の塩辛らしい。これはゲテモノ枠ではない気がする。美味しんぼで見て食べたいなと思っていたけど、そんなに感動するほどではない。塩っぽいので酒が進む。

f:id:kusano_k:20160305003105j:plain:w640

何だったか忘れたけど、何かのハツの天ぷら。普通に美味しい。

f:id:kusano_k:20160305003115j:plain:w640

アリの卵の卵焼き。大部分は鶏の卵で、白い粒がアリの卵。こんなに卵が大きいってどんなアリなのだろう? プツプツとした食感はあるけど、味はしない。

f:id:kusano_k:20160305003122j:plain:w640

馬の大動脈。モツのように固い。普通に美味しい。

f:id:kusano_k:20160305003129j:plain:w640

ラクダのトンペイ焼き。固いだけで、あまり味はしない。

基本的にわざわざ食べるほど美味しくない。考えてみれば、虫が美味しいなら、今頃は肉だけではなく虫を食べる文化が根付いていたはず。イナゴは美味しいから食べる文化が残っているのか。帰りに寄った野方ホープラーメンを皆で「美味しい美味しい」言いながら食べた。

PHPのmt_rand()にプルリクを送った

この話。

PHP の mt_rand() は一貫して壊れている(consistently broken)らしい - 唯物是真 @Scaled_Wurm

PHPmt_rand()が実装にミスがあることを知ったので、「PHPのコミットログに名前を載せるぞ╭( ・ㅂ・)و」と思ってプルリクを送ったら、一旦マージされたけど、リバートされた。

詳細

https://github.com/php/php-src/pull/1681/files

ついでにテストコードも付けたけど、直すべきは1文字だけ。 twistというマクロの定義が1文字間違えている。 loBit(u)ではなくloBit(v)が正しい。

#define twist(m,u,v)  (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(u))) & 0x9908b0dfU))

このマクロはオリジナルのソースコード

y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];

という処理に対応している。最適化されていて分かりづらいけど、loBit(x)01を返すので、符号を反転させると、0x000000000xffffffffになり、andを取ることで0x000000000x9908b0dfになる。オリジナルのソースコードmag01{0x0UL, 0x9908b0df}なので、表を引かずに同じ動作をするようになっている。オリジナルと同じ結果を得るためには、uではなくvの下位1bitを使わなければいけない。

PHPにmt_randが実装された当初から間違っていたわけではなく、10年前にコードを最適化したときエンバグしたらしい。 この前はオリジナルのメルセンヌ・ツイスタと同じ値を返していたはず。

普通に乱数を使う分には全く問題の無いレベルだと思うけど、この違いで乱数の周期性などがどの程度悪化しているのか、あるいは全く影響は無いのか、気になる。

経緯

2015年10月。とあるセキュリティ系のコンテストでmt_randを推測する問題を解いていて、なぜかC++での実装と上手く結果が合わなかった。乱数を推測するツールがあると教えてもらってそのツールを見ていたら、ソースコードの中にmt_twistという関数とphp_twistという関数があって、PHPは実装が異なっていることを知った。なので、このバグは私が見つけたわけではない。知っている人は知っている話だったらしい。1文字だけだし、直そうかとも思ったけど、面倒そうなので止めた。

https://github.com/GeorgeArgyros/Snowflake/blob/22d2a261f159e1a7b4233f0f4aac4020a90e079f/mt_rand/mt_rand.c#L39

2015年12月。このインタビューを読んで「PHPすごいなー」と思い、コミットログに名前を残したくなったので、バグ報告をして、プルリクを送った。この時点で、「たしかにバグだけど、直したら互換性が崩れるのでは? どうしよう」というようなコメントがついていた。

2016年2月。このコミットと衝突していたので、解消して、ついでに、「そもそも10年前の修正で互換性が崩れていたけど、今まで誰も文句を言っていないし、もう一度崩れても別に良いのでは」とコメントを付けた。 mt_rand()の返す値が変わったら困るような状況があるのなら、10年前の変更の時点で気が付かれて、すぐに直されたのではないかと。 今にして思うと、ちょっと乱暴だったかもしれない。 すっとマージされたかと思いきや、直後にリバートされた。

PHPのバグ修正の方法

この手の大規模なソフトウェアは開発環境を整えるだけで一苦労というイメージがあったけど、とても簡単だった。

git clone git@github.com:php/php-src.git
cd php-src
./buildconf
./configure
make

で、sapi/cli/phpに本体ができる。他のファイルを参考にして、tests/にテスト用のスクリプトを置くと、make testで実行される。

README.mdに書いてあるように、 https://bugs.php.net にチケットを作って、その番号を参照してプルリクを送れば良いらしい。

リバートについて

「だからPHPはダメなんだ」というような感じで叩かれているし、リバートされたときは「せっかくマージされたのにリバートするなよ……」と思ったけど、正しさよりもユーザーの利便性を優先しているからこそ、PHPはここまで流行っているのではないかと思う。 皮肉ではなく。 たとえ乱数の周期が2100になっていても困る人はいないけど、乱数の値が変わったら困る人ならいそう。

環境非依存の乱数

単に性能の良い乱数ならアルゴリズムの名前を付ける必要は無いので、各言語に実装されているメルセンヌ・ツイスタは言語が変わっても再現性のある乱数が得られるのが魅力だと思っていた。例えば、今回の修正が反映されれば、

<?php
mt_srand(12345678);
for ($i=0; $i<8; $i++)
    echo mt_rand().PHP_EOL;

#include <iostream>
#include <random>

int main()
{
    std::mt19937 rand(12345678);
    for (int i=0; i<8; i++)
        std::cout<<rand()/2<<std::endl;
}

はどちらも

527860569
1711027313
1280820687
688176834
770499160
412773096
813703253
898651287

という値を出力するようになる。C++は32bitで値を返すので、/2しているのがちょっと残念だけど。

他の言語はどうなのかと、Pythonを見てみると、genrand_int32()の値を直接取得するにはgetrandbits(32)という無理矢理感のある方法だし、init_genrand()を呼び出す手段は無いようだった。

言語間でも再現性のある乱数という需要はあまり無いのかもしれない。残念。

おまけ

私がバグチケットを作ったときに直前にあったバグが面白かった。

https://bugs.php.net/bug.php?id=71151

<?phpだけのファイルはHTMLからの脱出ができないらしい。「phpの後には空白文字が必要で、EOFは空白文字なのかという哲学的な問題だ」とRasmus氏がコメントしている。

追記

PHPでの、メルセンヌツイスタと今のmt_rand()と等価な処理の実装。乱数の値が一致する必要がある場合にはこれを使えば良さそう。

lt/PHP-MT19937: PHP implementations of MT19937, MT19937-64 and PHPs MT variant

シンガポール旅行

先月末に「家に引きこもってばかりいないで、たまには旅行しよう」と会社の同期に誘われて、シンガポールに行ってきた。せっかくなのでブログを書く。

飛行機

高級航空会社シンガポール航空。往復で6万円くらい。めったに飛行機に乗らないから値段の感覚が分からないけど、良く飛行機に乗る同期曰く「思ったよりも安かった」とのこと。噂通り、機内食は美味しかったし、機体も新しかった。

行きも帰りも深夜便を使った。寝坊して飛行機に乗り遅れる心配は無いし、時間が有効に使えるのは良いのだけど、フライトが6-7時間くらいで機内食だのがあるから正味4-5時間くらいしか寝られず、翌日が眠くて仕方が無かった。座席が良い分、深夜バスよりは寝やすかった気がする。あとは深夜バスがパーキングで休憩して時間を調節するみたいなことをしてくれれば良いのだけど、飛行機では無理か。

ドラえもん 新・のび太の宇宙開拓史」を観た。新しいドラえもんをほとんど見たことがなかったから、ドラえもんとはなかなか認識できないけれど、これはこれで面白かった。

ホテル

シンガポールで一番有名なマリーナベイサンズに1泊だけ泊まった。一番安い日を選んで1泊2万円くらい。高いけど、インフィニットプールに入れるし、空港にも観光名所にも近くて便利だし、部屋も広いしで、値段分の価値はありそう。

地上57階のインフィニットプール。水がそのまま空に繋がっているように見えるとか、そんな感じの意味での「インフィニット」だろうか。

水平線に近づいてみると、実際はこんな感じ。

f:id:kusano_k:20151229020725j:plain:w640

防水スマホだからと安心して水着のポケットに入れていたら、浸水して壊れた。防水を過信してはいけない……。

ホテルの中からは見られないけど、夜にこんな感じのレーザーショーをやっている。

エレベーターのパネルがグリーンスクリーンになっていた。

f:id:kusano_k:20151229021745j:plain:w640

2日目以降に泊まったVIPホテル。VIPだけど高くはない。

f:id:kusano_k:20151229022638j:plain:w640

ホテルのテレビで見たSUMO。早口の英語で実況していてとてもカッコ良かった。日本でも放送してほしい。

ネット環境

空港で、イモトのWiFiを借りた。現地での滞在時間ではなく、借りてから返すまでなので6日で、6400円。3日間で400MB以上だと帯域制限する可能性があるとのこと。ホテルではホテルのWiFi、街中でもWiFiがあるところではWiFiを使うように心掛けて、4日間で700MBくらい。通信量を気にするのも、スマホとは別にルーターを持ち運ぶのも面倒なので、次に海外に行くときはSIMフリーのスマホを持って行きたい。最近のスマホなら解除できるはず。

そもそも、普段から外出中にそんなにネットを使わないのだったら、ネット環境を用意していなくても何とかなる気がする。空港とかデパートとかにはWiFiがあって、ちょっと手続きをすれば使えるし、道に迷ってどうしようもなくなったとかなら、キャリアの海外ローミングをその場で使えば良いし。

場所が変わったからかGoogleの認証に弾かれて詰みかけた。2段階認証に登録していたガラケーは海外ローミング非対応で、たまたまスマホのほうも登録していて助かった。2段階認証のバックアップコードはちゃんと持ち歩こう。何回かログインしようとしたからか、アカウント1個はパスワードの変更を強制されて、あちこちのデバイスでパスワードを変えるのが面倒だった。

Google認証アプリに切り替えた。2段階認証を設定するときに、良く分からないアプリを入れたくないなと思って電話にしたけど、携帯回線に頼らない分アプリのほうが安心。

1日目

世界三大がっかりマーライオン。周りに観光客がいっぱいたから、たしかに本家マーライオンなのだろうけど、人がいなかったらレプリカだと思ってしまいそうw

ホテルにだだっ広いカジノがあった。ルーレットで自分の誕生日に置いたら当たって、150シンガポールドル儲けた。

シンガポールは日本の夏のような感じでずっと蒸し暑かったが、夕飯を食べに行ったどこかの街で地下鉄から出たら雪が降っていてびっくりした。実際はただの泡。

f:id:kusano_k:20151229022926j:plain:w640 f:id:kusano_k:20151229022929j:plain:w640

北京ダック。皮だけだと高いけど、これを頼むと肉の料理が安く頼めるので、それを考えるとまあまあ。

f:id:kusano_k:20151230040433j:plain:w640

「マリーナベイサンズの屋上のバーに行ってみよう」と誘われて行ってみたら、高級感がすごかった。ケースに入った葉巻を売っていた。葉巻を初めて見たかもしれない。「特別メニューです」と渡されたメニュー表を見たら、「○○ウイスキー○年 2000」とか書いてあって、「2000円か。けっこう高いなー」と思って良く見たらドルだった。普通のウィスキーを1杯飲んで2000円くらいだった気がする。

2日目

Anime Festival Asia 2015 in Singapore。一応これが主目的。コミケの企業ブース(一部同人エリアもあったけど)+ライブ。ライブに行くのは初めてだけど楽しかった。レーザーがかっこいい。せっかくなので光る棒も買ってみた。中にはLEDがびっしりというのを想像していたけれど、光るのは持ち手の部分だけで、棒は光を拡散させているだけなのか。

f:id:kusano_k:20151229025448j:plain:w640

日本のこういうイベントに比べて、参加者のコスプレしている率が高かった気がする。まだアニメがそんなに広まっていないので、来るのはコアな人ばかりなのだろうか。

会場で「ガラスの花と壊す世界」というアニメのポスターが貼られていて、見覚えが無いけど面白そうだな……と思っていたら、まだ未公開の劇場作品だった。そんなイベントがあるとは知らなかったけど、先行上映で本編丸ごと観られるし、声優のミニライブは聴けるしで最高だった。人を選ぶ作品だとは思うけど、私にとってはとても良かったので、公開されたらもう一度観に行こう。

3日目

あちこち歩き回った。まずは、セントーサ島

水族館。世界最大らしい

セントーサ島にもマーライオンがいた。本家よりでかいし、中にも入れる。中が派手で仙台大観音とか牛久大仏を思い出した。

カート好きの同期に誘われて、ゴーカートのようなソリのようなものに乗って遊んだ。コンクリートの坂道を自重で走るだけだけど、けっこうスピードが出る。

ケーブルカーに乗って、さよならセントーサ島

閉館ギリギリに植物園のドームに滑り込んだ。ライトアップはされているし、夜は夜で良いのかもしれないけど、暗くて良く見えないのでちょっと微妙。

f:id:kusano_k:20151230000820j:plain:w320 f:id:kusano_k:20151230001042j:plain:w320

ウツボカズラ(レゴ製)。

f:id:kusano_k:20151230001121j:plain:w640

この木の上の回廊を歩きたかったが、残念ながら時間が遅すぎた。

f:id:kusano_k:20151230004309j:plain:w640

屋台は遅い時間まで開いていたので、チキンライス。帰国直後の食戟のソーマでちょうどチキンライスが出てきた。

帰りに寄ったコンビニで皿が5個のけん玉を見つけて思わず買ってしまった。パッと見面白そうだと思ったけど、別に普通のけん玉と遊び方は変わらないような……。

4日目

適当に街中をウロウロしていた気がする。

小さい電機屋がいっぱい入っているビルがあって、秋葉原っぽかった。

誰かがゲーセンに行きたいというので着いていったら、ほとんど日本のゲーム機だった。現地の硬貨が使える台はほとんど無くて、硬貨の投入口には「100円」と書いてあった。レジで電子マネーをカードにチャージして、それで遊ぶらしい。電子マネーだとどこの国に持っていっても使えるのか。

どこかのビルの展望台からの景色。入場料も置いてある望遠鏡も無料で太っ腹。回った場所がだいたい見えて、小さな国だというのを実感。

帰国。公開直前だからかシンガポールの空港にスターウォーズの展示があった。同期がXウイングについて熱く語っていたが、スタウォーズを見たことが無いので良く分からなかった……。

f:id:kusano_k:20151230002808j:plain:w640

その他

ライブのポスター抽選に応募するときに、NRICもしくはパスポート番号を書く欄があって、何のことかと思ったら、シンガポールマイナンバーらしい。とてもカジュアルに使われていてすごい。

海外に行ったら、その国の硬貨を一通り持ち帰りたいと思っているのだけど、普通に買い物をしていて1セント硬貨は結局手に入らなかった。ガイドブックにもほとんど流通していないと書いてあった。5セント硬貨も1枚だけ。日本だとちょっと油断するとすぐ財布の中が1円玉だらけになるのに……。日本の店も198円で割安感を出すくらいなら、200円にしてほしい。

街中はどこも綺麗だったし、治安に不安は一切感じなかったし、IT化は進んでいるしで、理想の国家っぽい感じがした。一方で地下鉄には飲食したら罰金という貼り紙があったし、夜になるとコンビニで酒を売ってくれなくなったし、もしかすると綺麗すぎて息苦しいのかもしれない。

HITCON CTF 2015 Quals Crypto 200 poooooooow write-up

HITCON CTF 2015の予選にチームfuzzi3のメンバーとして参加して1問だけ解いた。

Crypto 200 poooooooow

問題サーバーに整数xを投げると、x^flag mod pを返してくる。pは、

p = 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723

p-1素因数分解すると、

p-1 = 2 * 3^336 * 4759647095086827597559114855685975263112106458932414012998147177848303887783492510354911068366203455488902018600593880874117783509946030773587965941

となる。(msieveにp-1をそのまま指定したらなぜか値が化けたので、(p-1)/2を計算して渡した。何故だろう?)

指数の底を任意に指定できる場合、位数の小さな底を渡すと逆算が可能になるという問題がある。例えば、p-1の位数は2((p-1)^2=1となる)ので、x=p-1とすると、x^flagの値はflagが偶数ならば1、奇数ならばp-1となる。同様に、位数がkの整数を底に指定すると、kが総当たり可能な程度に小さければ、flag mod kの値が分かる。

位数kを持つ底が存在する条件は、p-1が約数にkを持つこと。この問題の場合は、k = 2, 3, 6, 9, …などに対して、flag mod kの値が分かる。最初は中国人の剰余定理を使うのかなと思い、小さな素因数が2と3しかないので、法が互いに素という中国人の剰余定理の条件を満たさなあと悩んでいた。よくよく考えてみると、flag mod 3^kの値が分かっているときに、flag mod 3^(k+1)の値を求めるのは簡単だった。

位数がkの底の値(k乗根)は、離散対数などと違って大きな数字に対しても計算できるらしい。計算方法は分からないが、PARI/GPを使ったら出てきた。

(00:02) gp > p = 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723
%3 = 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723
(00:02) gp > for (i=0, 336, sqrtn(Mod(1,p), 3^i, &z); print(z))
1
Mod(104014548352862869844938168699037346159667005020653232215280909315013887004134868071692786470598745196869723476863259041566021786143181633190908349324551845723794609926567304576385405504723391936863098403039412007235326783702521959959990403821231826220564014204004925465542563989453628264120514916708791295289, 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723)
Mod(184652117342066002125654235724672107296479548524944232819111563903191006442841910870258588328187042859006937684077703029415354169137811839089174205147468046219075692488717893872876980963114118329358013489256502574078197180921037431791591430810377557558530731446903392174481754139833226637153091225821181459427, 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723)
Mod(184703592399630395992436694563840651821345959648882665358650769365293715003098677483460150685414076439977481202237026725692730858348800757738575025587940041796479236394368440075581490376984436883703286883100998351356645756513111907638957133347344001275568620875776030118946807467426690617366314494522903230861, 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723)
Mod(110911870833244863188457786643721493610784303513579129522393811396028723726659740858323669743224481525481653274103693005011435072682119191684346088511737934950819776631108869567490910585606931573400726494033281267128656345029354355593639402681259953259490212087559197723833793933264120796188614403292964375754, 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723)
  :

下記のコードで、x=3^kに対してのflag mod xが手に入る。前半のSHA-1の計算はブルートフォース防止の問題を解くため。

p = 195589859419604305972182309315916027436941011486827038011731627454673222943892428912238183097741291556130905026403820602489277325267966860236965344971798765628107804393049178848883490619438682809554522593445569865108465536075671326806730534242861732627383004696136244305728794347161769919436748766859796527723

p3 = [1,
104014548352862869844938168699037346159667005020653232215280909315013887004134868071692786470598745196869723476863259041566021786143181633190908349324551845723794609926567304576385405504723391936863098403039412007235326783702521959959990403821231826220564014204004925465542563989453628264120514916708791295289,
60596460703939283816039205007643327134157148193137267625175827451053986819941320545425174147667596081382708012312681744811027758187030913123958296233100508255282449193369626634505358810006112813774496917212618041107392205938556674774459583844872217984025489695097001179157787176195328504655348838631849663942,
10441323002096004510770587886741164350611625346463303011098537719084211549367934812572712892322805795870488891233845379359846218253172487403746893055076258863370778801037982921324392236506419913883778765063307635117884863379930809028657037691697264628883957391135108525171201634495578625408183792572214453266,
  :
]

from socket import *
from time import *
from hashlib import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(("52.69.244.164", 9003))
sleep(1)

t = s.recv(1024)
print t

prefix = t[99:99+11].replace(" ","").decode("hex")
try:
    for a in range(32,256):
     for b in range(32,256):
      for c in range(32,256):
       for d in range(32,256):
        w = prefix+chr(a)+chr(b)+chr(c)+chr(d)
        if sha1(w).hexdigest()[:6]=="000000":
         raise
except:
    pass

for i in range(len(p3)):
    s.send("%s\n"%p3[i])
    sleep(0.1)
    print "<%s>"%i, s.recv(10240)

あとは、返ってきた値からflagを求めれば良い。

flag = 0

for i in range(1,len(p3)):
   for j in range(3):
      if pow(root3[i], flag+j*3**(i-1), p) == res[i]:
      flag += j*3**(i-1)

print flag
print ("%x"%flag).decode("hex")
hitcon{CBRT_cbrt_Cbrt_CbRt_cBrT_cBRT_RePeAt......}