他カテゴリ

Naughty Password Maker 〜 暗号の経済性 〜

sphiarno-88's icon'
  • sphiarno-88
  • 2020/06/10 05:56

 

◆ 序

Content image

 

最近は、インターネットを使わない日がほぼなくなった。便利になる一方、どのサイトでもパスワードを要求される。パスワードの使い回しは駄目だ、とはよく聞く。秘密鍵を直接保有しているような場合もいろいろ面倒だ。

それでは、パスワードをどう管理すればいいのだろうか。キーチェーン・マネージャがいいのだろうか。GoogleやiPhoneに覚えさせておけば良いのだろうか。手帳等にびっしり書き留めてみるか。それとも、パソコン画面にパスワードを記入した付箋でも貼り付けるか。あるいは、フォルダに"password"というものでも作るか。

前半の撤退障壁が強そうなのもどこかで問題が発生しそうだが、後半のものはぼちぼち考え直したほうが良いだろう。

なんとかしてパスワードを忘れていいようにできないか。第三者より早く鍵を解除できればいいのではないか。そもそも、パスワードだけで安全性が確保できるのか。有限時間内には解除されるのではないか。

今回は、知識と時間をベースにした 【NAUGHTY PASSWORD MAKER】 というものを作ってみた。これをそのまま使用した場合のパスワードの安全性は保証できない。が、これを走らせて「何がどうなると危険なのか」ということを考察するにはちょうど良いと思う。

まあ、「わがまま娘のおもちゃ」くらいのものなので、中身が分からない場合は仮想環境(サンド・ボックス等)で検証するのがいいだろう。まだ日本語での使用の記事がないツールもある。これは、経済利用目的で使用するには十分注意が必要だ。

 

 

◆ この記事(プログラム)の効用

 ・ ほどほど安全なパスワードを作れる。

 ・ パスワードを忘れても復活させる方法を得ることができる。

 ・ 公知となった情報が結合したパスワードの危険性を実感できる。

 ・ どのような場合にパスワードが危険になるか、を考えるきっかけになる。

 ・ ハッカーになったような、あるいはマイニング気分を味わえるかも

 ・ 微妙にeciespyを使用している日本語記事

 ・ シュールなポエムと笑えないジョーク(これがメイン!)

 ・ おまけ 「追憶のメモリー」

 

※ このプログラムは自身を読み取り、結果を吐きだす機能があります。おまけの保証のために作ったものなので、ファイル操作が気に入らなければ、

# get this script for encrypt (Look at me!!)

以降それも含めて6行削除し、そこに

fst = ""

を追加してください。まとめ(全文)は、下側にあります。

 

 

◆ Naughty Password Maker 概要

Content image
実行状況

 

言語:Python3

特徴的モジュール:hashlib, cryptodome, eciespy

方式:シーケンス型

ファイル操作:自身を読み出し、使用目的の結果をテキストファイルで出力

動作の流れ:

 ①ユーザー名、ドメイン名、ほかサルト等からパスワードを作成する。

 ②定型的メッセージをパスワードで暗号化する。

 ③既知を仮定した情報から鍵を生成し、暗号を復号する。

 ④秘密のメッセージを作成する。

 ⑤プログラム自身と現在時刻等をハッシュし、秘密メッセージに加える。

 ⑥秘密メッセージを暗号化し、③で生成した鍵から復号する。

 ⑦プリントアウト、作成データ部消去、ファイルアウト

 

 ※ いくつかの機能は今回はスイッチにした。

 

 

◇ 1.インポート系

# < NAUGHTY PASSWORD MAKER >                        Thought doing nothing is wrong...How about this.

# import set
import random
import hashlib                                      # use MD5
import Crypto.Cipher.AES as AES                     # use AES
import Crypto.Util.Padding as PAD
import datetime
from ecies.utils import generate_eth_key            # refer to https://pypi.org/project/eciespy/
from ecies import encrypt, decrypt                  # commits on jun 8,2018 ~   (it needs to confirm)  MIT Licence

 

