ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

base64でエンコードとデコードをしてみる

少しセキュリティについて勉強を。

作ったwebアプリをherokuからVPSへ移行するにあたって、少しセキュリティの知識が必要になりました。

何とか移行してサーバーにファイアーウォールを設定して、ポートのhttpとhttpsのポートだけをとりあえず開けましたが、他に何をするべきかわかりません。

遠回りにはなるけども、この際、ちょっとセキュリティについて勉強しようかなと。

株系のこともやりたいけれども、少し休憩しています。


ということで今日は簡単なセキュリティの記事です。

base64はとってもシンプルで汎用性抜群のエンコード方式

MIME等のプロトコルでも使用されます。

しかし、あくまでもエンコード方式です。

#base64でエンコードした文字列
Y29ib2wgaXMgZm9zc2lsCg==

人には読めませんが、方式さえ知っていれば(みんな知っている)簡単にデコード可能なので、セキュアに保ちたいならさらにハッシュをかけるなどの対策が必要です。

最もシンプルなbasic認証は、ユーザー名とパスワードをbase64エンコードしていますが、セキュリティを担保しているとは口が避けても言えなさそうです。

ほとんどのブラウザが対応しているため頻繁に使用されていますが。

#ちなみにさっきの文字列をデコードしたら...
cobol is fossil

(ただのエンコード方式なので、デコードできるのは当たり前ですが...)



本来のbase64の目的は、どんな形式のデータでもbase64に変換して送ることができるという部分。(おそらく)

画像でも動画でも。

base64に変換してみる

base64エンコード手順です。(wikiからの引用)

1. 元データ
文字列: "ABCDEFG"
16進表現: 41, 42, 43, 44, 45, 46, 47
2進表現: 0100 0001, 0100 0010, 0100 0011, 0100 0100, 0100 0101, 0100 0110, 0100 0111

2. 6ビットずつに分割
010000 010100 001001 000011 010001 000100 010101 000110 010001 11

3. 2ビット余るので、4ビット分0を追加して6ビットにする
010000 010100 001001 000011 010001 000100 010101 000110 010001 110000

4. 変換表により、4文字ずつ変換
"QUJD", "REVG", "Rw"

5. 2文字余るので、2文字分 = 記号を追加して4文字にする
"QUJD", "REVG", "Rw=="

6. Base64文字列
"QUJDREVGRw=="

Base64 - Wikipedia



base64エンコードするとき
base64 エンコードファイル

base64 encode_file


base64にデコードするとき
base64 -d デコードファイル

base64 -d decode_file

標準入力からbase64エンコード

echo "cobol is fossil" | base64

#出力結果
Y29ib2wgaXMgZm9zc2lsCg==


標準入力からbase64でデコード

echo "Y29ib2wgaXMgZm9zc2lsCg==" | base64 -d

#出力結果
cobol is fossil

以上、終わり

ROT13をPythonで実装してみる

ROT13って何?

ROT13 または ROT-13、rot13 は単換字式暗号(シーザー暗号)の一つである。アルファベットを一文字毎に13文字後のアルファベットに置き換える。Aは Nに、 B は O に置き換えられ、以下同様である。英語の "Rotate by 13 places" の略。ネットワーク上のやりとり(電子掲示板、ネットニューズ、フォーラム等)で冗談の落ち、パズルの解法、ネタばれ情報、不快表現等を隠すのに用いられるアルゴリズムである。実際には暗号というほどのものではないが、ちょっと見に読んでしまうという事態は避けられる。雑誌などでクイズの正解を上下逆さまに印刷するが、それと似たようなものである。

ROT13 - Wikipedia

実装手順

この文字はROT13で暗号化された文字です。

pboby vf sbffvy.

文字にそのまま13は足せないので、一度この文字列をASCIIの数値に変換します。

以下、ASCIIコードの数値と文字の対応表のURL。

文字と数値 | サルにも分かるRSA暗号

112 98 111 98 121 32 118 102 32 115 98 102 102 118 121 46

ASCIIの数値に変換するとこうなります。


文字コードに変換してから、13を足すか引くかの条件を分岐するので、ASCIIの文字コードに変換した時

  • 65〜77であれば、プラス13
  • 78〜90であれば、マイナス13
  • 97〜109であれば、プラス13
  • 110〜123であれば、マイナス13

これで、A〜Z、a〜zの対応付けすることができます。


以下、簡単な対応表です。

A - M 65 - 77
N - Z 78 - 90
a - m 97 - 109
n - z 110 - 123

実装してみる

