技術とか戦略とか

SIerで証券レガシーシステムを8年いじってからSESに転職した普通の文系SEによる技術ブログ。

情報処理技術者試験対策「共通鍵暗号方式・公開鍵暗号方式とSSL」

この記事では、暗号化が必要な理由や共通鍵暗号方式・公開鍵暗号方式の概要、SSLの仕組みの概要について書きます。
 
1.暗号化が必要な理由
ノード(端末やサーバ等、他の機器との通信を行う主体を指す)間の通信内容は、Wiresharkのようなパケットキャプチャ(ソフトウェア)で確認することが可能です。
どのような形で確認できるのかは、Googleの画像検索(https://www.google.com/search?q=Wireshark&sxsrf=ALeKk02z0RxYtT7G0O_rVmDxd3LoryWp4g:1615711689095&source=lnms&tbm=isch&biw=1366&bih=657)で調べればイメージがわきやすいと思います。
 
そして、ユーザ/パスワードのような重要な情報を送受信する際も、同じようにパケットキャプチャで通信内容を見ることができてしまいます。
もし、そのような重要な情報が平文(生データ)で送受信されていたとしたら、それはセキュリティ面で重大なリスクとなります。
例えば、ユーザ/パスワードを盗み見た第三者が、なりすましでログインすることができてしまいます。
 
それを防ぐために、「鍵」と呼ばれる通信を行う者同士であらかじめ共有されたデータを使用し、特定のアルゴリズムにより通信するデータを暗号文に変換します。
そうすることで、第三者に通信内容を盗み見られたとしてもその中から重要な情報を取得されるのを防ぐことができます。
「鍵」を持たない第三者が暗号文を見ても内容を理解できない、という所が重要です。
 
2.共通鍵暗号方式・公開鍵暗号方式の仕組み
暗号化の方式は大きく分けて二つあり、「共通鍵暗号方式」と「公開鍵暗号方式」があります。
 
2.1.共通鍵暗号方式
これは、あらかじめ2者間で共有された共通鍵を使用する方式です。
図解すると以下のようになります。

f:id:akira2kun:20210501003619j:plain
 
この方式は、方式が単純であることから暗号化・復号を早く行うことができるのが利点ですが、多くの鍵を用意する必要がでてきてしまう欠点があります。
上記の図の通りなのですが、2者の組み合わせ毎に鍵を用意する必要が出てきてしまうため、n(n-1)/2の分だけ鍵が必要になってしまいます。
(各々のノード(n)は、他の各々のノード(*(n-1))に対して鍵を用意する必要がある。ただし、2者間で別々の鍵を用意する必要はない(/2)。)
 
2.2.公開鍵暗号方式
これは、それぞれの主体が秘密鍵と共有鍵を管理し、通信を行う時に通信相手に共有鍵を渡して通信を行う方式です。
図解すると以下のようになります。

f:id:akira2kun:20210501003636j:plain
 
この方式は、少ない鍵で通信を行うことができる利点がありますが、方式が難しく暗号化・復号を早く行うことができません。
必要な鍵の数は、それぞれの主体が秘密鍵と共有鍵の2つの鍵さえ持っていれば良いので、必要なのは2nの分のみです。
 
3.SSLについて
インターネット上で通信を安全に行う仕組みとして、SSLと呼ばれる仕組みがあります。
SSLは、インターネットプロトコルであるhttpsにも使われています。
(重要な情報を送受信する時にはhttpsを使うべきであると言われたことがあると思いますが、httpsが安全な理由はSSLを使っているからです)
 
SSLでは、先で説明した共通鍵暗号方式と公開鍵暗号方式を利用しています。
また、サーバ証明書を利用するのも特徴です。
サーバ証明書とは、認証局(サーバの正当性を証明する第三者の企業)からサーバに対して付与されるものであり、通信を行うサーバが正当なものである(犯罪等に悪用されることがない)ことを証明するデータです。
仕組みは以下の通りです。

f:id:akira2kun:20210501003653j:plain
 
----------------------
 
情報処理技術者試験に関する記事の目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

情報処理技術者試験対策「排他制御・デッドロック」

この記事では、情報処理技術者試験で問われる排他制御デッドロックについて、基礎的なことを書いていきます。
 
排他制御デッドロックを理解する前に、トランザクションについて理解する必要があります。
トランザクションとは、複数の処理をひとまとまりにしたものです。
例えば、出庫時に在庫数を更新するトランザクションは、下記の処理をひとまとまりにすることで実現できます。
・在庫テーブルから在庫量を取得する
・取得した在庫量から出庫した分を差し引く
・差し引いた在庫量を在庫テーブルに反映させる
 
このトランザクションを実行する上で注意が必要なのは、トランザクション実行中に在庫テーブルが更新されないことを保証する必要があることです。
もし、在庫量を取得した後に在庫テーブルが更新されてしまった場合、トランザクションで算出した在庫量でその更新を上書きしてしまいます。
それを防ぐために、トランザクション中で在庫テーブルにロック(排他制御)をかけ、トランザクション実行中に在庫テーブルが更新されないようにします。

f:id:akira2kun:20210501002637j:plain

 
このように更新結果の不整合を防げるのがロックなのですが、デメリットもあります。
複数のトランザクションがロックをかけた場合、複数のトランザクションがお互いにロック待ちの状態となり、トランザクションを終了できないのでロックを解除することもできず、(強制的にトランザクションを終了させるまでの間)永久にトランザクションが終了しなくなることがあります。
このような現象を、デッドロックと呼びます。

f:id:akira2kun:20210501002707j:plain
 
デッドロックを防ぐための代表的な手段として、トランザクションの間でロックする順番を統一するという手段があります。
この手段を用いることで、他のトランザクションが中途半端に進んで中途半端にロックをかけることがなくなるので、デッドロックを防ぐことができるようになります。

f:id:akira2kun:20210501002723j:plain
 
----------------------
 
情報処理技術者試験に関する記事の目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

情報処理技術者試験対策「VR・AR」

最近の情報処理技術者試験では、VRとARの違いを知らないと答えられない問題が出題されることがあります。
 
詳しい知名度は以下の通りなのですが、VRという用語に比べて、ARという用語は比較的知名度が低いです。
 
VR認知度は87.6%、ARは34%。『VRビジネス調査報告書2018』が発売 - VR Watch
https://www.watch.impress.co.jp/vr/articles/news/20180124_vrbusiness.html
 
情報処理技術者の試験勉強でARという用語を始めて知ったという方も少なくないかもしれません。
また、このテーマは10年ほど前の情報処理技術者試験では問われなかったテーマなので、昔に受験してそれっきりの方は今でも知らないかもしれません。
 
簡単に言うと、VRとはゴーグル等の機器を装着して仮想現実の中での疑似体験を提供するシステム、ARとは現実世界の中に情報を付与するシステム、という違いがあります。
イメージしやすい例を挙げると、「Pokémon GO」はARです。鳥取砂丘に出向き、スマートフォンのカメラで映し出した砂丘の中にレアポケモンを出現させて、スマートフォン上のスワイプ操作で捕まえる。これがイメージできれば、ARの言葉の意味は一発で覚えられると思います。
 
レガシーなシステムを昔から保守している技術者にとっては関係の無い話に思えるかもしれませんが、レガシーシステムが提供するAPIを通して最新鋭のシステムと連携する、という例は少なくなりません。
将来的にVRやARと連携することもあるかもしれませんので、システムの提案や社外との打ち合わせに備えて、言葉の意味だけでも覚えておいて損はないと思います。
 
----------------------
 
なお、2021年時点では情報処理技術者の出題範囲外だと思いますが、VRやARの他にMRという用語もあるので、こちらも覚えておくと良いでしょう。
MRは、VRとARを組み合わせたようなものです。
現実世界の上に情報が付加されているARとは異なり、VRと同じように機器を通して視覚や触覚による体験を行うことができます。
また、全くの仮想世界での体験となるVRとは異なり、ARと同じように現実世界をベースとした体験となります。
 
----------------------
 
情報処理技術者試験に関する記事の目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

情報処理技術者試験対策「静的解析ツール・動的解析ツール」

情報処理技術者試験では、「静的解析ツールとは何か」「動的解析ツールとは何か」を問う問題が出題されます。
この記事では、これらのツールは何か、何のために使うのか、といったことについて簡単に書いていきます。
 
【静的解析ツールの説明】
静的解析ツールとは、実行しない状態でソースコードのチェックを行うツールです。
コンパイル前に、コンパイルエラーや実行時エラーとなる箇所、若しくはエラーになる可能性が高かったり可読性が低下したりする箇所を見つけ、警告を出してくれます。
エラーや可読性低下につながる箇所を最速のタイミングで見つけることができ、また人間によるソースコードレビューと異なり見落としが出ることもないので、静的解析ツールを適切に使うことで品質が向上しやすくなります。
 
EclipseJavaソースコードを書く時に、未使用のインポートや変数が存在する時に黄色の波線が出た経験はないでしょうか?
静的解析ツールは、その機能をよりリッチにしたものと考えて良いです。
Eclipse自体も静的解析ツールの機能を含んでいると考えて良いと思っています)
Javaの場合、「FindBugs」や「SonarQube」といったツールが代表的な静的解析ツールとして挙げられます。
 