今回のインポートセットである。random, datetime, hashlib はここでは説明しない。Crypto...とあるものはcryptodomeのライブラリだ。

またeciesについては、もともとecdsaとsecp256k1の情報を探していたがなぜか他のモジュールではいろいろうまくいかない。自力解決する方法も考えたが、結局eciespyというものにたどり着いた。日本語の記事がないので、やや不安だ。直接ethの鍵ペアを作成できるようだが…先にその部分を提示する。

 

# message change
if m_eth:
    eth_k = generate_eth_key()              # secret key(fmt:private key?)
    sk_hex = eth_k.to_hex()                 # secret key(fmt:hex str)
    pk_hex = eth_k.public_key.to_hex()      # public key(fmt:hex str)
    pk_adr = eth_k.public_key.to_address()  # public_address
    user_message = "eth address: " + sk_hex
    # test
    # data = b'this is a test'
    # print("secret key    : " + sk_hex)
    print("public address : " + pk_adr)
    # print(data)
    # print(encrypt(pk_hex, data).hex())
    # print(decrypt(sk_hex, encrypt(pk_hex, data)))
    

 

題名がメッセージチェンジなのは、標準メッセージを別の部分で作成しているからだが、モジュール名にethが登場している。generate_eth_key()は、どうもプライベートキー型を作成するらしい。はじめて聞いた型だが、その操作方法までは分からなかった。ただ、秘密鍵と公開鍵のペアが間違いないことまでは確認できた。内部仕様までは確認してないので、実使用には注意が必要だ。

それと英語がおかしいのを気にしてはならない。日本語は文字化けするのだ。そしてこれは当然言い訳だ。

 

 

◇ 2.入力系&操作系

# user set
user_name = "LISA18e"                               # fixed value(LISA is eternal 18 years old!)
d_name = "EASY"                                     # input domain name(big and limit 4)
ftext = 'Hello, Alis of Cryptoland!'                # fixed message (utf-8)
user_message = 'Hello, Malice of Underground!'      # input message (utf-8)

# mode set
p_test = True                                       # password research test(weight by LISA's...)
p_dsp = True                                        # display password
m_dsp = True                                        # maybe LISA's secret...
m_eth = False                                       # change message to eth address ??
f_out = False                                       # file out for public

 

# user set はユーザ情報を想定している。

LISAは永遠の18才らしい。世の中なんて楽勝だったのだろう。

ftext はお決まりの挨拶(定形文)を想定している。中身の多様性や変化も大事だ、という主張のために固定文としている。

秘密のメッセージは私が個人的に好きなフレーズだ。Underground よりは Wonderland が一般的に使われているようだ。英語としては恥ずかしい系の雰囲気になるのだろう…が、秘密にしたいメッセージならなんでも良い。

 

# mode set は操作スイッチだ。

p_test:パスワードを探索するか?
p_dsp:パスワードを表示するか?
m_dsp:秘密のメッセージを表示するか?
m_eth:秘密のメッセージを変更するか?
f_out:ファイル出力するか?

パスワード探索はある仮定のもとで行う。デフォルトでオンにしているが、難度によりオフにした方がいいときがある。

ファイル出力はオフのままで良い。また、理由等いろいろ触れていない部分は有料部分でお分かりいただけるであろうから、ここではあえて述べない。ファイル出力した箇所の例は、プログラム全文のあとに掲載する。

 

 

◇ 3.変換セット

#  trans set
weight = 3                                                                      # Don't ask Lady!!
u_num = pow(18, weight)                                                         # difficulty( of LISA...)
pw_len = 16                                                                     # fixed by AES ?
r_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-*$%"   # len: 67
r_frm = ",|:"                                                                   # len: 3 ,those are litter
f = r_frm[int(hashlib.md5((user_name + d_name).encode()).hexdigest(), 16) % 3]  # frame is determined by u_set

