SyuchiNikuRingの備忘録

お勉強したことをまとめておく場所。中の人の理解や感覚で書いているから不正確なことも多いかも。

Ruby入門season1~演算記号・条件分岐・配列・キャッシュ~

やっほー。

今回はRubyのお話。

入門of入門のお話をまとめます。

標準出力はputs "(出力内容)"です。JavaでいえばSystem.out.println, C++でいえばcoutに当たるものですね。

四則演算については他の言語と同じです。

変数に関しては型を宣言する必要はなく、いきなり書いていいみたいです。驚き。

 

そして出力中に変数を入れたいときには#{変数}として出力する文字列や数値に含めてよいです。これを変数展開といいます。C++Javaでは、(文字列) + 変数 + (文字列)としてきたので、Rubyの柔軟性はいいですね。数値と文字列を出力で連結することはできないので、この記法で型が異なっても出力できるようにあらかじめ埋め込んでいると考えれば自然かもしれませんね。

条件分岐に関しては、ifで始まりendで終わります。endはこれまでの言語では出てこなかったので、忘れないようにしないとですね。条件分岐で、分岐が3つ以上あるときには、if/elsif/else/endの順で記述します。elifでもelseifでもなく、""elsif""です。スペルに気を付けましょう。

 

次に配列です。配列も配列を宣言することなく、(変数) = [値1、値2、…]のように書きます。配列中の特定値を取り出すときは、配列変数[インデックス番号]とします。変数展開も可能です。

 

C++Javaと大きく異なるのは繰り返し文です。Rubyではeach文を使います。

配列.each do |変数名| / endで書きます。このときの変数名は好きなものをつけられます。繰り返しは要素数分だけ行われます。

 

配列の次はキャッシュです。キャッシュは値を「キー」と結びつけます。表記の仕方は{キー => 値1, キー => 値2,...}です。複数種類のキーを使って値を記述すれば、代入先の変数を一気に記述できます。例えば、こんな感じ。

f:id:SyuchiNikuRing:20180907155145p:plain

 

これでsushi変数にマグロの情報を代入できました。これをputs sushiとすると、出力は「{"name" => "まぐろ", "price" => "130円", "wasabi" => "あり"}」となります。

ハッシュでは、変数[キー]とすることで特定のキーの値のみ取り出すことも可能です。そして、特定のキーに新たな値を代入することで値の更新が可能です。また、キーを新たに追加することもできます。追加する場合はキャッシュの最後尾に追加されます。

ところで毎回キーに""をつけるのはめんどくさいですよね。そこでキーの頭に「:」をつける書き方もあります。これを「シンボル」といいます。「""」「''」の代用だと今は考えてもらってOKです。正確には異なりますが、いまは気にしなくてOKです。

 

と、ここまでいろいろ書きましたが、実際には、

f:id:SyuchiNikuRing:20180907162833p:plain

と書けます。もっとも値を取得する際にはシンボルを使います。

 

キャッシュと条件分岐を組み合わせることもできます。

存在しないキーを指定するとnilとなり、条件分岐ではfalseとなります。先ほどのsushiの例からpriceをなくして動かしてみます。

f:id:SyuchiNikuRing:20180907161940p:plain

実行するとこうなります。

f:id:SyuchiNikuRing:20180907162009p:plain

うまくいきましたね。

 

キャッシュは配列に組み込むこともできます。

⁂wasaiではなくwasabiです。修正します。<2018/09/07>⁂

f:id:SyuchiNikuRing:20180907163232p:plain

実行してみます。

f:id:SyuchiNikuRing:20180907163250p:plain

130円なら食べよう...って感じで、えんがわの情報が手に入りました。

 

えんがわがさび抜きなのか否かだけを知りたいときはどうしたら良いのでしょうか。

簡単です。まずえんがわの情報が入っているキャッシュを取り出してから、キャッシュ内のインデックス番号を指定することで欲しい情報をピンポイントで取り出せます。

