package infosecmodules

import (
	"rubric/utils"
)

var PkiModule = Module{
	Key:         "pki",
	Aliases:     []string{"pk", "tls", "ssl", "certs"},
	Title:       "PKI, TLS и сертификаты",
	Description: "PKI, X.509, TLS/SSL, цепочки доверия, Let's Encrypt, управление сертификатами",
	Run:         showPki,
}

func showPki() {
	utils.Header("InfoSec — PKI, TLS и сертификаты")

	utils.Section("PKI — инфраструктура открытых ключей")
	utils.Code(`PKI (Public Key Infrastructure) — система для управления цифровыми сертификатами.

Компоненты:
  CA (Certificate Authority)      — удостоверяющий центр
  Root CA                         — корневой CA (самоподписанный, доверяем принудительно)
  Intermediate CA                 — промежуточный CA (подписан Root CA)
  Certificate                     — сертификат (публичный ключ + метаданные, подписанные CA)
  CRL (Certificate Revocation List) — список отозванных сертификатов
  OCSP (Online Certificate Status Protocol) — онлайн-проверка статуса

Цепочка доверия:
  Root CA → Intermediate CA → End-Entity Certificate (ваш сайт)

  Браузер доверяет Root CA (встроен в ОС/браузер).
  Root CA подписал Intermediate CA.
  Intermediate CA подписал ваш сертификат.
  Браузер верифицирует всю цепочку.

Публичные CA:
  Let's Encrypt    — бесплатный, автоматический
  DigiCert         — коммерческий
  Sectigo          — коммерческий
  GlobalSign       — коммерческий`)

	utils.Section("X.509 сертификат")
	utils.Code(`X.509 — стандартный формат цифровых сертификатов.

Поля сертификата:
  Version         — версия (обычно 3)
  Serial Number   — уникальный номер
  Issuer          — кто выдал (CA)
  Subject         — для кого (CN, O, OU, C...)
  Validity        — срок действия (Not Before / Not After)
  Public Key      — публичный ключ и алгоритм
  Extensions      — расширения (SANs, Key Usage, EKU...)
  Signature       — подпись CA

Subject Alternative Names (SANs):
  Поле для нескольких доменов/IP в одном сертификате.
  Обязательно с 2017 года (CN игнорируется браузерами).
  Пример: DNS:example.com, DNS:*.example.com, IP:1.2.3.4

Типы сертификатов:
  DV (Domain Validation)   — подтверждает владение доменом
  OV (Organization Validation) — подтверждает организацию
  EV (Extended Validation) — расширенная проверка (зелёный замок)
  Wildcard *.example.com   — все субдомены одного уровня

# Просмотр сертификата:
openssl x509 -in cert.pem -text -noout
openssl s_client -connect example.com:443 -showcerts
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates`)

	utils.Section("TLS — протокол Transport Layer Security")
	utils.Code(`TLS — криптографический протокол для защиты соединений.
HTTPS = HTTP + TLS.

История версий:
  SSL 2.0 / 3.0 — СЛОМАНЫ, не использовать
  TLS 1.0 / 1.1 — устарели, отключены в браузерах с 2020
  TLS 1.2        — приемлемо, широко используется
  TLS 1.3        — текущий стандарт, быстрее и безопаснее

TLS 1.3 улучшения:
  - 1-RTT handshake (вместо 2-RTT в 1.2)
  - 0-RTT resumption (возможна реплей-атака, осторожно)
  - Убраны ненадёжные алгоритмы (RC4, MD5, SHA-1, RSA key exchange)
  - PFS обязателен (все cipher suites используют ECDHE)

TLS 1.2 Handshake:
  1. ClientHello  — версии, cipher suites, random
  2. ServerHello  — выбор версии/cipher, сертификат
  3. Key Exchange — обмен ключами (DHE/ECDHE)
  4. Finished     — проверка, начало передачи данных`)

	utils.Println(utils.ColorBold + "Cipher Suites — наборы алгоритмов:" + utils.ColorReset)
	utils.Code(`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Расшифровка:
  TLS               — протокол
  ECDHE             — обмен ключами (PFS!)
  RSA               — аутентификация сервера
  AES_256_GCM       — шифрование (AEAD)
  SHA384            — HMAC / PRF

Рекомендованные (TLS 1.2):
  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256

TLS 1.3 (фиксированный набор):
  TLS_AES_256_GCM_SHA384
  TLS_AES_128_GCM_SHA256
  TLS_CHACHA20_POLY1305_SHA256`)

	utils.Section("Управление сертификатами")
	utils.Code(`# Генерация CSR (Certificate Signing Request):
# 1. Сгенерировать приватный ключ:
openssl genrsa -out server.key 4096
# или Ed25519:
openssl genpkey -algorithm Ed25519 -out server.key

# 2. Сгенерировать CSR:
openssl req -new -key server.key -out server.csr \
  -subj "/CN=example.com/O=MyOrg/C=RU"

# 3. Добавить SAN в CSR:
openssl req -new -key server.key -out server.csr \
  -subj "/CN=example.com" \
  -addext "subjectAltName=DNS:example.com,DNS:www.example.com,IP:1.2.3.4"

# Самоподписанный сертификат (для тестирования):
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -days 365 -nodes \
  -subj "/CN=localhost" \
  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

# Проверить CSR:
openssl req -text -noout -in server.csr

# Проверить сертификат:
openssl x509 -text -noout -in server.crt
openssl verify -CAfile ca-chain.pem server.crt

# Проверить что ключ соответствует сертификату:
openssl x509 -noout -modulus -in server.crt | md5sum
openssl rsa  -noout -modulus -in server.key | md5sum`)

	utils.Section("Let's Encrypt и ACME")
	utils.Code(`Let's Encrypt — бесплатный автоматический CA.
ACME — протокол автоматической выдачи сертификатов.

# Certbot (стандартный клиент):
certbot --nginx -d example.com -d www.example.com  # Nginx
certbot --apache -d example.com                    # Apache
certbot certonly --standalone -d example.com       # standalone
certbot certonly --dns-cloudflare -d "*.example.com"  # wildcard через DNS

# Автоообновление (systemd timer или cron):
certbot renew --dry-run    # проверить
# Systemd timer создаётся автоматически certbot-ом

# Файлы сертификата:
/etc/letsencrypt/live/example.com/
  cert.pem       — сертификат домена
  chain.pem      — промежуточные CA
  fullchain.pem  — cert + chain (для nginx/apache)
  privkey.pem    — приватный ключ

# acme.sh — альтернативный клиент:
curl https://get.acme.sh | sh
acme.sh --issue -d example.com --webroot /var/www/html
acme.sh --install-cert -d example.com \
  --cert-file /etc/nginx/ssl/cert.pem \
  --key-file /etc/nginx/ssl/key.pem \
  --fullchain-file /etc/nginx/ssl/fullchain.pem \
  --reloadcmd "nginx -s reload"`)

	utils.Section("Собственный CA (Internal PKI)")
	utils.Code(`# Создание Root CA:
mkdir -p ca/{certs,crl,newcerts,private}
chmod 700 ca/private
touch ca/index.txt
echo 1000 > ca/serial

openssl genrsa -aes256 -out ca/private/ca.key 4096
chmod 400 ca/private/ca.key

openssl req -new -x509 -days 3650 -key ca/private/ca.key \
  -out ca/certs/ca.crt \
  -subj "/C=RU/O=MyOrg/CN=MyOrg Root CA"

# Подпись сертификата своим CA:
openssl x509 -req -in server.csr \
  -CA ca/certs/ca.crt -CAkey ca/private/ca.key \
  -CAcreateserial -out server.crt \
  -days 365 -extensions v3_req

# Распространение Root CA:
# Linux: cp ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates
# Windows: Сертификаты → Доверенные корневые центры

# cert-manager (Kubernetes):
# Автоматическое управление сертификатами в K8s
# Поддерживает Let's Encrypt, Vault, собственный CA`)

	utils.Section("Проверка TLS конфигурации")
	utils.Code(`# SSL Labs — онлайн тест:
# https://www.ssllabs.com/ssltest/

# testssl.sh — локальный тест:
testssl.sh example.com
testssl.sh --protocols example.com    # только протоколы
testssl.sh --cipher-per-proto example.com

# nmap:
nmap --script ssl-enum-ciphers -p 443 example.com

# Проверить с командной строки:
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
curl -vI https://example.com 2>&1 | grep -E "TLS|SSL|cipher"

# Проверить дату истечения:
echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -enddate

# Проверить HSTS:
curl -sI https://example.com | grep -i strict`)

	utils.Footer()
}
