From e65dc561acab7a9e49f59777f16cb040c574c64d Mon Sep 17 00:00:00 2001 From: fusion32 Date: Thu, 3 Jul 2025 10:10:27 -0300 Subject: implement `crypto.cc` with OpenSSL + fix config loading I considered reversing the original `vlong` implementation but OpenSSL is just simpler, more secure, and most importantly, is already there. I also made it so the key is now stored in a PEM file (`tibia.pem`) so it can be easily swapped without re-compiling. This was the last piece to build and run a working executable, except that we now need to implement a query manager for the server to communicate with. I was able to fix a small problem with loading the config before hitting the problem with the query manager, which was expected. The next task should be getting a query manager up and running before starting phase two of upgrading and fixing the server itself. --- tools/genpem.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tools/genpem.go (limited to 'tools/genpem.go') diff --git a/tools/genpem.go b/tools/genpem.go new file mode 100644 index 0000000..542fd9a --- /dev/null +++ b/tools/genpem.go @@ -0,0 +1,71 @@ +package main + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "math/big" + "os" +) + +const ( + P = "1201758001370723323398753778257470257713354828752713123415294815" + + "0506251412291888866940292054989907714155267326586216043845592229" + + "084368540020196135619327879" + + Q = "1189892136861686835188050824611210139447876026576932541274639840" + + "5473436969889506919017477758618276066588858607419440134394668095" + + "105156501566867770737187273" + + E = "65537" +) + +func main() { + // NOTE(fusion): Generate key from known P, Q, and E. There isn't a helper + // function from the standard library so we need to build the private key + // ourselves. + p, ok := new(big.Int).SetString(P, 10) + if !ok || !p.ProbablyPrime(4) { + panic("invalid P") + } + + q, ok := new(big.Int).SetString(Q, 10) + if !ok || !q.ProbablyPrime(4) { + panic("invalid Q") + } + + e, ok := new(big.Int).SetString(E, 10) + if !ok || !e.IsInt64() || !e.ProbablyPrime(4) { + panic("invalid E") + } + + pMinus1 := new(big.Int).Sub(p, big.NewInt(1)) + qMinus1 := new(big.Int).Sub(q, big.NewInt(1)) + gcd := new(big.Int).GCD(nil, nil, pMinus1, qMinus1) + phi := new(big.Int).Mul(pMinus1, qMinus1) + lambda := new(big.Int).Div(phi, gcd) + d := new(big.Int).ModInverse(e, lambda) + n := new(big.Int).Mul(p, q) + + privateKey := rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: n, + E: int(e.Int64()), + }, + D: d, + Primes: []*big.Int{p, q}, + } + + // NOTE(fusion): `Validate()` will only perform minor sanity checks. To actually + // check that the output key is valid use `openssl rsa -in KEY.PEM -check`. + if err := privateKey.Validate(); err != nil { + panic("invalid private key: " + err.Error()) + } + + // NOTE(fusion): Dump private key into stdout. + block := pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(&privateKey), + } + pem.Encode(os.Stdout, &block) +} -- cgit v1.2.3