contents = "pboby vf sbffvy."
process = ""
for script in contents:
	num = ord(script)

	#space or period
	if num == 32 or num == 46:
		ascii_script = chr(num)

	#A - M
	elif num >= 65 and num <= 77:
		ascii_script = chr(num + 13)

	#N - Z
	elif num >= 78 and num <= 90:
		ascii_script = chr(num - 13)

	#a - m
	elif num >= 97 and num <= 109:
		ascii_script = chr(num + 13)

	#n - z
	elif num >= 110 and num <= 123:
		ascii_script = chr(num - 13)

	process += ascii_script

print(process)

このプログラムをじっこうした結果

cobol is fossil.

こうなります。

まとめ

最近は新人研修に勤しむ毎日です。

しかも、なななんとcobolの研修なので楽しくて楽しくてたまりません汗

以上終わり。

seleniumで自動売買 〜SBI証券から自動で株を買ってみる〜

自動売買ってどうやってやるの?

アルゴリズムトレードが昨今流行りではありますが。

残念ながら日本の証券会社は一般向けに株式売買のAPIは公開されていません。

そのため、APIを通してのアルゴリズムによる株の自動売買は現状できません。

FXやビットコインAPIが公開されているので、アルゴリズムで自動売買を行っている人が多いようですが、株式で自動売買をやっている人があまりいないのはここらへんの理由かと思います。

(高頻度取引は東京証券取引所に登録すれば可能なようですが、調べてもあまり情報がでてきません、個人では行えず法人のみっぽいです)

最近、銀行の取引をAPI化して業務提携をする動きが盛んになってきていますが、証券会社が売買等のシステムをAPI化する話はあまり聞きません。

こういった話は国主導で進めるので、明日急にAPI公開なんてことにはならないので、株式売買のAPI公開はいったん諦めましょう。


では、どうやるか。

どうやらseleniumというウェブのUI自動テストツールが使えそうです。

seleniumはクリックや文字入力をプログラムを通して、自動で行えることができるライブラリです。

もともとはシステムのテストを自動化する目的で発展してきたようですが、これを使ってウェブを操作することもできます。

つまり、SBI証券にログインして、株を売買する動きもseleniumで再現できるということです。

seleniumの簡単な使い方の記事

前にyoutubeで「yui」と検索するコードをseleniumで書きました。

doz13189.hatenablog.com

これをちょっと変えるだけで、SBI証券にログインして株を売買するってのはできそうです。

SBI証券にログインして株を買ってみる

import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys


class PythonOrgSearch(unittest.TestCase):


	def setUp(self):
		
		self.driver = webdriver.Chrome("/home/ubuntu/robo/chromedriver")


	def test_serch_in_python_org(self, signal=1):
		driver = self.driver

		#SBI証券のHP
		driver.get("https://www.sbisec.co.jp/ETGate")

		#SBI証券のログインID
		driver.find_element_by_name("user_id").send_keys("login_id")

		#SBI証券のログインパスワード
		driver.find_element_by_name("user_password").send_keys("login_password")
		driver.find_element_by_name("ACT_login").click()

		driver.find_element_by_xpath('//div[@id="link02M"]/ul/li[2]').click()

		if signal == 1:
			PythonOrgSearch.buy(self)

		elif signal == 0:
			PythonOrgSearch.sell(self)


	def tearDown(self):
		self.driver.close()


	def buy(self):
		print("buy")

		driver = self.driver

		#現物買にチェック
		driver.find_element_by_name("trade_kbn").click()
		
		#銘柄コードを入力
		driver.find_element_by_name("stock_sec_code").send_keys(1305)
		
		#売買株数を入力
		driver.find_element_by_name("input_quantity").send_keys(100)
		
		#価格指定
		driver.find_element_by_xpath('//td[@id="gsn1"]/input').click()

		#預かり区分を指定
		driver.find_element_by_name("hitokutei_trade_kbn").click()
		
		#取引パスワードを入力
		driver.find_element_by_name("trade_pwd").send_keys("trade_password")

		#注文確認画面をクリック
		driver.find_element_by_name("ACT_estimate").click()

		#注文発注
		driver.find_element_by_name("ACT_place").click()


	def sell(self):
		print("sell")

if __name__ == "__main__":
    unittest.main()

HTMLの構造上、find_element_by_nameで要素を取得できない部分はxpathを使いました。

成行か指値か、を選択するところがまさにそれで、仕方がなくxpathを使っています。

SBI証券はHPにJaveScriptを使用していないので、selenium単体で全ての操作を完結させることができました。

selenium自体の使い方はシンプルなので、コードを書くと言ってもHTMLの構造を読むのがメインでした。