print("identify:" + user_name + f + d_name + f)                                 # suppose it is known

 

変換セットだ。weight で難度を調性する。作成する分には重くしてもどうということはないが、探索スイッチがオンの場合はどんどん重くなる。18の何乗かというオーダーだが、それでも最近のパソコンの計算速度はとんでもないことが分かる。6くらいまではやってみた。

なお最初は探索するために「空の配列」を使用しどんどん鍵のリストを作成投入し、あとで検証する、という方法をとっていた。ちょっと考えたら分かるが、パソコンが鍵の山になるところだった。ふう、危ない危ない。

変換方法は、目的物がパスワードなのでそれなりの文字リストにした。除算するのに素数の方が良さそうなので素数個にしている。変えても構わない。

フレーム表示のためと言いながら、追加のゴミも加えた。ゴミを加えるのにMD5で選択しているのだから、なんとも贅沢なゴミだ。駄菓子菓子、割と役立つゴミだ。

ユーザ情報のうち公開系のものは公知であると仮定し、表示している。

しかし公知であっても、レディに年齢と体重を聞いてはならないようだ。

 

 

◇ 4.サルト等追加とキー作成

# salt and litter frame
r = random.randint(0, u_num)
# r = r                                                                         # for test
text = user_name + f + d_name + f + str(r)
pw_str = ""

# hash key -> password (suppose method is known)
mdl = 0
for i in range(pw_len):
    md5 = int(hashlib.md5((text + str(mdl) + str(i)).encode()).hexdigest(), 16) # a foolish chain
    mdl = md5 % len(r_str)
    pw_str = pw_str + r_str[mdl]

 

サルトとゴミフレームを追加したあとで、パスワードを作成している。他の値が所与であるならば、rの値でパスワードが決定する。rの値は0から難度で計算した18^nまでの乱数だ。逆に考えて難度を決めておけば、それまでの中に目的のパスワードが存在する、ということになる。難度を1にして18通りのなかのどれかを使用する、という方法なら、生成要素が分かれば忘れても発見できる。不安ならrにバイアスをかけるのも手だ。まあそれでも、大事なものであるなら使用を勧めない。

なお少し話は変わるが、サルトが分からない場合は、レインボー攻撃の知識が必要だ。戦隊モノで出てきそうな、全員のコンビネーション攻撃のような名前に惑わされてはならない。ただ、コンビネーション(分散化)はあながち間違ってない。また、マイニングは適当なゼロの数量で相手方が降参してくれるが、分散処理攻撃という意味では同じだ。

参考)レインボー攻撃 wikipedia より

基本的に全ての暗号化されたメッセージは、解読することに経済的合理性が存在するならば有限時間で解読される、と考えた方が良い。逆に、解読しないことに経済的合理性が存在するならば、それらには固定化される力が働く、という考えだ。

ただ現実のサルトは塩とは思えないくらいの大きさをもっている(マヨラーがかけるマヨネーズの量を想像するとよい)が、問題はそこではない。破られるなら繋いで固定化した方が良い。繋げば早いものが確定されたものだ、という考えはブロックチェーンに限った話ではない。

 

 

◇ 5.いろいろ

# display password
if p_dsp:
    print("Hello, \"" + text + "\" !   password:" + pw_str)
print('')

# create key(byte type)
key1 = pw_str.encode()
key2 = key1

# get this script for encrypt (Look at me!!)
path = __file__
with open(path) as fpy:
    fst = fpy.read()
    # print(type(fst))
    # print(fst)

 

パスワードを表示するかどうかはスイッチにしている。

そのままではただの文字列なので型変換をしている。これは共通鍵だが、key1が暗号用、key2を復号用にしている。もし探索をオンにしていれば、あとでkey2はリフレッシュされてから探索される。(という設定にしている。実際には別の用事のためにダミーのキーを使用している。)

またここで自分自身のファイルを文字として読み出している。

