ストレージの暗号化

ストレージ暗号化とは、ストレージ内部のデータを暗号化することで、正しい鍵を持っているユーザ以外はデータを利用できないようにする仕組みのこと
ストレージを暗号化しておくことで、不正アクセスの被害にあった際や、ストレージを盗聴されたり紛失したりした際の情報漏洩を防ぐことができる 
ただし、鍵の情報が漏洩すると暗号化しても情報が漏洩してしまう。また、マルウェア感染などの脅威は防げない

1. 暗号化ソフトを利用する
ESET Endpoint Encryption: 有名なESETの暗号化ソフト
NonCopy2: 純国産ソフトウェア
セキュリティ・ウェアハウス: windowsと似た操作感で使いやすさが魅力の暗号化ソフト

2. 標準搭載機能を使う
Windows10Proなどに標準機能として入っているBitLockerが有名

3. 暗号化機能のあるストレージを使う
クラウドストレージでも暗号化機能を備えたサービスは多い

また、ストレージの暗号化だけでなく、マルウェア対策、多要素認証、バックアップなどの対策も大切

メールの暗号化

## メールの暗号化とは?
メールの本文や添付ファイルを暗号化して第三者によってメールにアクセスされないようにすること
暗号化ソフトを導入すれば、通常通りメールの送受信をするだけで自動的に暗号化されて第三者による盗聴や改ざんを防ぐ
メールの暗号化には公開鍵暗号方式と秘密鍵暗号方式の2つがある

## 公開鍵暗号方式
公開鍵暗号方式は「公開鍵」「秘密鍵」と呼ばれる2つの鍵を利用してデータのやり取りを行う方法
1. 秘密鍵を使って公開鍵を作成
2. メール相手に公開鍵を送付
3. 公開鍵を受け取った側が公開鍵を使ってメールを暗号化
4. 暗号化されたメールを受信し、公開鍵を作るときに使った秘密鍵で複合する

## 秘密鍵暗号方式
秘密鍵暗号方式は共通鍵のみでデータを暗号化・複合する

## メール暗号化方法の種類
メールの暗号化には次の2つのプロトコル(通信手順)が用いられる
– PGP・S/MIME: メールの暗号化、電子署名に使われている
– SSL・TLS: インターネット上でやり取りされる通信を暗号化する技術。SSL/TLSを使うには第三者機関が発行するサーバ証明という電子証明書が必要

### Gmailでの確認方法
Gmailでは暗号化されていないメールサーバを経由して送られてきたメールをやり取りした時に、暗号化されていないことを示すマークが表示される

### Outlookでの確認方法
Outlookでも設定を確認することができる

Basic認証の脆弱性

Basic認証では.htaccess, .htpasswdという2つのヘッダが働いている。
サーバの認証をかけたいフォルダに.htaccess, .htpasswdというファイルを作成するだけ

## Basic認証のデメリット
– サーバを跨いだ認証設定ができない
– クローラが巡回できないため、SEO対策ができない
– セキュリティレベルが高いとは言えない

## Basic認証の脆弱性
– 脆弱性が指摘される理由として、「文字コードの種類」「httpであること」が挙げられる
– Basic認証ではログイン情報を入力する際に「Base64」を平文でやり取りする 「http」通信のため、盗聴されやすい
– 公開直前の確認用Webページ、特定のメンバーとのみ共有する場合、無料サイトなどは簡易的な認証で問題ない。個人情報は含めてはいけない
– Basic認証はクローラが巡回しない

Basic認証はブラウザにID、パスワードを保存する。Base64でエンコードされているが、デコードすれば簡単に確認できる
また、ログアウト機能がない

APIの暗号化

ほとんどのAPIはREST(Representational State Transfer)またはSOAP(Simple Object Access Protocol)で実装されている
REST APIはTLS暗号化(HTTPS)をサポートする。そのため、データを読み取ることも変更することもできない
REST APIはJSONも使用する。SOAP APIよりも高速

SOAPはXML暗号化、XML署名、SAMLトークンを組み合わせて使用する

### APIセキュリティ強化の例
– トークンを使用する
– 暗号化と署名を使用する
– 脆弱性を特定する
– クオータとスロットリングを使用する
– APIゲートウェイを使用する