このコードを実行すると...

銘柄コード1305の株を100株、成行で買います。

東京証券取引所が開いている時間に実行すると、本当に約定してしまうので夜に実行しましたが、しっかりと注文できました。

seleniumゆえの欠点

上記のコードは単体テストのライブラリをインポートして、全ての操作の開始から終了までの時間を計測しています。

結果的に全ての操作を終えるのに、22秒程度かかります。

インターネットの接続状況によってはもう少しかかる場合もあります。

つまり、注文に時間がかかりすぎです。

1日1回や2回程度ならこの程度のスピードで十分ですが、頻度を上げるには少し実行速度が遅いように思います。

そのため、売買まで20〜30秒程度なら許容できるアルゴリズム取引戦略が必要になります。

デイトレをするには心もとないので、やはりスイングトレードかなぁなんて思っています。


以上終わり。

環境変数パス(PATH)がよくわからいのでunset $PATHしてみた

Linuxを使用している人なら、いや、WindowsでもOS Xでも、環境変数が何たるかをわかっている人なら、このタイトルのヤバさはわかるはずです。

普通に考えたら、絶対にやってはいけないコマンドをうってみました。

そもそもPATHを通すってなんだ?

pythonをインストールしても、pipをインストールしても、PATHを通す作業って必ず、必要です。

しかし、私はめんどくさがりなのでパスを通す必要がある場合は、いつも記事内に貼ってあるPATHをコピペで済ましていました。

export PATH=$PATH:/var/www/html

このコードさえあれば、理解していないくてもとりあえず動くようになるからそれでいいや、と済ましていました。


と、言ってもPATHを通すってことの意味が全くわからないわけではありませんでした。

なんとなく、「PATHを通すこと、どのディレクトリにいても指定のコマンドが実行できるようになる」ぐらいのことは頭でわかっていました。

頭でわかっていても、実際に自分でファイルを作って実行するコードを書いて、環境変数PATHを通すということはやったことなかったので、曖昧な理解にとどまっていました。


わかっていると思っていても、詳細を詰められると実はわかっていないことってたくさんあります。

私にとってPATHを通すは、まさに詳細を詰められると実はわかっていない領域でした。

厳しい環境にあえて身を置く

ということで、まずPATHが通っているということがどれだけありがたいことかを理解するためにPATHを消してみました。

PATHがない世界に身を置くことで、PATHの本質を理解しようとそういう魂胆です。

※もし、Linux初心者の方であれば、絶対に真似しないでください

※私はVPSでこれを実行しています。
※最悪、Linuxが壊れたらインストールし直せばいいか、くらいの軽い気持ちなのでこのコマンドをうてるだけです。
VPSって実験するには本当にいい場所です。

unset $PATH

このコマンドを入力してlsコマンドを入力すると...

#ls

Command 'ls' is available in '/bin/ls'
The command could not be located because '/bin' is not included in the PATH environment variable.
ls: command not found

ウソやろ、ls使えへんやん。

他にもcd、vi、find、cat全部使えへん。

エラーをよく見ると、/bin/lsのディレクトリに行けばlsが実行できると書いてあります。

ということは/bin/lsと打てば、lsコマンドが実行できるはず。

/bin/ls

無事にlsでき、何を打ってもcommand not foundしか返ってきないし、PATHが通っていない世界の厳しさも理解できました。


パス(PATH)の確認と設定方法は? - Pocketstudio.jp Linux Wiki

この後上のURLを見ながら、ちょくちょくlsに環境変数PATHを通したりしていました。

さて元に戻すにはどうしようか

あいにく$PATHのコピーはとっていなかったので、困ったものです。

全てのPATHを自分で通し直すにも、もともと設定してあったPATHもわかりません。


LinuxではPATHはユーザーごとに管理しています。

su user_name

でユーザーを変更すると、環境変数はもっていけません。

逆に環境変数を持って行きたいときは。

su -

と、ハイフンをつけると持っていけます。

なので、rootに切り替えてrootの環境変数をコピーしてしまえばいいか、という結論に至りました。

環境変数を無事元に戻したあたりで...

そもそもlsのソースコードはどんなん?

環境変数を通していて、そもそもlsのソースコードが気になりました。

/bin/lsをcatしても、文字化けして見れなかったで、ググるとこんな記事が。

techblog.yahoo.co.jp

yahoo!japanでは、新人にlsのソースコードを読ませるそう。

コードも短く、ぴったりだそうだ。

4月から新入社員の私は、同い年で同じことをしているのかと思うと、よし自分も読んでみようという気持ちになり、ソースコードを眺めて、そっと画面を閉じた。