LISAはお嬢様なので、気にしてあげないといけなかったのだ。

 

 

◇ 6.秘密メッセージをセット化

# secret message set
now = datetime.datetime.now()
add_ms1 = "p_test:" + str(p_test) + ", p_dsp:" + str(p_dsp) + ", m_dsp:" + str(m_dsp) \
         + ", m_eth:" + str(m_eth) + ", f_out:" + str(f_out) + ", weight:" + str(weight) \
          + ", Done:" + str(now)
add_ms2 = ", pg_digest:0x" + hashlib.md5((fst + str(now)).encode()).hexdigest()         # Now Only
message = user_message + "(" + add_ms1 + add_ms2 + ")"

 

特に言うことはないが、現在時刻を取得して自分自身と合わせてハッシュ化し、更にその他データと合わせて秘密メッセージに追加している。認証時刻ではないので公証性はないが、まあ必要性もそこまではないだろう。偽装することを私が面倒なだけだし、そもそも今回の場合、テストモードで行えば中身は見えてしまうのだ。

 

 

◇ 7.定形メッセージを暗号化

# encrypt(AES) fixed message (use key1)
iv = b'0' * 16
aes = AES.new(key1, AES.MODE_CBC, iv)
data1 = PAD.pad(ftext.encode('utf-8'), 16, 'pkcs7')
cipher = aes.encrypt(data1)
print("encrypt message:0x", cipher.hex())

 

ここでは 'Hello, Alis of Cryptoland!' という、お決まりの定型文があると仮定する。cipherが暗号文だが、それを16進数に変換し表示している。

 

 

◇ 8.定形メッセージを復号化

# decrypt(AES) fixed message (use key2)
# set for hack (now, do nothing)
dec_message = cipher.hex()                              # or = "(hex excluded '0x')"
cipher1 = bytes.fromhex(dec_message)
sec_name = user_name
sec_dn = d_name
sec_f = f
key2_dummy = ""
if p_test:                                              # password hack test
    start_time = datetime.datetime.now()
    for i in range(u_num + 1):
        key3 = ""
        mdl = 0
        test_nm = sec_name + sec_f + sec_dn + sec_f + str(i)
        for j in range(pw_len):
            md5 = int(hashlib.md5((test_nm + str(mdl) + str(j)).encode()).hexdigest(), 16)
            mdl = md5 % len(r_str)
            key3 = key3 + r_str[mdl]
        k = key3.encode()
        aes = AES.new(k, AES.MODE_CBC, iv)
        data = PAD.pad(ftext.encode('utf-8'), 16, 'pkcs7')
        cipher_v = aes.encrypt(data)
        if cipher1 == cipher_v:                         # collesponded fixed message
            end_time = datetime.datetime.now()
            cost_time = (end_time - start_time).total_seconds()
            key2_dummy = k                              # discover key2 !! (key2_dummy == key2)
            print("decrypt hack is scceed!! ( try_times:" + str(i + 1) + ", seconds:"
                  + str(cost_time) + ", key:" + key3 + " )")
            break
    aes = AES.new(key2_dummy, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher1)
    plain = PAD.unpad(data2, 16, 'pkcs7')
else:
    aes = AES.new(key2, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher)
    plain = PAD.unpad(data2, 16, 'pkcs7')
print("decrypt message:" + plain.decode('utf-8'))
print("")

 

少し冗長になっているのは、鍵がないものとして公知となっている情報(名前等、定型文、暗号方法)から鍵を探索できるフレームにしているからだ。逆に忘れてしまったときは最初でもここからでも探索できる。

暗号方法は今回はオリジナルの文字列だが、通常は定形化されているものだ。したがって今回探索するのはサルトだけだが、どれくらいで探索できるかということは計測できる。今回のサルトとゴミを除いた本体の選択可能性は70^10くらいだろう。