⁂priveではなくpriceです。修正します。<2018/09/07>⁂

f:id:SyuchiNikuRing:20180907164527p:plain

実行します。

f:id:SyuchiNikuRing:20180907164550p:plain

正しく出ました。

each文の中に入れてみました。

f:id:SyuchiNikuRing:20180907170025p:plain

実行します。

f:id:SyuchiNikuRing:20180907170051p:plain

いい感じですね。ちなみにeach文の変数(| |の中のもの)で変数展開しないとエラーになります。中の人はしばらくそれに気が付かないでエラーを吐かれ続けました。

 

今回はここまで。

Java入門season8~クラス継承~

やっほー。今回はクラス継承についてまとめます。

これなくしてJavaは語れませんね。

 

クラス継承をすれば、より抽象的なクラスを作り、そのクラスを継承してカスタマイズするというコードの書き方ができるようになります。つまり、重複を少なくできるということです。

継承されるクラスを「スーパークラス」、継承してカスタマイズしたクラスを「サブクラス」といいます。

表記の仕方は、class (サブクラス) extends (スーパークラス)です。

mainメソッド内での呼び出し方はいつもと同じです。

(クラス名) (インスタンス) = new (クラス名);

(インスタンス).set...で具体的な値をセットできます。

 

サブクラスでカスタマイズしたいときは、追加したいメソッドを書き足すだけです。

mainで呼び出すときは、(インスタンス).(メソッド)で呼び出します。

 

と、ここまで基本的なことを書きましたが、一番重要なことは「継承は一方通行」だということです。

スーパークラスからサブクラスへの継承はできても、サブクラスからスーパークラスへの継承はできません。

これを利用してメソッドのオーバーライドを行います。

先ほど、クラス継承をしてカスタマイズ可能であると書きましたが、メソッドのオーバーライドがまさにそのことです。サブクラスでスーパークラスと同名のメソッドを定義するとサブクラス側のメソッドが優先されます。上書きされるということです。そしてスーパークラスのメソッドをサブクラス側で呼び出す場合には、super.メソッド()とします。これでスーパークラス側のメソッドをサブクラス側で呼び出せます。

コンストラクタに関してですが、サブクラスでコンストラクタを定義するときは、まず先頭でスーパークラスのコンストラクタを呼び出さなければならないというルールがあります。super()で呼び出せます。

定義の手順についてですが、スーパークラスでコンストラクタを定義します。次にサブクラス内でコンストラクタを定義します。そしてそのコンストラクタ内でsuper(仮引数)とします。この仮引数がスーパークラスのコンストラクタの仮引数に引き渡されます。

 

クラス継承で問題になるのはフィールドのアクセス制限です。なんでもかんでもset/getを使うのではなく、protectedを使い手もあります。protectedはクラス内とサブクラスからのみアクセスが許されるものです。privateだとそのクラス内のみアクセス可能でありサブクラスからのアクセスができません。だからといって何でもかんでもpublicを使うのも考えものです。カプセル化の意味もなくなってしまうからです。

 

クラス継承では各クラスの最大公約数的なメソッドを新たにスーパークラスとして定義し、各クラスはそのスーパークラスを継承して必要に応じてカスタマイズします。ここまではスーパークラス内にあるメソッドは全て具体的な処理内容を伴っていました。しかし、実際にはメソッドは同じでもその処理内容は異なる場合も考えられます。例えば、movementというメソッドがあっても、人間と魚、蛇ではその中身は異なります。

このとき、中身が異なるからといって全てのクラスにmovementというメソッドを書くのは重複になり保守性の低下につながります。そこで、処理内容は書かずにメソッドだけスーパークラスに定義しておく手段が欲しくなります。ここで登場するのが抽象メソッドabstractです。publicの前に書きます。一つでも抽象メソッドがあるクラスは抽象クラスといい、クラス名の前にabstractを付けます。abstractはオーバーライドを強制します。上書きされなければエラーになります。また、抽象クラスからはインスタンスを生成することはできません。

 

