#なにこれ
予め決めた暗号に基づいてノイズを算出して、画像に入れるやつ。復号可能。
#目次
1、暗号化
2、復号化
3、暗号を当ててもらう
4、後書き
#暗号化
文字列の暗号を決めて、asciiコードを算出します。画像の行毎に行数と暗号の長さの余りを計算して、ノイズの値にします。当該行の全ての画素にノイズを加算します。
例えば私の暗号は「ore mo waru katta」(俺も悪かった)です→_→。
asciiコードは[111, 114, 101, 95, 109, 111, 95, 119, 97, 114, 117, 95, 107, 97, 116, 116, 97]です。
↑これにノイズを入れるよ
def encode(x,key):
return ((255,x+key) if x+key<=255 else (0,x-255+key))
↑これで、画素に入れるノイズの値を計算しますね。画素の値にノイズを加算して、255を超えたら255を引いて、0と計算の結果をreturnします。超えてない場合1と結果をreturnします。
単純すぎて申し訳ない。。。
で、画像全体に対してこうします。
def encode_image(img):
ori_img = plt.imread(img)
encode_img = np.array(ori_img,dtype='uint8')
with open('{}_code.txt'.format(img[:-4]),'w') as f:
for sub_array in encode_img[:,:,-1]:
f.write(str(list(sub_array)).replace('[','').replace(']','')+',')
f.close()
for x in range(encode_img.shape[0]):
for y in encode_img[x]:
y[-1] == 255
key = password[x%len(password)]
y[-1],y[1] = (encode(y[1],key))
img_name = 'encode_'+img[:-4]+'.png'
plt.imshow(encode_img)
print(img_name)
plt.imsave(img_name,encode_img)
画素の第二チャンネルにノイズを入れ、第四チャンネルは'255を引いたかのフラグ'として使っています。引いたら0、引いてなかったら1にすることで、復号するとき第四チャンネルの値に基づいて255を加算するかを決めますね。
(ちなみになんかこの方法アホみたい...)
(完璧に復号するため元の画像の第四チャンネルも知らないといけないから、txtに保存した...)
(さらにアホみたいになってきた...)
と!暗号化したら先の画像はこうなりました!↓
よし、使えなくなったでしょ!
#復号化
第二チャンネルに加算した値を減算して、第四チャンネルを直接オリジナル画像の第四チャンネルをコピーします...(ここ本当にアホらしい)ちなみにオリジナル画像の第四チャネルを'画像の名前_code.txt'に保存しました。
def decode(x,flag,key):
return (x-key if flag==255 else x+255-key)
↑ちなみにこのflagは第四チャネルの数値です。
で、ここ、相手に暗号を入力してもらって、入力のasciiコードを復号キーに使います。
つまり正しい暗号を入力しない限り正しく復号できないってことですね。
def test(input_):
for file in os.listdir():
if file.endswith('.png'):
encode_img = plt.imread(file)
encode_img = np.array(encode_img*255,dtype='uint8')
img = copy.deepcopy(encode_img)
with open (file[:-4]+'_code.txt','r') as f:
txt = f.read()
f.close()
code_array = np.fromstring(txt, dtype=int, sep=',')
code_array = code_array.reshape(encode_img.shape[:2])
input_password = []
for i in str(input_):
input_password.append(ord(str(i)))
print('password:',input_password)
for x in range(img.shape[0]):
for y in img[x]:
key = input_password[x%len(input_password)]
y[1] = decode(y[1],y[-1],key)
img[:,:,-1] = code_array
plt.imsave('result/{}.jpg'.format(file[:-4]+input_),img)
print('result saved as /result/{}.jpg'.format(file[:-4]+input_))
if __name__=='__main__':
test(input('please input the password:\n'))
で、例えば「'onigunsou'」(鬼軍曹)を入力するとーー
こんなりましたーー!
「'ore mo waru katta'」を入力したら?
お見事。
#暗号を当ててもらう
あとは簡単ですね。
password = [111, 114, 101, 95, 109, 111, 95, 119, 97, 114, 117, 95, 107, 97, 116, 116, 97]
init = '---_--_----_-----'
def guess_password(ate):
guess = input('please guess the password\n')
for i in guess:
if ord(i) in password and i not in ate:
ate.append(i)
print(ate)
result = ''
for j in range(len(password)):
result +=(chr(password[j]) if chr(password[j]) in ate else init[j])
print(result)
return result
def start():
init = '---_--_----_-----'
ate = ['_']
result = guess_password(ate)
while not all(chr(k) in ate for k in password):
result = guess_password(ate)
print('おめでとう!暗証番号は{}ですよ。\n私も悪かった。'.format(result))
if __name__ == '__main__':
start()
と、暗号を当ててもらいます。
ちなみにこんな感じです。
暴力で英文字を全部入力しても解けますけど...
相手に優しい暗号システムですね笑。
#後書き
Sくんにグラフの作成を頼まれて、しかし翌日喧嘩になっちゃった。
もちろん自分も悪かったけど、相手もちょっと鬼軍曹だった。。。
正直自分もちょっと怒っていたし、送りたくなかった。けど!拗ねてると言ってもやるべき事はやるでしょ。そうしないと自分も責任感のない人になっちゃうじゃん。
と思って、作ったグラフの一枚を送って、自分の非を認めて、「私悪かった。ごめん。」て言った。
しかし相手の返信遅かったし、堂々と「もう一枚もちょうだい」って書いてた。
- _ -
-_-??
何かしら自分の責任感を示しながら、- _ -??の気持ちを伝える方法ないのかなぁって思って、こういう手を考えた。
と、相手に送って、丁寧に説明して、忙しかったら放置してもいいよ、夜12時までに必ずオリジナル画像を送信しますっと言ったら。
相手は(多分暴力で解けたと思いますけど)秒で解けた。。。
流石に誰も使わないと思うので、コード適度に書きました。
まあ、プログラミングの練習になりましたし、楽しかった!
なんか人生全ての知恵を使ってしまった気がする...