0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

暗号化

暗号化とは、データを第三者に読み取られないように変換する技術です。
暗号化には主に以下の2種類があります。

共通鍵暗号

  • 仕組み: 暗号化と復号に同じ鍵を使用
  • : AES
  • 特徴: 高速だが、クライアントとサーバー間の鍵の安全な共有が課題

公開鍵暗号

  • 仕組み: 暗号化に公開鍵、復号に秘密鍵を使用
  • : RSA
  • 特徴: 鍵の共有が容易ですが、処理速度が遅い

Webアプリケーションにおける暗号化の役割

データ通信の暗号化

WebではTLS(Transport Layer Security)が一般的です。TLSは、クライアントとサーバー間のデータ通信を暗号化して、盗聴や改ざんを防ぎます。
現在のWebアプリケーションでは、HTTP通信を暗号化するHTTPSが標準です。

TLSの仕組み

  1. クライアントがサーバーに接続をリクエスト(ハンドシェイク)
  2. サーバーは証明書を提示して自身を証明
  3. クライアントは証明書を検証し、共通鍵を生成
  4. 公開鍵を使って共通鍵を暗号化し、サーバーに送信
  5. サーバーは秘密鍵で共通鍵を復号し、暗号化通信を開始

パスワードのハッシュ化

Webアプリケーションでユーザーのパスワードを保存するとき、平文で保存してはいけません。
代わりに、ハッシュ化を利用します。

ハッシュ関数

  • 入力データを固定長のハッシュ値に変換
  • 同じ入力は必ず同じハッシュ値になる
  • 一方向性
    • ハッシュ値から元のデータを復元できない

推奨されるハッシュアルゴリズム

  • bcrypt: ソルトを自動生成し、安全性が高い
  • argon2: パスワードハッシュの最新アルゴリズム

Goでのパスワードハッシュ化の例

package main

import (
	"fmt"
	"golang.org/x/crypto/bcrypt"
)

func main() {
	password := "securepassword123"
	
	// パスワードのハッシュ化
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		fmt.Println("Error hashing password:", err)
		return
	}
	fmt.Println("Hashed Password:", string(hashedPassword))
	
	// ハッシュと元のパスワードを比較
	err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password))
	if err != nil {
		fmt.Println("Password does not match")
	} else {
		fmt.Println("Password matches")
	}
}
Hashed Password: $2a$10$vuPUBtc3p0jFsamrUx1EsuRWKd2.JJME6A3RfEuKnS3VhwancP/KW
Password matches

データ改ざんの防止

HMAC(Hash-based Message Authentication Code)

データが改ざんされていないことを確認するために使用されます。

HMACの仕組み

  1. 暗号鍵とデータをハッシュ関数に入力
  2. HMAC値をデータと共に送信
  3. 受信側で同じ手順でハッシュ値を生成し、比較
  4. ハッシュ値が一致すればデータが改ざんされていないことを確認
  5. ハッシュ値が異なればデータが改ざんされた可能性がある
  • 使用例: Webトークン(JWT)の署名検証

JWT(JSON Web Token)

JWTは、認証情報を安全にやり取りするためのフォーマットです。
署名(HMACまたはRSA)を使用して改ざんを防止します。

package main

import (
	"fmt"
	"time"

	"github.com/golang-jwt/jwt/v4"
)

func main() {
	secretKey := []byte("secret-key")

	// JWTトークンの生成
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"username": "engineer_tacky",
		"exp":      time.Now().Add(time.Hour * 1).Unix(), // 1時間後に有効期限切れ
	})
	signedToken, err := token.SignedString(secretKey)
	if err != nil {
		fmt.Println("Error creating token:", err)
		return
	}
	fmt.Println("JWT Token:", signedToken)
}
JWT Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzQ0ODU2MTEsInVzZXJuYW1lIjoiZW5naW5lZXJfdGFja3kifQ.41omonoDo1QbWiV_mGieSed_svmftVrh0T-3yWtEDks

セキュリティ対策

HTTPSの導入

  • 全ての通信をHTTPSで保護
  • Let's Encryptを使えば無料で証明書を取得可能(Certbotで更新を自動化できる)

SQLインジェクション対策

  • プリペアドステートメントを使用して、SQL文をパラメータ化
SELECT * FROM users WHERE id = ?
  • ORMの活用(GORMなど)
    • 直接SQL文を書く頻度を減らし、安全性を向上できます

クロスサイトスクリプティング(XSS)対策

  • ユーザーが入力したデータを画面に表示する際、適切にエスケープ処理を行い、HTMLタグやJavaScriptコードが埋め込まれるのを防ぎます
import "html/template"

func renderTemplate(w http.ResponseWriter, data string) {
  tmpl := template.Must(template.New("example").Parse("{{.}}"))
  tmpl.Execute(w, data) // 自動的にエスケープされる
}

クロスサイトリクエストフォージェリ(CSRF)対策

  • フォームやAPIリクエストにCSRFトークンを含めることで、意図しないリクエストを防ぎます
  • サーバー側でトークンの一致を検証します
<input type="hidden" name="_csrf" value="CSRF_TOKEN">
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?