【動的解析ツールの説明】
動的解析ツールとは、実行時にプログラムの実行状態を解析するツールです。
変数の内部状態の表示や、プログラムの呼び出し回数・実行時間の計測、プログラムの命令や分岐の網羅率の計測、アサーションチェック(変数状態等が期待結果と一致していることの確認)等を行います。
単純に実行結果を見るだけでは分からない情報を見ることができるので、バグの調査やテストの実施状況確認、テストの実行結果の確認といった作業を効率良く行うことができるようになります。
 
Eclipseデバッグ機能を使うと、各ステップ毎で変数の内部状態の変化を見ることができます。
Eclipseがサポートするこの機能も、動的解析ツールと呼べるものです。
 
----------------------
 
目次
https://1drv.ms/b/s!AivF3bzWXOzuhG1Xk5hscKYqkLkM

Base64の説明とjavaでのエンコード・デコードの例

Base64とは、テキストデータやバイナリデータ(画像ファイル、PDFファイル等)を表現する方式の一つです。
以下の64種類の文字と末尾のパディング文字(=)を用いて表現するのが特徴です。
・アルファベット(a~z, A~Z)
・数字(0~9)
・一部の記号(+, /)
 
この表現方式は、一部の文字しか使用できないプロトコルでデータの送受信を行いたい場合に有用であり、ASCII文字しか送受信できないプロトコルでもデータの送受信が可能になります。
有名な所で言うと、電子メール(SMTP)でBase64が使われています。
また、APIでのデータ送受信でも良く使われます。
 
