162 lines
4.5 KiB
Python
162 lines
4.5 KiB
Python
import secrets
|
|
import hashlib
|
|
import hmac
|
|
import base64
|
|
import uuid
|
|
import os
|
|
import string
|
|
from flask import Flask, render_template, request, jsonify
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
KEY_CONFIGS = {
|
|
"jwt_hs256": {
|
|
"label": "JWT Secret (HS256)",
|
|
"description": "HMAC-SHA256용 JWT 시크릿 키",
|
|
"bytes": 32,
|
|
"format": "hex",
|
|
},
|
|
"jwt_hs384": {
|
|
"label": "JWT Secret (HS384)",
|
|
"description": "HMAC-SHA384용 JWT 시크릿 키",
|
|
"bytes": 48,
|
|
"format": "hex",
|
|
},
|
|
"jwt_hs512": {
|
|
"label": "JWT Secret (HS512)",
|
|
"description": "HMAC-SHA512용 JWT 시크릿 키",
|
|
"bytes": 64,
|
|
"format": "hex",
|
|
},
|
|
"jwt_base64": {
|
|
"label": "JWT Secret (Base64URL)",
|
|
"description": "Base64URL 인코딩 JWT 시크릿 (256-bit)",
|
|
"bytes": 32,
|
|
"format": "base64url",
|
|
},
|
|
"api_key": {
|
|
"label": "API Key",
|
|
"description": "sk- 접두사 포함 API 키",
|
|
"bytes": 32,
|
|
"format": "api_key",
|
|
},
|
|
"op_key": {
|
|
"label": "Operation Key",
|
|
"description": "ops- 접두사 포함 운영 키",
|
|
"bytes": 24,
|
|
"format": "op_key",
|
|
},
|
|
"hex_256": {
|
|
"label": "Random Hex (256-bit)",
|
|
"description": "순수 랜덤 Hex 문자열",
|
|
"bytes": 32,
|
|
"format": "hex",
|
|
},
|
|
"hex_512": {
|
|
"label": "Random Hex (512-bit)",
|
|
"description": "순수 랜덤 Hex 문자열 (512-bit)",
|
|
"bytes": 64,
|
|
"format": "hex",
|
|
},
|
|
"alphanumeric": {
|
|
"label": "Alphanumeric Key",
|
|
"description": "영숫자 조합 랜덤 키",
|
|
"bytes": 32,
|
|
"format": "alphanumeric",
|
|
},
|
|
"uuid_v4": {
|
|
"label": "UUID v4",
|
|
"description": "표준 UUID v4",
|
|
"bytes": 16,
|
|
"format": "uuid",
|
|
},
|
|
"custom": {
|
|
"label": "Custom Length",
|
|
"description": "직접 바이트 수 지정",
|
|
"bytes": None,
|
|
"format": "hex",
|
|
},
|
|
}
|
|
|
|
|
|
def generate_key(key_type: str, custom_bytes: int = 32, custom_format: str = "hex") -> dict:
|
|
config = KEY_CONFIGS.get(key_type)
|
|
if not config:
|
|
raise ValueError(f"Unknown key type: {key_type}")
|
|
|
|
byte_length = config["bytes"] if config["bytes"] is not None else custom_bytes
|
|
fmt = custom_format if key_type == "custom" else config["format"]
|
|
|
|
raw = secrets.token_bytes(byte_length)
|
|
|
|
if fmt == "hex":
|
|
key = raw.hex()
|
|
elif fmt == "base64url":
|
|
key = base64.urlsafe_b64encode(raw).rstrip(b"=").decode()
|
|
elif fmt == "api_key":
|
|
encoded = base64.urlsafe_b64encode(raw).rstrip(b"=").decode()
|
|
key = f"sk-{encoded}"
|
|
elif fmt == "op_key":
|
|
encoded = base64.urlsafe_b64encode(raw).rstrip(b"=").decode()
|
|
key = f"ops-{encoded}"
|
|
elif fmt == "alphanumeric":
|
|
alphabet = string.ascii_letters + string.digits
|
|
key = "".join(secrets.choice(alphabet) for _ in range(byte_length))
|
|
elif fmt == "uuid":
|
|
key = str(uuid.uuid4())
|
|
else:
|
|
key = raw.hex()
|
|
|
|
return {
|
|
"key": key,
|
|
"type": key_type,
|
|
"label": config["label"],
|
|
"bits": byte_length * 8,
|
|
"length": len(key),
|
|
"algorithm": fmt.upper(),
|
|
}
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
return render_template("index.html", key_configs=KEY_CONFIGS)
|
|
|
|
|
|
@app.route("/api/generate", methods=["POST"])
|
|
def api_generate():
|
|
data = request.get_json() or {}
|
|
key_type = data.get("type", "jwt_hs256")
|
|
custom_bytes = int(data.get("custom_bytes", 32))
|
|
custom_format = data.get("custom_format", "hex")
|
|
|
|
if custom_bytes < 8:
|
|
custom_bytes = 8
|
|
elif custom_bytes > 512:
|
|
custom_bytes = 512
|
|
|
|
try:
|
|
result = generate_key(key_type, custom_bytes, custom_format)
|
|
return jsonify({"success": True, "data": result})
|
|
except Exception as e:
|
|
return jsonify({"success": False, "error": str(e)}), 400
|
|
|
|
|
|
@app.route("/api/generate/bulk", methods=["POST"])
|
|
def api_generate_bulk():
|
|
data = request.get_json() or {}
|
|
key_type = data.get("type", "jwt_hs256")
|
|
count = min(int(data.get("count", 5)), 20)
|
|
custom_bytes = int(data.get("custom_bytes", 32))
|
|
custom_format = data.get("custom_format", "hex")
|
|
|
|
try:
|
|
results = [generate_key(key_type, custom_bytes, custom_format) for _ in range(count)]
|
|
return jsonify({"success": True, "data": results})
|
|
except Exception as e:
|
|
return jsonify({"success": False, "error": str(e)}), 400
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(debug=True, host="0.0.0.0", port=5050)
|