通常、パスワードの長さだけで安全性を担保しているわけではない(応答時間や停止、毎回鍵がかわる通信方法等も考慮)が、短いものや単純すぎるものの危険性は分かるだろう。

探索スイッチはオンにしている。LISAを怒らせたらどのくらい計算できるか試してみるのもよかった。オフのときはバイパスで復号する。

また、これで出力された過去のものを探索するときは、

dec_message = "a298372742fea2cfc0ecde96608c063917debad01c8b8e3d5def4765978605f9"
cipher1 = bytes.fromhex(dec_message)
sec_name = "LISA18e"
sec_dn = "EASY"
sec_f = ","
key2_dummy = ""

のように変更すればいい。

 

 

◇ 9.秘密メッセージを暗号化

# encrypt message(AES) use key1
iv = b'0' * 16
aes = AES.new(key1, AES.MODE_CBC, iv)
data1 = PAD.pad(message.encode('utf-8'), 16, 'pkcs7')
cipher_m = aes.encrypt(data1)
print("encrypt message:0x", cipher_m.hex())

 

定形メッセージの暗号化の時と同じだ。ただし、とても長い。

 

 

◇ 10.秘密メッセージを復号化

# decrypt message(AES) use key2
if m_dsp:
    # set for hack (now, do nothing)
    key2 = key2                                                 # or = "(password)".encode()
    dec_message = cipher_m.hex()                                # or = "(hex excluded '0x')"
    cipher_m = bytes.fromhex(dec_message)
    # decrypt
    aes = AES.new(key2, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher_m)
    plain = PAD.unpad(data2, 16, 'pkcs7')
    print("decrypt message:" + plain.decode('utf-8'))

 

これも冗長なのは、定形メッセージの解読から手に入れた鍵で暗号化された秘密メッセージを復号するためだ。該当箇所を、

    key2 = "2+wTU5DQft7yV5d3".encode()
    dec_message = "3924649de5dc739da91b9d720118936c6e129e2b8b996df53b3294063de9fcd9acd73be3067f5b91c79c7e" \
                  "3aed3f47a16d9adb43e085ea56131c29fc3e81a12c99eded557cee124a3cc296c7731117fad99fd8506d48" \
                  "0ba098d7b4270bc605fe7bca39be278228293bee141954d483caa7385db9b4117be13c93bb7d00b243996d" \
                  "cd6c12a1510830789d3e259567e5e51730a21d4552dec4634942aa48d8f91a13d948457caeb6a873f470f8" \
                  "1997731da46ac4984d946fb9a8da911d62f82d62"

のように書き換えたらいい。

そして解読の選択のためのスイッチが、なぜかここにもついている。

 

 

◇ 11.サヨナラ、私の記憶よ...

# good-by my secret memory...
key1 = key2 = key2_dummy = key3 = k = r = ""
text = pw_str = aes = data = data1 = data2 = plain = ""
eth_k = sk_hex = user_message = message = ""
add_ms1 = add_ms2 = fst = ""

 

かなしい思い出、にがい記憶、つらかった過去。

そんなものも消えてしまうと思うと、これも人生なんだなあと思う。

人生かたなし。パイソン型なし?

 

 

◇ 12.そして記録だけが残った

# file out
if f_out:
    with open('NaughtyPM-t.txt', 'w', encoding='utf-8') as file:
        file.write("user_name  :" + user_name + '\n')
        file.write("domain_name:" + d_name + "\n\n")
        file.write("p_test:" + str(p_test) + ", p_dsp:" + str(p_dsp) + ", m_dsp:" + str(m_dsp) +
                   ", m_eth:" + str(m_eth) + ", f_out:" + str(f_out) + '\n')
        file.write("weight(assumption):" + str(weight) + ", Done:" + str(now) + "\n\n")
        file.write("well-known fixed message:" + ftext + '\n')
        file.write("encrypted fixed message :0x\n" + cipher.hex() + "\n\n")
        file.write("encrypted secret message:0x\n" + cipher_m.hex() + '\n')

 

