[PD2] Made cert checks in cryptoutils
This commit is contained in:
parent
69559f41ca
commit
62962a13c7
9 changed files with 160 additions and 133 deletions
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"PD1/internal/client"
|
||||
"PD2/internal/client"
|
||||
)
|
||||
|
||||
func main(){
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"PD1/internal/gateway"
|
||||
"PD2/internal/gateway"
|
||||
)
|
||||
|
||||
func main(){
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"PD1/internal/server"
|
||||
"PD2/internal/server"
|
||||
)
|
||||
|
||||
func main(){
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module PD1
|
||||
module PD2
|
||||
|
||||
go 1.22.2
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"PD1/internal/protocol"
|
||||
"PD1/internal/utils/cryptoUtils"
|
||||
"PD1/internal/utils/networking"
|
||||
"PD2/internal/protocol"
|
||||
"PD2/internal/utils/cryptoUtils"
|
||||
"PD2/internal/utils/networking"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"flag"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package gateway
|
||||
|
||||
import (
|
||||
"PD1/internal/protocol"
|
||||
"PD1/internal/utils/cryptoUtils"
|
||||
"PD2/internal/protocol"
|
||||
"PD2/internal/utils/cryptoUtils"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -32,30 +32,30 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke
|
|||
var postRegister protocol.PostRegister
|
||||
err := c.Bind(postRegister)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest,gin.H{"error": "Request body is not a PostRegister"})
|
||||
return
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Request body is not a PostRegister"})
|
||||
return
|
||||
}
|
||||
|
||||
//Check if the certificate pseudonym matches the uid in postRegister
|
||||
//And if it's signed by the CA
|
||||
userCert, err := x509.ParseCertificate(postRegister.Certificate)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest,gin.H{"error": "User certificate is invalid"})
|
||||
return
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"})
|
||||
return
|
||||
}
|
||||
|
||||
oidMap := cryptoUtils.ExtractAllOIDValues(userCert)
|
||||
//Check if certificate usage is MSG SERVICE
|
||||
usage := oidMap["2.5.4.11"]
|
||||
if usage != "MSG SERVICE" {
|
||||
c.JSON(http.StatusBadRequest,gin.H{"error": "Certificate usage is not \"MSG SERVICE\""})
|
||||
return
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Certificate usage is not \"MSG SERVICE\""})
|
||||
return
|
||||
}
|
||||
|
||||
err = keyStore.CheckCert(userCert, postRegister.UID)
|
||||
err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest,gin.H{"error": "User certificate is invalid, not trusted or belongs to another user"})
|
||||
return
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid, not trusted, belongs to another user or has incorrect usage field"})
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := HashPassword(postRegister.Password)
|
||||
|
@ -65,10 +65,10 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke
|
|||
|
||||
err = dataStore.InsertUser(postRegister.UID, hashedPassword)
|
||||
if err != nil {
|
||||
log.Fatalln("Could not insert user into DB")
|
||||
log.Fatalln("Could not insert user into DB")
|
||||
}
|
||||
|
||||
//TODO: Send the certificate to the server
|
||||
//TODO: Send the certificate to the server
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
|
||||
|
@ -91,31 +91,30 @@ func HandleLogin(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.KeySt
|
|||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user id or password"})
|
||||
return
|
||||
}
|
||||
jwToken, err := GenerateJWT(postLogin.UID)
|
||||
jwToken, err := GenerateJWT(postLogin.UID)
|
||||
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create token"})
|
||||
}
|
||||
//Send token to user
|
||||
c.JSON(http.StatusOK, gin.H{"token":jwToken})
|
||||
}
|
||||
//Send token to user
|
||||
c.JSON(http.StatusOK, gin.H{"token": jwToken})
|
||||
}
|
||||
|
||||
|
||||
func AuthMiddleware(c *gin.Context) {
|
||||
fmt.Println("Authentication Middleware")
|
||||
tokenList := c.Request.Header["Token"]
|
||||
if tokenList == nil {
|
||||
c.JSON(http.StatusUnauthorized,gin.H{"error": "No authentication token provided"})
|
||||
}
|
||||
// We only care about the first entry
|
||||
token := tokenList[0]
|
||||
|
||||
uid, err := ValidateJWT(token)
|
||||
if err!= nil {
|
||||
c.JSON(http.StatusUnauthorized,gin.H{"error": "Token is invalid or has expired"})
|
||||
}
|
||||
c.Set("uid", uid)
|
||||
c.Next()
|
||||
tokenList := c.Request.Header["Token"]
|
||||
if tokenList == nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "No authentication token provided"})
|
||||
}
|
||||
// We only care about the first entry
|
||||
token := tokenList[0]
|
||||
|
||||
uid, err := ValidateJWT(token)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is invalid or has expired"})
|
||||
}
|
||||
c.Set("uid", uid)
|
||||
c.Next()
|
||||
}
|
||||
|
||||
func Run() {
|
||||
|
@ -164,10 +163,10 @@ func Run() {
|
|||
server := http.Server{
|
||||
Addr: "0.0.0.0:8080",
|
||||
Handler: router,
|
||||
TLSConfig: serverKeyStore.GetServerTLSConfig(),
|
||||
TLSConfig: keyStore.GetGatewayIncomingTLSConfig(),
|
||||
}
|
||||
|
||||
err := server.ListenAndServeTLS("", "")
|
||||
err = server.ListenAndServeTLS("", "")
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"PD1/internal/protocol"
|
||||
"PD2/internal/protocol"
|
||||
"crypto/x509"
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"PD1/internal/protocol"
|
||||
"PD1/internal/utils/cryptoUtils"
|
||||
"PD2/internal/protocol"
|
||||
"PD2/internal/utils/cryptoUtils"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -10,29 +10,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
//func clientHandler(connection networking.Connection[protocol.Packet], dataStore DataStore) {
|
||||
// defer connection.Conn.Close()
|
||||
//
|
||||
// //Get certificate sent by user
|
||||
// clientCert := connection.GetPeerCertificate()
|
||||
// //Get the OID values
|
||||
// oidMap := cryptoUtils.ExtractAllOIDValues(clientCert)
|
||||
// //Check if certificate usage is MSG SERVICE
|
||||
// usage := oidMap["2.5.4.11"]
|
||||
// if usage == "" {
|
||||
// log.Fatalln("User certificate does not have the correct usage")
|
||||
// }
|
||||
// //Get the UID of this user
|
||||
// UID := oidMap["2.5.4.65"]
|
||||
// if UID == "" {
|
||||
// log.Fatalln("User certificate does not specify it's PSEUDONYM")
|
||||
// }
|
||||
// err := dataStore.storeUserCertIfNotExists(UID, *clientCert)
|
||||
// if err != nil {
|
||||
// log.Fatalln(err)
|
||||
// }
|
||||
//}
|
||||
|
||||
func HandleGetUserCert(c *gin.Context, dataStore DataStore) {
|
||||
user := c.Param("user")
|
||||
userCertPacket, err := dataStore.GetUserCertificate(user)
|
||||
|
|
|
@ -19,19 +19,15 @@ import (
|
|||
)
|
||||
|
||||
type KeyStore struct {
|
||||
cert *x509.Certificate
|
||||
caCertChain []*x509.Certificate
|
||||
privKey *rsa.PrivateKey
|
||||
cert *x509.Certificate
|
||||
caCertPool *x509.CertPool
|
||||
privKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -67,25 +63,31 @@ func LoadKeyStore(keyStorePath string, password string) (KeyStore, error) {
|
|||
if err := privKey.Validate(); err != nil {
|
||||
return KeyStore{}, err
|
||||
}
|
||||
return KeyStore{cert: cert, caCertChain: caCerts, privKey: privKey}, err
|
||||
}
|
||||
|
||||
// Check if the cert is signed by the CA and is for the correct user
|
||||
func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error {
|
||||
caCertPool := x509.NewCertPool()
|
||||
for _, caCert := range k.caCertChain {
|
||||
for _, caCert := range caCerts {
|
||||
caCertPool.AddCert(caCert)
|
||||
}
|
||||
|
||||
return KeyStore{cert: cert, caCertPool: caCertPool, privKey: privKey}, err
|
||||
}
|
||||
|
||||
// Check if the cert is signed by a known CA
|
||||
func (k KeyStore) CheckCertCA(cert *x509.Certificate) error {
|
||||
// Verify the peer's certificate
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: caCertPool,
|
||||
Roots: k.caCertPool,
|
||||
}
|
||||
// Check if the certificate is signed by the specified CA
|
||||
_, err := cert.Verify(opts)
|
||||
if err != nil {
|
||||
log.Println("Certificate not signed by a trusted CA")
|
||||
return err
|
||||
return errors.New("certificate not signed by trusted CA")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if the cert is valid
|
||||
func (k KeyStore) CheckCertTime(cert *x509.Certificate) error {
|
||||
if cert.NotAfter.Before(time.Now()) {
|
||||
return errors.New("certificate has expired")
|
||||
}
|
||||
|
@ -93,10 +95,37 @@ func (k KeyStore) CheckCert(cert *x509.Certificate, uid string) error {
|
|||
return errors.New("certificate is not valid yet")
|
||||
}
|
||||
|
||||
//Check if the pseudonym field is set to UID
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if the pseudonym field is set to the correct pseudonym
|
||||
func (k KeyStore) CheckCertPseudonym(cert *x509.Certificate, pseudonym string) error {
|
||||
oidMap := ExtractAllOIDValues(cert)
|
||||
if oidMap["2.5.4.65"] != uid {
|
||||
log.Println("Certificate does not belong to the message's receiver")
|
||||
if oidMap["2.5.4.65"] != pseudonym {
|
||||
return errors.New("Certificate does not belong to the correct pseudonym")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k KeyStore) CheckCertUsage(cert *x509.Certificate, usage string) error {
|
||||
oidMap := ExtractAllOIDValues(cert)
|
||||
if oidMap["2.5.4.11"] != usage {
|
||||
return errors.New("Certificate does not have the correct usage")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k KeyStore) CheckCert(cert *x509.Certificate, pseudonym string, usage string) error {
|
||||
if err := k.CheckCertCA(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.CheckCertTime(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.CheckCertPseudonym(cert, pseudonym); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.CheckCertUsage(cert, usage); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
@ -106,49 +135,58 @@ func (k *KeyStore) GetTLSConfig() *tls.Config {
|
|||
|
||||
certificate := tls.Certificate{Certificate: [][]byte{k.cert.Raw}, PrivateKey: k.privKey, Leaf: k.cert}
|
||||
|
||||
//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},
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func (k *KeyStore) GetServerTLSConfig() *tls.Config {
|
||||
func (k *KeyStore) GetGatewayIncomingTLSConfig() *tls.Config {
|
||||
tlsConfig := k.GetTLSConfig()
|
||||
|
||||
//Add the CA certificate chain to a CertPool
|
||||
caCertPool := x509.NewCertPool()
|
||||
for _, caCert := range k.caCertChain {
|
||||
caCertPool.AddCert(caCert)
|
||||
}
|
||||
tlsConfig.ClientCAs = caCertPool
|
||||
tlsConfig.ClientAuth = tls.RequireAnyClientCert
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||
// Verify the peer's certificate
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: caCertPool,
|
||||
}
|
||||
for _, certBytes := range rawCerts {
|
||||
cert, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cert.NotAfter.Before(time.Now()) {
|
||||
return errors.New("certificate has expired")
|
||||
if err = k.CheckCertCA(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if cert.NotBefore.After(time.Now()) {
|
||||
return errors.New("certificate is not valid yet")
|
||||
if err = k.CheckCertTime(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
// Check if the certificate is signed by the specified CA
|
||||
_, err = cert.Verify(opts)
|
||||
func (k *KeyStore) GetGatewayOutgoingTLSConfig() *tls.Config {
|
||||
tlsConfig := k.GetTLSConfig()
|
||||
|
||||
tlsConfig.RootCAs = k.caCertPool
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||
for _, certBytes := range rawCerts {
|
||||
cert, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return errors.New("certificate not signed by trusted CA")
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertCA(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertTime(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertPseudonym(cert, "SERVER"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -159,41 +197,54 @@ func (k *KeyStore) GetServerTLSConfig() *tls.Config {
|
|||
func (k *KeyStore) GetClientTLSConfig() *tls.Config {
|
||||
tlsConfig := k.GetTLSConfig()
|
||||
|
||||
//Add the CA certificate chain to a CertPool
|
||||
caCertPool := x509.NewCertPool()
|
||||
for _, caCert := range k.caCertChain {
|
||||
caCertPool.AddCert(caCert)
|
||||
}
|
||||
tlsConfig.RootCAs = caCertPool
|
||||
tlsConfig.RootCAs = k.caCertPool
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||
// Verify the peer's certificate
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: caCertPool,
|
||||
}
|
||||
for _, certBytes := range rawCerts {
|
||||
cert, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cert.NotAfter.Before(time.Now()) {
|
||||
return errors.New("certificate has expired")
|
||||
if err = k.CheckCertCA(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if cert.NotBefore.After(time.Now()) {
|
||||
return errors.New("certificate is not valid yet")
|
||||
if err = k.CheckCertTime(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
|
||||
return err
|
||||
}
|
||||
oidMap := ExtractAllOIDValues(cert)
|
||||
|
||||
// Check if the certificate is signed by the specified CA
|
||||
_, err = cert.Verify(opts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return tlsConfig
|
||||
}
|
||||
|
||||
func (k *KeyStore) GetServerTLSConfig() *tls.Config {
|
||||
tlsConfig := k.GetTLSConfig()
|
||||
|
||||
tlsConfig.ClientAuth = tls.RequireAnyClientCert
|
||||
tlsConfig.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error {
|
||||
for _, certBytes := range rawCerts {
|
||||
cert, err := x509.ParseCertificate(certBytes)
|
||||
if err != nil {
|
||||
return errors.New("certificate not signed by trusted CA")
|
||||
return err
|
||||
}
|
||||
|
||||
//Check if the pseudonym field is set to "SERVER"
|
||||
if oidMap["2.5.4.65"] != "SERVER" {
|
||||
return errors.New("peer isn't the server")
|
||||
if err = k.CheckCertCA(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertTime(cert); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertPseudonym(cert, "GATEWAY"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = k.CheckCertUsage(cert, "MSG SERVICE"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
Loading…
Reference in a new issue