ここで、Base64エンコード・デコードをイメージしやすくするため、2バイト文字(日本語)を Java8 の java.util.Base64https://docs.oracle.com/javase/jp/8/docs/api/java/util/Base64.html)を用いてエンコード・デコードしてみます。
 
【サンプルコード】
・Base64Test.java
import java.util.Base64;

public class Base64Test {

  public static void main(String[] args) {

    // 元の文字列(2バイト文字)
    final String orgStr = "こんにちは!";

    // Base64へのエンコード
    String encodedStr =
      Base64.getEncoder().encodeToString(orgStr.getBytes());

    // Base64からのデコード
    String decodedStr =
      new String(Base64.getDecoder().decode(encodedStr));

    System.out.println("元の文字列      : " + orgStr);
    System.out.println("Base64へのエンコード : " + encodedStr);
    System.out.println("Base64からのデコード : " + decodedStr);

  }

}
 
【実行結果】
元の文字列      : こんにちは!
Base64へのエンコード : 44GT44KT44Gr44Gh44Gv77yB
Base64からのデコード : こんにちは!
 
----
 
なお、今回の記事では触れませんが、バイナリファイルを1バイトずつエンコード・デコードすることで、バイナリデータにも対応できます。
また、Base64エンコード・デコードの方式は公開されており、人気の言語ではライブラリも存在しているので、他の言語でも実装可能です。

Vue.jsに出てくるコロン(v-bind)とアットマーク(v-on)について

Vue.jsのコードに時折コロン(:)やアットマーク(@)が出てきて戸惑う人がいるかもしれませんが、これは省略記法です。
それぞれ、v-bind、v-onを指しています。
 