※ このスイッチをオンにして走らせると、これを置いた場所に形式的な記録がテキスト形式でファイルアウトされます。こんな感じです。

 

 

user_name  :LISA18e
domain_name:EASY

p_test:True, p_dsp:True, m_dsp:True, m_eth:False, f_out:True
weight(assumption):3, Done:2020-06-13 08:18:55.480350

well-known fixed message:Hello, Alis of Cryptoland!
encrypted fixed message :0x
0f17f03c1a9f828888cb8d9458ad3b234a07ed797c7e7ec67cce04a5ba78b9dc

encrypted secret message:0x
651ebd0a1cac905faf2f4cf5ad53156e77748add6a1283bfa82f597212eae24c7fbc131b27fb5003aef471c6dce39a9146a146e8ff00cbd29021f239ad0c67a431f93559b336f8259e44266ad2fec11cfac908a04585f319fc823db53959a4b691e80572752338e69be87fee6684427dc4b246fa2aa3804055bb7f2888abd05358db1bd24fa89bcbfbd97bfa585a39e4de89505205b16b43e3768a101ef5617fa861992cb2d7c87bbbf5b06f7e22ac70277567465f440673f36ffe9be0b603a4

 

 

あのときLISAは、何を言っていたのだろうか…

 

 

◆ まとめ(全文です)

 

# < NAUGHTY PASSWORD MAKER >                        Thought doing nothing is wrong...How about this.

# import set
import random
import hashlib                                      # use MD5
import Crypto.Cipher.AES as AES                     # use AES
import Crypto.Util.Padding as PAD
import datetime
from ecies.utils import generate_eth_key            # refer to https://pypi.org/project/eciespy/
from ecies import encrypt, decrypt                  # commits on jun 8,2018 ~   (it needs to confirm)  MIT Licence

# user set
user_name = "LISA18e"                               # fixed value(LISA is eternal 18 years old!)
d_name = "EASY"                                     # input domain name(big and limit 4)
ftext = 'Hello, Alis of Cryptoland!'                # fixed message (utf-8)
user_message = 'Hello, Malice of Underground!'      # input message (utf-8)

# mode set
p_test = True                                       # password research test(weight by LISA's...)
p_dsp = True                                        # display password
m_dsp = True                                        # maybe LISA's secret...
m_eth = False                                       # change message to eth address ??
f_out = False                                       # file out for public

#  trans set
weight = 3                                                                      # Don't ask Lady!!
u_num = pow(18, weight)                                                         # difficulty( of LISA...)
pw_len = 16                                                                     # fixed by AES ?
r_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-*$%"   # len: 67
r_frm = ",|:"                                                                   # len: 3 ,those are litter
f = r_frm[int(hashlib.md5((user_name + d_name).encode()).hexdigest(), 16) % 3]  # frame is determined by u_set

print("identify:" + user_name + f + d_name + f)                                 # suppose it is known

# salt and litter frame
r = random.randint(0, u_num)
# r = r                                                                         # for test
text = user_name + f + d_name + f + str(r)
pw_str = ""

# hash key -> password (suppose method is known)
mdl = 0
for i in range(pw_len):
    md5 = int(hashlib.md5((text + str(mdl) + str(i)).encode()).hexdigest(), 16) # a foolish chain
    mdl = md5 % len(r_str)
    pw_str = pw_str + r_str[mdl]

# display password
if p_dsp:
    print("Hello, \"" + text + "\" !   password:" + pw_str)
print('')

# create key(byte type)
key1 = pw_str.encode()
key2 = key1

# get this script for encrypt (Look at me!!)
path = __file__
with open(path) as fpy:
    fst = fpy.read()
    # print(type(fst))
    # print(fst)

