package main

// Eklenti paketi dogrulamasi. Bridge, Ed25519 imzasi ve SHA-256 ozeti tutmayan HICBIR
// dosyayi kabul etmez. Imzalama anahtarinin GIZLI kismi bu koda ve bu depoya ASLA girmez;
// anahtar cevrimdisi tutulur. Gomulu acik anahtar bos ise hicbir eklenti kurulamaz.

import (
	"crypto/ed25519"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"strings"
)

// Gomulu acik anahtar (Ed25519, base64). Bos birakilirsa kurulum tamamen kapalidir.
var paketAcikAnahtar = "bE1qYWOzKZasuepzdrtWGEIcDYAm6RvI6Ymy+HVpYcA="

var (
	errPaketAnahtarYok = errors.New("eklenti imza anahtari tanimli degil")
	errPaketImza       = errors.New("eklenti imzasi gecersiz")
	errPaketOzet       = errors.New("eklenti dosyasi ozeti uyusmuyor")
)

// paketBilgisi: katalogdan gelen, imzalanmis manifest.
// Bicim "v1" (eski paketler; acilis alani imzalanmaz) ya da "v2" (acilis alani imzalanir).
type paketBilgisi struct {
	Anahtar string `json:"anahtar"`
	Surum   string `json:"surum"`
	Sha256  string `json:"sha256"`
	Imza    string `json:"imza"`
	Bicim   string `json:"bicim"`
	Acilis  bool   `json:"acilis"`
}

// acilisiIstiyor: acilis bayragi yalnizca imzali v2 pakette gecerlidir.
// v1 imzasi acilis alanini kapsamadigi icin v1 pakette bayrak degeri yok sayilir.
func acilisiIstiyor(p paketBilgisi) bool {
	return p.Bicim == "v2" && p.Acilis
}

// imzaliMetin: imzalanan metin. Alanlar sabit sirada, ayirici '\n'.
// v2 metni acilis bayragini da icerir; bayrak boylece imzayla baglanir.
func imzaliMetin(p paketBilgisi) []byte {
	ozet := strings.ToLower(p.Sha256)
	if p.Bicim == "v2" {
		acilis := "0"
		if p.Acilis {
			acilis = "1"
		}
		return []byte("fikoyt-eklenti-v2\n" + p.Anahtar + "\n" + p.Surum + "\n" + ozet + "\n" + acilis)
	}
	return []byte("fikoyt-eklenti-v1\n" + p.Anahtar + "\n" + p.Surum + "\n" + ozet)
}

// paketDogrula: once imza (manifest, sha256 dahil), sonra dosya ozeti kontrol edilir.
func paketDogrula(p paketBilgisi, anahtarB64 string, dosya []byte) error {
	if anahtarB64 == "" {
		return errPaketAnahtarYok
	}
	pub, err := base64.StdEncoding.DecodeString(anahtarB64)
	if err != nil || len(pub) != ed25519.PublicKeySize {
		return errPaketAnahtarYok
	}
	imza, err := base64.StdEncoding.DecodeString(p.Imza)
	if err != nil || len(imza) != ed25519.SignatureSize {
		return errPaketImza
	}
	if !ed25519.Verify(pub, imzaliMetin(p), imza) {
		return errPaketImza
	}
	ozet := sha256.Sum256(dosya)
	if !strings.EqualFold(hex.EncodeToString(ozet[:]), p.Sha256) {
		return errPaketOzet
	}
	return nil
}