### API管理とセキュリティ
– APIキー
– 基本認証
– OpenID Connect

MySQLで暗号化、復号化

* AES_ENCRYPT()/ AES_DECRYPT()などの暗号化関数を使用する

CREATE TABLE IF NOT EXISTS `user` (
	`user_id` VARCHAR(100) NOT NULL,
	`password` VARBINARY(200) NOT NULL,
	PRIMARY KEY (`user_id`)
)
COMMENT='ユーザ'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=11;

INSERT INTO `user`(`user_id`,`password`) VALUES(`user1`,AES_ENCRYPT(`password1`,`ENCRYPT-KEY`));
INSERT INTO `user`(`user_id`,`password`) VALUES(`user2`,AES_ENCRYPT(`password2`,`ENCRYPT-KEY`));
INSERT INTO `user`(`user_id`,`password`) VALUES(`user2`,AES_ENCRYPT(`password3`,`ENCRYPT-KEY`));

SELECT `user_id`, AES_DECRPYPT(`password`, `ENCRYPT-KEY`) FROM `user`;

psqlの暗号化と復号

PostgreSQLの機能にpgcryptという暗号関数を提供するライブラリがある

CREATE TEMPORARY FUNCTION decrypt(_text STRING) RETURNS STRING LANGUAGE js AS
"""
	if (_text === null) {return _text}
	let base64_text = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(_text))
	let key = CryptJS.enc.Utf.parse('PASSWORD\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000')
	let iv = CryptoJS.enc.Utf8.parse('')
	let options = { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 };
	let _decrypt = CryptoJS.AES.decrypt(base_text, key, options);
	return _decrypt.toString(CryptoJS.enc.Utf8);
""" OPTIONS (library="gs://xxxxxxxxx/crypto-js-4.1.1/crypto-js.js");

SELECT decrypt(substring('\\xba9a0a4189f691d761c431c89f42e319', 3));

データベースの暗号化

データベース暗号化の種類
1. データベース管理システム(DBMS)による暗号化
DBMSが持つ暗号化機能を使用する方法
しかし、サーバやパソコンのメモリ上には暗号化されていないデータが一時的に残る場合があり、高度な技術があれば読み取られてしまう恐れがある

2.ストレージ(記録装置)の暗号化
データを記録するストレージ(記録装置)自体を暗号化する方法。OSやファイルシステム、ストレージが備える暗号化機能を使ってデータが書き込まれる際に自動的に暗号化し、読み取るときに同じく自動的に解読される仕組み
OSから見ると暗号化されない状態

3.データ自体の暗号化
データ自体を暗号化してからデータベースに記録する

アクセス制御を含む暗号化を考える必要がある
情報機器の紛失・盗難対策
誤操作対策
情報機器の処分時の対策

アクセス制御など複数の対策を組み合わせて実施する訳ね

暗号処理のパディングモード(パディング方式)

分割する時にブロックで綺麗に割り切れない場合は、パディングで穴埋めします。

### パディングモード
・PKCS#5 PKCS#7 : AESと組み合わせることが多い
・Optimal Asymmetric Encryption Padding(OAEP) : RSAと組み合わせることが多い。その場合はRSA-OAEPと呼ばれる

def self.encrypt(data, pass, salt)
	cipher = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
	key_iv = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, 1000, cipher.key_len+cipher.iv_len)
	key = key_iv[0, cipher.key_len]
	iv = key_iv[cipher.key_len, cipher.iv_len]
	cipher.encrypt
	cipher.key = key
	cipher.iv = iv
	encryptvalue = cipher.update(data) + cipher.final
	return Base64.b64encode(encryptvalue)
end	

test_214_bytes.txt 214 bytes
test_215_bytes.txt 215 bytes
openssl rsautl -encrypt -oaep -pubin -inkey public-key.pem -in test_214_bytes.txt -out test_214_bytes.enc
openssl rsautl -encrypt -oaep -pubin -inkey public-key.pem -in test_215_bytes.txt -out test_215_bytes.enc

暗号アルゴリズム AES, DES, RC4, RSA, 楕円曲線暗号