今回はここまで。

 

 

マルウェアの種類のお話。

やっほー。以前のエントリで簡単に攻撃の種類が云々と書いた気がしますが、こちらで改めてまとめます。主に攻撃に用いられるもののお話ですかね。

 

syuchinikuring.hatenablog.com

 

以前のエントリではざっくりofざっくりとしかまとめておかなかったので、今回はその補充を。というか、こちらがまとめで以前の分がその補充というべきなんですけどね。まあいいやその辺は。

 

ではさっそくいってみよー。

 

★そもそも…マルウェアって何?

よく聞く言葉ではありますが、マルウェアと聞いて何かをすぐに答えられる人は少ないと思います。ぱっと浮かぶのは「ランサムウェア」ですかね。

マルウェアとは、データをパクったり改ざんしたりコンピュータを乗っ取ったり…といった悪意あるコードの総称です。要はクソ迷惑なコードのこと。

有名なものは次のようなものがあります。

・ボット

ランサムウェア

・ウイルス

トロイの木馬

・ワーム

スパイウェア

アドウェア

・スケアウェア

ルートキット

・中間者

 

1.ボット

オンライン上で自動的に動くことを目的に作られています。ボットのほとんどは無害です。Twitterでよく見る自動投稿アカウントは○○botなんて名前の人気コンテンツに関連したものが多いですよね。しかし、ボットネットという悪意のあるものや一見無害そうでも攻撃者の命令があれば動き出すようにプログラムされたボットもあります。

 

2.ランサムウェア

有名なマルウェア。感染するとユーザのデータなどを暗号化して見られないようし、身代金を要求してくるマルウェア。基本的にはユーザの知らないキーを用いて暗号化しますが、中にはシステムの脆弱性につけこんでデータを暗号化してくるものもあります。ファイルのDLやシステムの脆弱性などから感染する可能性があります。

 

3.ウイルス

これもよく聞くものですね。ウイルスは他の実行ファイル内に含まれる悪意あるコードで、基本的にはユーザの何らかのアクションを必要とします。メールやUSBなどを通じて拡散されています。

 

4.トロイの木馬

これも有名ですね。音楽のファイルやゲームなど実行ファイルなどにも含まれ、正当な操作を装い、悪意あるコードを実行します。

 

5.ワーム

一番の特徴は、自ら増殖できるということでしょうか。ネットワークの脆弱性につけこんで増殖し単独で活動します。拡散する速度も極めて速いです。

 

6.スパイウェア

名前からして既に悪いですね。名前の通り、ユーザをスパイします。つまり、ユーザのコンピュータの利用状況やキーストロークの収集を行い、セキュリティ設定の変更を行います。セキュリティ設定を変更してそのレベルを下げるので、トロイの木馬など他のマルウェアとセットになっていることがあります。スパイウェアでセキュリティをガバガバにしたのちトロイの木馬などのマルウェアで好き放題やるという流れですね。

 

7.アドウェア

「アド」は広告のadvertisementのadです。広告配信を行いつつどさくさ紛れにスパイウェアなどを入れてくるマルウェアです。

 

8.スケアウェア

ポップアップウィンドウからセキュリティ上の問題を伝える(ふりをする)など、危機感につけこんでくるマルウェアです。このポップアップウィンドウに従ってプログラムを実行するとマルウェアに感染します。

 

9.ルートキット

OSを弄ってくるマルウェア。攻撃者のためにバックドアを設置するので、攻撃者はこれ以降好き放題コンピュータにアクセスできるようになります。権限の昇格などの変更とシステムファイルの変更を行うなど、深刻な問題を引き起こしかねないマルウェアです。

 

10.中間者