また、今度にしよう、思ったより大変そうだ。

そろそろLinuxを使い始めてから、1年ほど経つのですが、私はLinuxの1%も理解していないようです。

今までpythonのプログラムを書くためだけのOSだったので、さしてLinux側をさわることもありませんでした。

しかし、サーバーを立てる等のことをしていると、自然とLinux側の知識も必要となり、今必死に勉強しています。


触り始めるとこれまた面白いもので、時間がどんどん吸い込まれていきます。

こうやって私のゴールデンウィークLinuxいじりに吸い込まれていくことでしょう。

以上、終わり。

conoha(VPS)にanacondaを利用してpython3をインストール

conoha(VPS)にanacondaを利用して、pythonの環境を整えました。

最近、ちょっとしたメモ系の記事が多いです、そして今回も。


Anacondaをローカル環境にダウンロード
Download Anaconda Now! | Continuum


2秒だけ悩んだのは、どうやってconohaにanacondaの元ソースをダウンロードするかです。

gitでcloneするか、あるいはいったんローカル環境に持って行って、ローカル環境からVPSにファイルを転送するか。

ローカル環境からVPSにファイルを転送する方を選択

scp Anaconda3-4.3.1-Linux-x86_64.sh ubuntu@157.***.***.***:/home/user

scpはリモートとローカル間でコピーするためのコマンドです。

転送が成功したので。

インストーラーを起動

bash Anaconda3-4.3.1-Linux-x86_64.sh

適当にenterとyesを繰り返すと、conohaに無事anacondaの環境が入りました。

以上、終わり。

ufwでファイアーウォールを構築

ファイアーウォールを設定する

conohaでVPSを借りたので、ファイアーウォールを設定します。

今のところガバガバセキュリティなのでよくありません。

ufwで設定

ufwは、Ubuntuのファイアーウォールを設定するためのツールです。

このコマンドでufwの状態を確認する。

#状態を確認
sudo ufw status

statusで現在開いているポートを確認できます。

このコマンドでファイアーウォールを有効化します。

#有効化
sudo ufw enable


初期設定では全てのポートを遮断します。

とりあえず全てのポートを遮断してから、開くポートだけを許可していきます。

#全てのポートを遮断
sudo ufw default DENY


httpsとhttpからの接続を許可する。

ポートを指定することもできるので、httpであればポート番号80、httpsであればポート番号443としても可。

#https接続を許可
sudo ufw allow https/tcp
sudo ufw allow http/tcp

#ポートを直接指定することも可能
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp


ssh接続も許可。

ブルートフォースアタックが怖かったら、接続にリミットをかける。

#ssh接続を許可
sudo ufw allow ssh

#limitを設定
sudo ufw limit ssh

まとめ

ufwで簡単にファイアーウォールを設定できました。

Ubuntuからconoha(VPS)にSSH接続してみる

苦労したよ

SSH接続、けっこう詰まったので自分なりにまとめておきます。

あと、conohaのサイトは案外サラッとしか書いていないので、自分なりにではありますが設定を行う理由なんかも書いて詳しめの記事にしています。

間違っていたらすみません。笑

SSH接続をする理由

conohaはサイト上からコンソールを開けるので、とても便利です。

しかし、いちいちconohaのサイトに行ってコンソールを開いて...ってやるのは面倒なので、自分のPC(クライアント)からconohaのVPSをリモート操作しましょう。

っていう導入的な部分は他のサイトにたくさん書いてあるので、さっさと本題に行きます。

まずはパスワード認証でSSH接続

SSH接続には2つの接続方法があります。

  • パスワード認証方式
  • 公開鍵認証方式

パスワード認証方式は、セキュリティの面から推奨されていません。(後に後述)

まずはパスワード認証によるSSH接続を行い、後でパスワード認証から公開鍵認証に変更します。


まずはrootでVPSにログインします。

そして、sshd_configを設定を変更します。

sshd_configにssh接続に関する設定が記述してあります。

ここで2つの設定を変更します。

vi /etc/ssh/sshd_config
  • PasswordAuthentication no → yes
  • ChallengeResponseAuthentication no → yes

この2つをnoからyesに変更します。

私の乏しい知識でこの2つの設定の意味を説明すると、パスワード認証を許可するか否かです。

PasswordAuthenticationはパスワード認証の許可、ChallengeResponseAuthenticationはパスワードを送った際にログイン成功か失敗かを示すためのものです。

基本的にサーバーは、ブルートフォースアタック(何通りものパスワードを送りつけてログインを試みる力技攻撃)を避けるためにパスワード認証は許可しません。