共通鍵暗号方式には「DES」「RC4」「AES」などがある

### AES
AESは無線LANなどに用いられる暗号化アルゴリズムの一つで Advanced Encryption Standardの略で標準的に使われている。共通鍵暗号で、データの送信者と受信者が同じ暗号鍵を用いて暗号化と復号を実行する DES以上の強度を持つ。処理速度も優れている
AESは128,192, 256bitから鍵長を選んで利用可能
SubBytes, ShiftRows, MixColumns, AddRoundKeyなどの変換を行う
WPA2(無線LAN), SSL/TLS化通信(https://)、ファイルの暗号化などで使われている
WifiのWPA2, WPA3はAESを採用している

### DES/3DES
1977年にアメリカ連邦政府標準が採用した暗号アルゴリズム
DESは鍵長が短い(56bit)などの難点があった 総当たり攻撃に弱い
鍵長は56bitですが、パリティチェック用の8bitを加えて64bitとして扱う
この弱点を補うために2DES(DESを2回繰り返す112bitの鍵長)、3DES(DESを3回繰り返す、168bitだが処理に時間がかかる)が登場したが別の攻撃に弱いなどの弱点が見つかった
DESでは64bitのデータを半分(LとR)に分割し、同じような処理を繰り返す過程がある。この繰り返しの単位をラウンドと言う

### RC4(Rivest’s Cipher4)
ブロックのが長さ(鍵長)を自由に設定できるアルゴリズム
鍵の長さを40〜2048bitの間で自由に設定できる
逐次暗号化するすストリーム暗号 簡単にセキュリティを突破されてしまう
SSL3.0以前やWifiのWEPやWAPはRC4を用いている

### RSA
公開鍵暗号方式、暗号化と復号に別の鍵を使用する
「大きな数字を素因数分解するには膨大な時間がかかる」ことを利用したアルゴリズム。
安全性が高いが処理に時間がかかる

### 楕円曲線暗号
楕円曲線( y2 = x3 + ax + b で表される曲線)の数学的な特性を安全性の根拠とする暗号。「一方向の計算は容易でも、反対方向の計算は困難」な性質が使われることで、公開鍵が知られても容易に秘密鍵を割り出せない仕組み。暗号化や復号に必要な計算量が少なく、他のアルゴリズムより短い鍵で同等の強度が得られることから、活用の幅が広がっている。

### ハイブリッド暗号方式
共通鍵暗号方式と公開鍵暗号方式の特徴を組み合わせた方式
1. 受信者が公開鍵と秘密鍵を作成する
2. 送信者は通信で使用する「共通の秘密鍵」を作成する
3. 送信者は取得した受信者の公開鍵を使って「共通の秘密鍵」を暗号化し、送付する
4. 受信者は秘密鍵を使って「共通の秘密鍵」を復号する
ハイブリッド暗号方式は、共通鍵暗号方式の持つ鍵の受け渡しの課題を公開鍵暗号方式でカバーし、公開鍵暗号方式が持つ処理速度の遅さを共通鍵暗号方式でカバー

### ハッシュ化
不可逆性(元に戻せない性質)を持つ
ユーザーがパスワードを初期登録する際にハッシュ化によってパスワードが変換されハッシュ値が得られます。ログインをする際は、入力されたパスワードのハッシュ値と登録の際に保存されたハッシュ値を比較することで、ユーザーが同一であると認証できる

OpenSSLの実装

// 暗号化
openssl_encrypt($data, $method, $key, $options, $iv);

// 復号
openssl_decrypt($data, $method, $key, $options, $iv);

暗号化時は bin2hex、復号時は hex2bin を用いる

$enc_string = bin2hex(openssl_encrypt($data, $method, $key, 0, $iv));
$dec_string = openssl_decrypt(hex2bin($data), $method, $key, 0, $iv);
$key = "passphrase";
$str = "abcdef";

$encrypt = openssl_encrypt($str, 'aes-256-ecb', $key);
echo $encrypt;

echo "\n";
$decrypt = openssl_decrypt($encrypt, 'aes-256-ecb', $key);
echo $decrypt;

$ php index.php
HR6LV+jGY5iU8Rycs+Jv8g==
abcde