暗号の話をやったことがあれば中間者攻撃(Man-in-the-middle)などを聞いたことがあるかもしれません。それと同じような話で、攻撃者はユーザの情報を受信できるようになります。Mitによりユーザに知られることなくデバイスを操作でき、財務情報を盗聴するために広く使われています。MitMoは攻撃者にユーザの情報を送信させ、SMSなどの2段階認証ですら潜り抜けられます。

 

今回はここまで。

2要素認証の話。

やっほー。今回は2要素認証の話ですよ。

最近多くなってきましたよね。2FA。

 

サイトが2FA使っているのか確認したい人はここで確認するといいですよ。

 

twofactorauth.org

 

物理的な認証ではいわゆるパスワードなどを要求されます。そしてここをクリアしてから生体認証に移行します。指紋とか静脈とかを用いた認証ですね。

以前にお邪魔した企業のセキュリティ部門の入り口は生体認証を要求する2FA方式だそうです。さすがセキュリティ部門って感じです。

 

今回はこれだけ。備忘録だもん。

パスワードの話。

やっほー。昨日の台風の影響で我が家のルータは使用不可になりネット難民と化していました。そんなことは置いておいて、今回はパスワードのお話を。

オンライン上で新しく何を始めようとする際には避けては通れなくなっているパスワード設定。複雑なものにすべきだの長いものにすべきだの言われていますし、設定時にそのように求められます。そして使いまわしはやめろとも…

 

正直覚えられない‼

 

今回は安全なパスワードの要件と作り方、そしていくつかのツールもご紹介します。

 

まずは、安全なパスワードの要件から。4つあります。

1.ユーザ自身にとって覚えやすい

2.他人からは推測困難

3.プログラムで探索するのが困難(辞書的に探索するのが困難)

4.大文字小文字が含まれ、かつアルファベット以外の記号が含まれている

 

1と2はこれまでのパスワードの設定時の思考回路だと相反しているように思えるかもしれません。しかし、大丈夫なんです、1と2は両立可能なのです。

 

パス「ワード」だと単純化しがちですが、パス「フレーズ」ではどうでしょうか。これなら長くなっても覚えられるのではないでしょうか。フレーズの際には4語以上が良いとされています。単語の頭文字を大文字にするとかしてパターンも増やせます。

 

しかし、「そもそもパスワード/パスフレーズ」なんて浮かんでこない、という方がいるでしょう。そんな方にはこちらのツールをご紹介します。

まずは一つ目、ランダムなパスワードを作ってくれるツールです。

passwordsgenerator.net

こんな感じ。

f:id:SyuchiNikuRing:20180905233414p:plain

"Generate Password"をクリックすると"Your New Password"にパスワードが自動で生成されます。しかし、ランダムな文字列になるので覚えるのは難しいですね…

 

そこでもう一つがこちら。なんとランダムな4つの単語を出してくれるんです。覚えにくいなと感じたら何度も生成をしてくれます。

 

preshing.com

 

こんな感じ。

f:id:SyuchiNikuRing:20180905233659p:plain

"Generate Another!"をクリックすると満足いくまでパスフレーズを生成してくれます。

 

しかし、こんな声も聞こえてきそうです。「いくつも作っていたらそのうち忘れる。」

 

…その通りですね。そんな方にはこちら。パスワードマネージャです。

自分の代わりにパスを覚えておいてくれます。マスタのパスワードさえ覚えておけばOKなのでパスがいくつになろうが安心ですね!

http://htps://www.lastpass.com/

 

今回はここまで。パスの設定と管理だけはきちんとやりましょう。

TextCounterの中身に関して

やっほー。前回のエントリで渡されたテキストファイルの行数・文字数・単語数・各アルファベットの出現回数を返すプログラムを作ったと書きました。

その中身ですが、基本的にjava.io.*のインポートによりライブラリにあるクラスをフル活用する感じです。

