// tofuproxy -- flexible HTTP/HTTPS proxy, TLS terminator, X.509 TOFU
//              manager, WARC/geminispace browser
// Copyright (C) 2021-2026 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package main

import (
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"log"
	"math/big"
	"os"
	"time"

	"go.stargrave.org/tofuproxy"
)

func main() {
	cn := flag.String("cn", "tofuproxy.localhost", "CommonName")
	ai := flag.String("ai", "eddsa", "ecdsa|eddsa (ECDSA-256 or EdDSA algorithm)")
	flag.Parse()
	log.SetFlags(log.Lshortfile)

	pub, prv := tofuproxy.NewKeypair(*ai)
	notBefore := time.Now()
	notAfter := notBefore.Add(365 * 24 * time.Hour)

	serialRaw := make([]byte, 16)
	rand.Read(serialRaw)
	serial := big.NewInt(0)
	serial = serial.SetBytes(serialRaw)

	template := x509.Certificate{
		SerialNumber:          serial,
		Subject:               pkix.Name{CommonName: *cn},
		DNSNames:              []string{*cn},
		NotBefore:             notBefore,
		NotAfter:              notAfter,
		BasicConstraintsValid: true,
		IsCA:                  true,
	}
	certRaw, err := x509.CreateCertificate(
		rand.Reader, &template, &template, pub, prv,
	)
	if err != nil {
		log.Fatalln(err)
	}
	if _, err = x509.ParseCertificate(certRaw); err != nil {
		log.Fatalln(err)
	}
	pkcs8, err := x509.MarshalPKCS8PrivateKey(prv)
	if err != nil {
		log.Fatalln(err)
	}

	err = pem.Encode(os.Stdout, &pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8})
	if err != nil {
		log.Fatalln(err)
	}
	err = pem.Encode(os.Stdout, &pem.Block{Type: "CERTIFICATE", Bytes: certRaw})
	if err != nil {
		log.Fatalln(err)
	}
}