# message change
if m_eth:
    eth_k = generate_eth_key()              # secret key(fmt:private key?)
    sk_hex = eth_k.to_hex()                 # secret key(fmt:hex str)
    pk_hex = eth_k.public_key.to_hex()      # public key(fmt:hex str)
    pk_adr = eth_k.public_key.to_address()  # public_address
    user_message = "eth address: " + sk_hex
    # test
    # data = b'this is a test'
    # print("secret key    : " + sk_hex)
    print("public address : " + pk_adr)
    # print(data)
    # print(encrypt(pk_hex, data).hex())
    # print(decrypt(sk_hex, encrypt(pk_hex, data)))

# secret message set
now = datetime.datetime.now()
add_ms1 = "p_test:" + str(p_test) + ", p_dsp:" + str(p_dsp) + ", m_dsp:" + str(m_dsp) \
         + ", m_eth:" + str(m_eth) + ", f_out:" + str(f_out) + ", weight:" + str(weight) \
          + ", Done:" + str(now)
add_ms2 = ", pg_digest:0x" + hashlib.md5((fst + str(now)).encode()).hexdigest()         # Now Only
message = user_message + "(" + add_ms1 + add_ms2 + ")"

# encrypt(AES) fixed message (use key1)
iv = b'0' * 16
aes = AES.new(key1, AES.MODE_CBC, iv)
data1 = PAD.pad(ftext.encode('utf-8'), 16, 'pkcs7')
cipher = aes.encrypt(data1)
print("encrypt message:0x", cipher.hex())

# decrypt(AES) fixed message (use key2)
# set for hack (now, do nothing)
dec_message = cipher.hex()                              # or = "(hex excluded '0x')"
cipher1 = bytes.fromhex(dec_message)
sec_name = user_name
sec_dn = d_name
sec_f = f
key2_dummy = ""
if p_test:                                              # password hack test
    start_time = datetime.datetime.now()
    for i in range(u_num + 1):
        key3 = ""
        mdl = 0
        test_nm = sec_name + sec_f + sec_dn + sec_f + str(i)
        for j in range(pw_len):
            md5 = int(hashlib.md5((test_nm + str(mdl) + str(j)).encode()).hexdigest(), 16)
            mdl = md5 % len(r_str)
            key3 = key3 + r_str[mdl]
        k = key3.encode()
        aes = AES.new(k, AES.MODE_CBC, iv)
        data = PAD.pad(ftext.encode('utf-8'), 16, 'pkcs7')
        cipher_v = aes.encrypt(data)
        if cipher1 == cipher_v:                         # collesponded fixed message
            end_time = datetime.datetime.now()
            cost_time = (end_time - start_time).total_seconds()
            key2_dummy = k                              # discover key2 !! (key2_dummy == key2)
            print("decrypt hack is scceed!! ( try_times:" + str(i + 1) + ", seconds:"
                  + str(cost_time) + ", key:" + key3 + " )")
            break
    aes = AES.new(key2_dummy, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher1)
    plain = PAD.unpad(data2, 16, 'pkcs7')
else:
    aes = AES.new(key2, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher)
    plain = PAD.unpad(data2, 16, 'pkcs7')
print("decrypt message:" + plain.decode('utf-8'))
print("")

# encrypt message(AES) use key1
iv = b'0' * 16
aes = AES.new(key1, AES.MODE_CBC, iv)
data1 = PAD.pad(message.encode('utf-8'), 16, 'pkcs7')
cipher_m = aes.encrypt(data1)
print("encrypt message:0x", cipher_m.hex())

# decrypt message(AES) use key2
if m_dsp:
    # set for hack (now, do nothing)
    key2 = key2                                                 # or = "(password)".encode()
    dec_message = cipher_m.hex()                                # or = "(hex excluded '0x')"
    cipher_m = bytes.fromhex(dec_message)
    # decrypt
    aes = AES.new(key2, AES.MODE_CBC, iv)
    data2 = aes.decrypt(cipher_m)
    plain = PAD.unpad(data2, 16, 'pkcs7')
    print("decrypt message:" + plain.decode('utf-8'))