行数はreadLine()をwhile(line != null)内でゴリゴリ回します。whileの終了条件line = nullを判定するためにwhile内で次の行を読み込み更新します。

これで行数のカウントは終わり。

次に文字数ですが、これもいまの考え方をそのまま使えます。

各行の長さを.length()で取得し合計したものが文字数になります。したがって、前半の2つのメソッドはほとんど同じです。

次に各アルファベットの出現回数に関してです。大文字と小文字の区別は取得した文字をtoUpperCaseに放り込んでからfor(int i = 60; i <= 90; i++)のループで一文字ずつ判定していけばよいです。i = 60はAのASCⅡ上のコードを表します。

詳しくはこちらを。

ASCIIコード表 - Javaちょこっとリファレンス

行を読み込むreadLine()や文字を読み込むread()はintを要求するので、(char c == 'A'; c <= 'Z'; c++)は使えないのです。

詳しくはこちら。

InputStream (Java Platform SE 6)

問題は単語数です。スペースでsplitする方法ではうまくいかないことがあったので、別の方法を考えました。うまくいきませんでしたが…

スペースでsplitする方法以外で考えたのは、スペースを区切り文字としダブるスペースの場合にはカウントしない方法で、連続したスペースをカウントの際に排除できる(はずの)ものでした。こんな感じのものです。実際のコードは持ち出せないので記憶を基に再現しました。まずは前半。こちらに件の処理が含まれています。スクショ内で説明を完結させようとコメントをぶち込みまくりましたが、これはお行儀が悪いのでやめましょう。

f:id:SyuchiNikuRing:20180831224239p:plain

何をしているのかを順に説明します。

17行目でこのメソッドの戻り値を定義し初期化しています。

23行目と24行目ではread()を用いてテキストファイル内の文字を先頭から一文字ずつ読み込む準備をしています。問題はここからです。二つの真偽値isNotSpace_1, isNotSpace_2は各文字に対して文字であればtrueに、スペース又は改行記号であればfalseになります。そして、isNotSpace_1はi+1番目の文字、isNotSpace_2はi番目の文字の状態true/falseに対応しています。具体例をあげると、

apple[ ]banana[ ]chocolate[\n]

delicious[ ][ ]east[ ]fruits[\n]   ([ ]はスペースを、[\n]は改行記号を明示的に表現)

というテキストがあるとします。先頭からread()を使って読み込むと、最初は、appleのaとなります。この時、isNotSpace_1 = trueとします。そうすると、真偽値は、isNotSpace_2 = false, isNotSpace_1 = trueとなります。次の文字を同じように読み込むと、apppleのpなので、isNotSpace_1から値を受け取ってisNotSpace_2 = trueに、isNotSpace_1 = trueとなります。これを繰り返すとappleのeを読み込んだ時にisNotSpace_1 = true, isNotSpace_2 = trueになります。次の文字は[ ]なのでisNotSpace_1 = falseとなります。コードでは36行目のelse節に入り、if節によりwordNumberCountでカウントされます(というかされるはずだった)。とまあ、こんな感じで処理を繰り返していきます。

 

正直、40行目の条件が正しいと思えない。内容的にも位置的にも。

 

そして後半。

f:id:SyuchiNikuRing:20180831230518p:plain

実際に動かしてみるとelse節に入るものの明らかに大きい値を返されてしまい、途方に暮れてしまいました。

 

実際の単語数のカウントってどういうアルゴリズムで動いているのか…

 

インターーーーーーーーーン‼︎まとめpart7

やっほー。先週に続いて1週間ほどインターンに行っておりました。

何していたのかというのはここ最近のエントリから大方想像がつくと思います。

そうです。Javaの基礎を勉強しておりました。細かいことはこれから徒然なるままに書いていきます。

 

ではレッツゴー。

 

インターン先はとあるベンチャーで開発メインの企業です。なんと参加者4人。