Vueオブジェクトの変数や関数をHTML側から参照するために、v-bindやv-onを使用します。
 
以下、サンプルコードです。
 
【サンプルコード(v-bind)】
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
 <title>Vue.js - Hello world!</title>
</head>
<body>

<div id="app">
 <!-- 属性では{{ }}構文は使用できない。代わりにv-bindを使用する -->
 <input type="text" v-bind:value="message1"><br>
 <!-- 省略記法 -->
 <input type="text" :value="message2">
</div>

<script src="https://unpkg.com/vue"></script>
<script>
 var app = new Vue({
  // elで指定した値はdivタグのidと対応
  el: '#app',
  // 変数の初期値定義
  data: {
   message1: 'Hello World 1!',
   message2: 'Hello World 2!'
  }
 })
</script>
</body>
</html>
 
【実行結果(v-bind)】
以下のように、Vueオブジェクトの変数の値とHTMLを結びつけることができます。

f:id:akira2kun:20210307200811j:plain

 

 
【サンプルコード(v-on)】
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
 <title>Vue.js - Hello world!</title>
</head>
<body>

<div id="app">
 <!-- v-onによりボタン押下時のベントハンドラ実行が可能になる -->
 <button v-on:click="btnClicked">ボタン1</button><br>
 <!-- 省略記法 -->
 <button @click="btnClicked">ボタン2</button>
</div>

<script src="https://unpkg.com/vue"></script>
<script>
 var app = new Vue({
  // elで指定した値はdivタグのidと対応
  el: '#app',
  // 変数の初期値定義
  data: {
   message: 'Hello World!'
  },
  // 関数定義
  methods: {
   btnClicked(){
    alert(this.message);
   }
  }
 })
</script>
</body>
</html>
 
【実行結果(v-on)】
以下のように、Vueオブジェクトの関数を呼び出すことができます。
これは、ボタン1とボタン2の両方で同じ動きになります。

f:id:akira2kun:20210307200826j:plain



JavaScriptのasync・awaitのサンプルコード

JavaScriptでは、通常は非同期処理となり、重い関数が終わるまで待つということをせず、次の関数に先に制御が移ってしまいます。
そのため、API呼び出しやIO(ファイルの読み書きやDBの読み書き)を伴う関数を呼び出した後に、その結果を元に次の処理を行う、というフローを行うためには一工夫必要です。
 
これを簡単に書くために、JavaScriptにはasync/awaitという文法が用意されています。
この記事では、非同期処理のサンプルコードと、async/awaitを用いて同期処理にするサンプルコードを用意しているので、そのサンプルコードを読めば使い方は理解できると思います。
 
async/awaitを使う上での注意点として、promiseやresolveとセットで使う必要があるという点があります。
これをセットで使用しないと、同期処理にならない、待った後の処理が実行できない、等のバグになります。
async/awaitはpromiseオブジェクトを簡単に扱うための文法でもあるので、promiseについては別途Webで調べるとより理解が深まると思います。
 
【サンプルコード(非同期処理)】
// すぐ終わる処理
function lightTask() {
 console.log("light");
}

// 1秒かかる重い処理
function heavyTask() {
 const procedure = () => {
  console.log("heavy");
 }
 setTimeout(procedure, 1000);
}

// JavaScriptは通常は非同期なので、heavyTaskの終了を待ってくれない
function exection() {
 heavyTask();
 lightTask();
}

exection();
 
【処理結果(非同期処理)】
C:\tmp>node sample.js
light
heavy

C:\tmp>
 
【サンプルコード(同期処理)】
function lightTask() {
 console.log("light");
}

function heavyTask() {
 // awaitで呼び出される関数ではpromiseオブジェクトを返す必要がある
 return new Promise((resolve, reject) => {
  const procedure = () => {
   console.log("heavy");
   resolve(0); // returnではなくresolveで戻す(これを忘れると制御が戻らない)
  }
  setTimeout(procedure, 1000);
 });
}

// awaitを使用する関数にはasyncをつける
async function exection() {
 let result = await heavyTask(); // awaitで呼び出すことで処理が終わるまで待つ
 // console.log(result); // 0
 lightTask();
}

exection();
 
【処理結果(同期処理)】
C:\tmp>node sample.js
heavy
light

C:\tmp>