# good-by my secret memory...
key1 = key2 = key2_dummy = key3 = k = r = ""
text = pw_str = aes = data = data1 = data2 = plain = ""
eth_k = sk_hex = user_message = message = ""
add_ms1 = add_ms2 = fst = ""

# file out
if f_out:
    with open('NaughtyPM-t.txt', 'w', encoding='utf-8') as file:
        file.write("user_name  :" + user_name + '\n')
        file.write("domain_name:" + d_name + "\n\n")
        file.write("p_test:" + str(p_test) + ", p_dsp:" + str(p_dsp) + ", m_dsp:" + str(m_dsp) +
                   ", m_eth:" + str(m_eth) + ", f_out:" + str(f_out) + '\n')
        file.write("weight(assumption):" + str(weight) + ", Done:" + str(now) + "\n\n")
        file.write("well-known fixed message:" + ftext + '\n')
        file.write("encrypted fixed message :0x\n" + cipher.hex() + "\n\n")
        file.write("encrypted secret message:0x\n" + cipher_m.hex() + '\n')

 

※ この中で & が & にどんどん変形するようです。

私がこのページを開いたり閉じたりするたびに、どんどん増えるポケットビスケットだ。エスケープ処理の残骸と思われるが、「そういう意味」ではアンプ攻撃の脆弱性が存在するといえるかもしれない。アンプップ。

※ 正しい意味のアンプ攻撃ではありません。

※ なので & を消して and にしました。

 

 

◇・◇・◇・◇・◇・◇・◇・◇・◇

 

本文はここまでです。長いポエムでした。

おつかれさまです。そして、ありがとうございます。

 

ここから先は追憶のメモリーです。

 

 

Article tip 0人がサポートしています
獲得ALIS: Article like 20.89 ALIS Article tip 0.00 ALIS
sphiarno-88's icon'
  • sphiarno-88
  • @sphiarno-88
くるくる回る人

投稿者の人気記事
コメントする
コメントする
こちらもおすすめ!
Eye catch
クリプト

NFT解体新書・デジタルデータをNFTで販売するときのすべて【実証実験・共有レポート】

Like token Tip token
121.79 ALIS
Eye catch
トラベル

わら人形を釘で打ち呪う 丑の刻参りは今も存在するのか? 京都最恐の貴船神社奥宮を調べた

Like token Tip token
486.35 ALIS
Eye catch
トラベル

梅雨の京都八瀬・瑠璃光院はしっとり濃い新緑の世界

Like token Tip token
216.64 ALIS
Eye catch
クリプト

約2年間ブロックチェ-ンゲームをして

Like token Tip token
61.20 ALIS
Eye catch
ビジネス

海外企業と契約するフリーランス広報になった経緯をセルフインタビューで明かす!

Like token Tip token
16.10 ALIS
Eye catch
クリプト

Bitcoinの価値の源泉は、PoWによる電気代ではなくて"競争原理"だった。

Like token Tip token
159.32 ALIS
Eye catch
他カテゴリ

オランダ人が語る大麻大国のオランダ

Like token Tip token
46.20 ALIS
Eye catch
クリプト

ジョークコインとして出発したDogecoin(ドージコイン)の誕生から現在まで。注目される非証券性🐶

Like token Tip token
38.31 ALIS
Eye catch
他カテゴリ

機械学習を体験してみよう!(難易度低)

Like token Tip token
124.82 ALIS
Eye catch
他カテゴリ

警察官が一人で戦ったらどのくらいの強さなの?『柔道編』 【元警察官が本音で回答】

Like token Tip token
114.82 ALIS
Eye catch
他カテゴリ

警察官が一人で戦ったらどのくらいの強さなの?『柔道編』 【元警察官が本音で回答】

Like token Tip token
114.82 ALIS
Eye catch
ゲーム

【初心者向け】Splinterlandsの遊び方【BCG】

Like token Tip token
6.32 ALIS