この企業,言い方は失礼ですが,オフィスは雑居ビルの2フロアのみで各フロアともとても狭い。ホームページが綺麗だった分ちょっとがっかり。

しかし,取引先には先週までお世話になった企業をはじめ日本有数の大企業が並んでおりました(まあ誰も知らない企業なんか載せないわな)。業務形態としては,プロジェクト参画によりチームで客先に常駐しての開発がメインです。こんな感じで普段は本社オフィスに人がそんなに多くないので,小さくても大丈夫なようです。開発実績の領域はかなり幅広い感じでした。会社の説明をしてくれた採用担当者も普段は客先常駐エンジニアで,常駐型SEのつらいところを語ってくれましたが,割と生々しかったのが印象的でした。

 

それでは1週間何をしていたのかをみていきましょう。

ざっくりいうと冒頭にもあった通り,Java の基礎を勉強していました。

初日に演習問題を渡され,それを順に解いていき(コードを書く),社員にレビューしてもらうということを3日目までやっておりました。雰囲気的には競プロ的な問題を解く感じですかね。この間にちょこちょことアジャイル開発(という名のドミノ倒し)を体験したり会社説明をしてもらうなどのミニイベントもありました。

一通り基礎をやったので4日目からは4人で一つのプログラムを作り出したのですが,何と時間は4日目と5日目だけ。ブラックか。

 

何を作ったのかというと,カレンダーとTextCounterです。

カレンダーは,年月日の順に入力を受け取り,それらをサーバ側に渡してクライアント側には曜日を返すというもの。4年に一度の閏年を考慮してねという条件付き。割とよくありそうな感じ。そして,年月日の入力を受け取った際にその都度不正な値(ex. -2018年,13月,32日など)か否かをチェックし,全てでtrueとなった場合に曜日を計算して返すというメソッドを実装しました。この課題は4人それぞれで1つのクラスを分担して作ることにし,中の人はクライアント側のクラスを担当しました。サーバからの年月日の入力要求のメッセージを受信してコンソールに表示し、コンソールからの標準入力をサーバ側に送信、曜日の計算をしたサーバからの返事をコンソールに表示するというものです。

やる前は,まあ1人でもすぐに作れそうな感じだし割と簡単めかな?とか思っていました。(ググればサーバとの通信を確立させるコード出るし)

しかし,4人で作るとなると話は別でした…

認識のすり合わせを行わないといけないし,定期的に全員の進捗を把握しないといけません。正直めんどくさい。1人なら全く気にしないことも複数だと気にしないといけない。変数の名前も気を付けなければならないのです。競プロとの違いが大きい…

大規模プロジェクトでは当然の作業も慣れない4人だとなかなか効率が悪いです。

設計仕様書の段階で既に認識がズレているなんてこともザラに起こりました。まずはそこの擦り合わせと共有からスタート。

そんなこんなでコーディングを進めていったのですが,なんと1日で無事終了。

ちゃんと動いてくれました。途中でクライアントとサーバの接続がうまくいかないトラブルがありましたが,20分ほどで原因を特定し改修。参照資料のコードをゴリゴリ真似したものの,ちゃんと動いてよかったです。

 

次にTextCounterを作りました。どんな機能が実装されているのかというと,渡されたファイル内のコンテンツに対して,

・文字数チェック

・単語数チェック

・行数チェック

・各文字の出現頻度チェック

の四つを行います。私はもう1人と一緒にこれら四つの機能を実装していきました。(流石に1日ではキツくない?とか思いつつ…)

 順調に進んでいたのですが、単語数カウンタが正しく動かないバグが発生し、ついに直せずインターンは終わってしまいました…

 

Javaはあらゆるところで使われているので,今回勉強するきっかけができて良かったですというのが今回の感想。もう少し付け加えると,Javaはかなり自由度の高い言語なので,書いているうちにだんだん楽しくなってきます。今回の基礎演習を踏まえてJavaの勉強も続けたいですね。