From 2c4f1fd2fc32edafe6cc1bb233eb4aafe6e4c6b1 Mon Sep 17 00:00:00 2001 From: afonso Date: Thu, 18 Apr 2024 13:06:16 +0100 Subject: [PATCH] [PD1] Certs done --- Projs/PD1/internal/client/client.go | 16 ++-- Projs/PD1/internal/client/interface.go | 9 +++ Projs/PD1/internal/server/server.go | 8 +- .../internal/utils/cryptoUtils/cryptoUtils.go | 77 +++++++++++++++---- Projs/PD1/internal/utils/networking/client.go | 14 +++- Projs/PD1/internal/utils/networking/server.go | 9 ++- 6 files changed, 104 insertions(+), 29 deletions(-) diff --git a/Projs/PD1/internal/client/client.go b/Projs/PD1/internal/client/client.go index 0f7dccb..4268ca5 100644 --- a/Projs/PD1/internal/client/client.go +++ b/Projs/PD1/internal/client/client.go @@ -2,6 +2,7 @@ package client import ( "PD1/internal/protocol" + "PD1/internal/utils/cryptoUtils" "PD1/internal/utils/networking" "flag" "fmt" @@ -24,16 +25,19 @@ func Run() { } uid := flag.Arg(1) subject := flag.Arg(2) - // Read message content from stdin messageContent := readMessageContent() - cl := networking.NewClient[protocol.Packet]() + + clientCert := cryptoUtils.LoadKeyStore("userdata.p12") + + cl := networking.NewClient[protocol.Packet](clientCert) defer cl.Connection.Conn.Close() - // TODO: getuserinfo client cert - // TODO: ask server for the recieving client's cert + + certRequestPacket := protocol.NewRequestUserCertPacket(uid) cl.Connection.Send(certRequestPacket) certPacket := cl.Connection.Receive() - // TODO: cipherContent := cryptoUtils.encryptMessageContent() + + // TODO: Encrypt message submitMessage(cl,uid,cipherContent) case "askqueue": @@ -52,7 +56,7 @@ func Run() { showHelp() default: - fmt.Println("Invalid command. Use 'help' for instructions.") + commandError() } } diff --git a/Projs/PD1/internal/client/interface.go b/Projs/PD1/internal/client/interface.go index 490a1dd..0e48357 100644 --- a/Projs/PD1/internal/client/interface.go +++ b/Projs/PD1/internal/client/interface.go @@ -14,6 +14,9 @@ func readMessageContent() string { return scanner.Text() } +//FIX: Why is this function in the client if it's called by crypto? +// It should be called by the client and the result +// should then be passed into the crypto library func AskUserPassword() string { fmt.Println("Enter message content (limited to 1000 bytes):") scanner := bufio.NewScanner(os.Stdin) @@ -22,6 +25,12 @@ func AskUserPassword() string { return scanner.Text() } +func commandError() { + fmt.Println("MSG SERVICE: command error!") + showHelp() +} + + func showHelp() { fmt.Println("Comandos da aplicação cliente:") fmt.Println("-user : Especifica o ficheiro com dados do utilizador. Por omissão, será assumido que esse ficheiro é userdata.p12.") diff --git a/Projs/PD1/internal/server/server.go b/Projs/PD1/internal/server/server.go index fcd2073..046b7a3 100644 --- a/Projs/PD1/internal/server/server.go +++ b/Projs/PD1/internal/server/server.go @@ -2,6 +2,7 @@ package server import ( "PD1/internal/protocol" + "PD1/internal/utils/cryptoUtils" "PD1/internal/utils/networking" "fmt" ) @@ -34,8 +35,13 @@ func Run(port int) { dataStore := OpenDB() defer dataStore.db.Close() + //TODO: Get the server's keystore path instead of hardcoding it + + //Read server keystore + serverKeyStore := cryptoUtils.LoadKeyStore("serverdata.p12") + //Create server listener - server := networking.NewServer[protocol.Packet](port) + server := networking.NewServer[protocol.Packet](serverKeyStore,port) go server.ListenLoop() for { diff --git a/Projs/PD1/internal/utils/cryptoUtils/cryptoUtils.go b/Projs/PD1/internal/utils/cryptoUtils/cryptoUtils.go index f6dcf07..ce91c51 100644 --- a/Projs/PD1/internal/utils/cryptoUtils/cryptoUtils.go +++ b/Projs/PD1/internal/utils/cryptoUtils/cryptoUtils.go @@ -2,31 +2,41 @@ package cryptoUtils import ( "PD1/internal/client" - "PD1/internal/protocol" "crypto/rsa" + "crypto/tls" "crypto/x509" - "fmt" + "encoding/pem" "log" "os" "software.sslmate.com/src/go-pkcs12" ) -func Print() { - fmt.Println("crypto package") +type KeyStore struct { + cert *x509.Certificate + caCertChain []*x509.Certificate + privKey rsa.PrivateKey } -func getUserInfo(certFilename string) ( - rsa.PrivateKey, - *x509.Certificate, - []*x509.Certificate, - error) { +func (k KeyStore) GetCert() *x509.Certificate { + return k.cert +} + +func (k KeyStore) GetCACertChain() []*x509.Certificate { + return k.caCertChain +} + +func (k KeyStore) GetPrivKey() rsa.PrivateKey { + return k.privKey +} + +func LoadKeyStore(keyStorePath string) KeyStore { + var privKey rsa.PrivateKey - certFile, err := os.ReadFile(certFilename) + certFile, err := os.ReadFile(keyStorePath) if err != nil { - log.Panicln("Provided certificate %v couldn't be opened", certFilename) - return rsa.PrivateKey{}, nil, nil, err + log.Panicln("Provided certificate %v couldn't be opened", keyStorePath) } password := client.AskUserPassword() @@ -34,16 +44,49 @@ func getUserInfo(certFilename string) ( privKey = privKeyInterface.(rsa.PrivateKey) if err != nil { log.Panicln("PKCS12 key store couldn't be decoded") - return rsa.PrivateKey{}, nil, nil, err } if err := privKey.Validate(); err != nil { log.Panicln("Private key is not valid") - return rsa.PrivateKey{}, nil, nil, err } - return privKey, cert, caCerts, nil + return KeyStore{cert: cert, caCertChain: caCerts, privKey: privKey} } -func encryptMessageContent(privKey rsa.PrivateKey, peerPubKey rsa.PublicKey, content []byte) []byte { +func (k KeyStore)GetTLSConfig() *tls.Config { + certificate ,err := tls.X509KeyPair(k.cert.Raw, pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(&k.privKey)})) + if err!=nil{ + log.Panicln("Could not load certificate and privkey to TLS") + } + + //Add the CA certificate chain to a CertPool + caCertPool := x509.NewCertPool() + for _, caCert := range k.caCertChain { + caCertPool.AddCert(caCert) + } + + config := &tls.Config{ + Certificates: []tls.Certificate{certificate}, + ClientCAs: caCertPool, + } + return config +} + +func (k KeyStore)GetTLSConfigServer() *tls.Config { + config := k.GetTLSConfig() + + config.ClientAuth = tls.RequireAndVerifyClientCert + + return config +} + +func (k KeyStore)GetTLSConfigClient() *tls.Config { + config:= k.GetTLSConfig() + + config.ServerName = "SERVER" + + return config +} + +func (k KeyStore)EncryptMessageContent(peerPubKey rsa.PublicKey, content []byte) []byte { // Digital envolope - + return nil } diff --git a/Projs/PD1/internal/utils/networking/client.go b/Projs/PD1/internal/utils/networking/client.go index d9d8a58..292c13a 100644 --- a/Projs/PD1/internal/utils/networking/client.go +++ b/Projs/PD1/internal/utils/networking/client.go @@ -1,13 +1,21 @@ package networking -import "net" +import ( + "crypto/tls" + "net" +) + + +type ClientTLSConfigProvider interface { + GetTLSConfigClient() *tls.Config +} type Client[T any] struct { Connection Connection[T] } -func NewClient[T any]() Client[T] { - dialConn, err := net.Dial("tcp", "localhost:8080") +func NewClient[T any](clientTLSConfigProvider ClientTLSConfigProvider) Client[T] { + dialConn, err := tls.Dial("tcp", "localhost:8080", clientTLSConfigProvider.GetTLSConfigClient()) if err != nil { panic("Could not open connection to server") } diff --git a/Projs/PD1/internal/utils/networking/server.go b/Projs/PD1/internal/utils/networking/server.go index 38e5d1c..0d86cdd 100644 --- a/Projs/PD1/internal/utils/networking/server.go +++ b/Projs/PD1/internal/utils/networking/server.go @@ -1,18 +1,23 @@ package networking import ( + "crypto/tls" "fmt" "net" ) +type ServerTLSConfigProvider interface { + GetServerTLSConfig() *tls.Config +} + type Server[T any] struct { listener net.Listener C chan Connection[T] } -func NewServer[T any](port int) Server[T]{ +func NewServer[T any](serverTLSConfigProvider ServerTLSConfigProvider,port int) Server[T]{ - listener, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port)) + listener, err := tls.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port), serverTLSConfigProvider.GetServerTLSConfig()) if err != nil { panic("Server could not bind to address") }