そのため、これら2つはデフォルトでnoになっています。

SSH接続を行うために一時的にyesにするだけなので、後でnoに変更します。

2つともnoに変更したら。

service sshd restart

sshd_configの変更を反映。


これでクライアントPCからSSH接続を試みると成功するはずです。

ssh root@157.7*******

公開鍵方式でSSH接続

VPS側のホームディレクトリにいきます。

#cdでホームディレクトリに移動
cd

このホームディレクトリに公開鍵を入れるフォルダを作ります。

たしかubuntuにはデフォルトでなかったで、私は自分で作ったのですが、すでにあれば作る必要はありません。

#公開鍵をいれるフォルダがあるかを確認
#オプション-aで隠しファイルも表示される
ls -a

そこに.sshというフォルダがなければ。

mkdir .ssh

次に、この.sshフォルダに書き込み、読み込み、実行の権限を与えます。

chmod 700 /root/.ssh/

ここで先ほどいじったsshd_configをもう一度いじり直しにいきます。

vi /etc/ssh/sshd_config

設定を変更するのは公開鍵認証を許可するためです。

#RSA鍵を許可
RSAAuthentication yes

#公開鍵認証を許可
PubkeyAuthentication yes

#公開鍵の場所をここで明示
AuthorizedKeysFile      .ssh/authorized_keys


以上の作業が終わったら、ここからクライアントPCに戻ります。

#クライアントPCの.sshフォルダに移ります
ls -a
cd .ssh

ここで秘密鍵と公開鍵を生成します。

ssh-keygen -t rsa -b 2048

ssh-keygenはSSHで利用する認証用の鍵を生成・管理・変換するコマンドです。

鍵のタイプはRSA、2048bitの鍵を生成します。

生成時にパスフレーズを要求されますが、全てデフォルトでかまわないので、全部Enterで問題ないと思います。

生成されるid_rsa秘密鍵、これは絶対にばらしちゃいけないので大切にPCに保管しておきます。

id_rsa.pubは公開鍵で、こちらをVPS側にアップロードします。

そして、公開鍵に読み書きの権限を付与します。

chmod 600 ~/.ssh/id_rsa.pub

そして、VPS側に送ります。

scp id_rsa.pub root@157.7*******:/root/.ssh/authorized_keys

scpはリモートとクライアント間でファイルをコピーするためのコマンドです。

今回はid_rsa.pubをauthorized_keysという名前に変えてVPSにコピーしています。

authorized_keysというファイル名は伝統のようです。


これで公開鍵認証方式でのSSH接続が可能になるはずです。

ssh root@157.7*******

パスワードなしで接続されれば、成功です。

逆にパスワードを要求されれば、失敗です。

root以外でのユーザーでSSH接続を行う

rootで接続を許可してしまうのは、なかなかまずいです。

もし、サーバーを乗っ取られた場合rootだと何でもできてしまうからです。

なので、SSH接続はroot以外のユーザーで行う必要があります。

VPS側でユーザーを追加し、これまでと同じ手順で公開鍵認証方式でのSSH接続を設定します。

ユーザーの追加。

#ユーザー追加
adduser user_name

#追加したユーザーがsudoコマンドを使えるようにする
gpasswd -a user_name sudo

ここまでやったら、あとはrootでの手順と同じなので省略。

ただ、公開鍵を送るときに気をつけたいのは。

scp id_rsa.pub root@157.7*******:~/.ssh/authorized_keys

ではなく、

scp id_rsa.pub root@157.7*******:/home/user_name/.ssh/authorized_keys

と、user_nameのフォルダに送ることをしっかりと記述しないといけません。

前者だとrootのほうのフォルダに送られてしまいます。

私はこのミスに気づくのにかなり時間を費やしました...笑

最後にrootでのログインとパスワード認証を禁止する

#パスワード認証の禁止
PasswordAuthentication no
ChallengeResponseAuthentication no

#rootでのログイン禁止
PermitRootLogin no

設定し終わったら、

service sshd restart

これで設定が反映されたはず。

rootでのログインはできなくなっています。

まとめ

conohaはさくらVPSより安くて良いのですが、さくらVPSと比べると情報量はどうしても劣りますね。

とくに私のようにはじめてVPSを使用する人からすると、エラーでたときにかなり困りました。

日本のサービスなので海外サイトにものっていませんし。

なので、私のようなVPS初心者のかたがconohaを使った時のためにけっこう詳しめに書きました。

(エラーがでまくったので、その都度調べるたびに勝手に詳しくなってしまった感はあるが)

誰かの助けになれば幸いですね。

以上終わり!