chore: Seperate code into multiple files for client and server.

This commit is contained in:
greysoh 2024-10-20 12:13:23 -04:00
parent a977e69aef
commit a5e479cc0c
Signed by: imterah
GPG key ID: 8FA7DD57BA6CEA37
7 changed files with 230 additions and 188 deletions

View file

@ -1,8 +1,6 @@
package client package client
import ( import (
"crypto/cipher"
"crypto/rand"
"fmt" "fmt"
"net" "net"
@ -12,74 +10,6 @@ import (
"github.com/ProtonMail/gopenpgp/v3/crypto" "github.com/ProtonMail/gopenpgp/v3/crypto"
) )
func (bismuth BismuthClient) encryptMessage(aead cipher.AEAD, msg []byte) ([]byte, error) {
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return []byte{}, err
}
encryptedMsg := aead.Seal(nonce, nonce, msg, nil)
return encryptedMsg, nil
}
func (bismuth BismuthClient) decryptMessage(aead cipher.AEAD, encMsg []byte) ([]byte, error) {
if len(encMsg) < aead.NonceSize() {
return []byte{}, fmt.Errorf("ciphertext too short")
}
// Split nonce and ciphertext.
nonce, ciphertext := encMsg[:aead.NonceSize()], encMsg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
decryptedData, err := aead.Open(nil, nonce, ciphertext, nil)
if err != nil {
return []byte{}, err
}
return decryptedData, nil
}
// Checks to see if a certificate is trusted in the client cache.
//
// - `host`: The host of the server.
// - `certificateFingerprint`: A fingerprint of the servers key.
// - `isSelfSigned`: If true, the certificate is either actually self-signed, or
// verification is dsabled (CheckIfCertificatesAreSigned in BismuthClient is false)
// - `isTrustworthy`: If true, the certificate is signed by 51% of peers.
type CertCheckCallback func(host, certificateFingerprint string, isSelfSigned, isTrustworthy bool) bool
// Connects to a server using a provided method, with host being the host:
//
// OwnConnMethodCallback("google.com:80")
type OwnConnMethodCallback func(address string) (net.Conn, error)
// Bismuth Client
type BismuthClient struct {
// GOpenPGP public key
PublicKey *crypto.Key
// GOpenPGP private key
PrivateKey *crypto.Key
// Check if the certificates are signed if enabled.
//
// If true, "cross-verifies" the server to make sure the certificates are signed.
//
// If false, all certificates will be reported as being self signed because we can't
// really prove otherwise.
CheckIfCertificatesAreSigned bool
// Checks to see if a certificate is trusted in the client cache.
// See CertCheckCallback for more typing information.
CertificateSignChecker CertCheckCallback
// Connects to a server (used for CheckIfCertificatesAreSigned if enabled/set to true).
ConnectToServer OwnConnMethodCallback
// GopenPGP instance
pgp *crypto.PGPHandle
}
// Initializes the client. Should be done automatically if you call New() // Initializes the client. Should be done automatically if you call New()
// //
// If you don't call client.New(), you *MUST* call this function before running bismuth.Conn(). // If you don't call client.New(), you *MUST* call this function before running bismuth.Conn().
@ -240,33 +170,3 @@ func (bismuth BismuthClient) Conn(conn net.Conn) (net.Conn, error) {
Bismuth: &bmConn, Bismuth: &bmConn,
}, nil }, nil
} }
// Creates a new BismuthClient.
//
// Both `pubKey` and `privKey` are armored PGP public and private keys respectively.
func New(pubKey string, privKey string) (*BismuthClient, error) {
publicKey, err := crypto.NewKeyFromArmored(pubKey)
if err != nil {
return nil, err
}
privateKey, err := crypto.NewKeyFromArmored(privKey)
if err != nil {
return nil, err
}
bismuth := BismuthClient{
PublicKey: publicKey,
PrivateKey: privateKey,
}
err = bismuth.InitializeClient()
if err != nil {
return nil, err
}
return &bismuth, nil
}

46
client/typing.go Normal file
View file

@ -0,0 +1,46 @@
package client
import (
"net"
"github.com/ProtonMail/gopenpgp/v3/crypto"
)
// Checks to see if a certificate is trusted in the client cache.
//
// - `host`: The host of the server.
// - `certificateFingerprint`: A fingerprint of the servers key.
// - `isSelfSigned`: If true, the certificate is either actually self-signed, or
// verification is dsabled (CheckIfCertificatesAreSigned in BismuthClient is false)
// - `isTrustworthy`: If true, the certificate is signed by 51% of peers.
type CertCheckCallback func(host, certificateFingerprint string, isSelfSigned, isTrustworthy bool) bool
// Connects to a server using a provided method, with host being the host:
//
// OwnConnMethodCallback("google.com:80")
type OwnConnMethodCallback func(address string) (net.Conn, error)
// Bismuth Client
type BismuthClient struct {
// GOpenPGP public key
PublicKey *crypto.Key
// GOpenPGP private key
PrivateKey *crypto.Key
// Check if the certificates are signed if enabled.
//
// If true, "cross-verifies" the server to make sure the certificates are signed.
//
// If false, all certificates will be reported as being self signed because we can't
// really prove otherwise.
CheckIfCertificatesAreSigned bool
// Checks to see if a certificate is trusted in the client cache.
// See CertCheckCallback for more typing information.
CertificateSignChecker CertCheckCallback
// Connects to a server (used for CheckIfCertificatesAreSigned if enabled/set to true).
ConnectToServer OwnConnMethodCallback
// GopenPGP instance
pgp *crypto.PGPHandle
}

68
client/utils.go Normal file
View file

@ -0,0 +1,68 @@
package client
import (
"crypto/cipher"
"crypto/rand"
"fmt"
"github.com/ProtonMail/gopenpgp/v3/crypto"
)
func (bismuth BismuthClient) encryptMessage(aead cipher.AEAD, msg []byte) ([]byte, error) {
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return []byte{}, err
}
encryptedMsg := aead.Seal(nonce, nonce, msg, nil)
return encryptedMsg, nil
}
func (bismuth BismuthClient) decryptMessage(aead cipher.AEAD, encMsg []byte) ([]byte, error) {
if len(encMsg) < aead.NonceSize() {
return []byte{}, fmt.Errorf("ciphertext too short")
}
// Split nonce and ciphertext.
nonce, ciphertext := encMsg[:aead.NonceSize()], encMsg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
decryptedData, err := aead.Open(nil, nonce, ciphertext, nil)
if err != nil {
return []byte{}, err
}
return decryptedData, nil
}
// Creates a new BismuthClient.
//
// Both `pubKey` and `privKey` are armored PGP public and private keys respectively.
func New(pubKey string, privKey string) (*BismuthClient, error) {
publicKey, err := crypto.NewKeyFromArmored(pubKey)
if err != nil {
return nil, err
}
privateKey, err := crypto.NewKeyFromArmored(privKey)
if err != nil {
return nil, err
}
bismuth := BismuthClient{
PublicKey: publicKey,
PrivateKey: privateKey,
}
err = bismuth.InitializeClient()
if err != nil {
return nil, err
}
return &bismuth, nil
}

View file

@ -2,32 +2,44 @@
package commons package commons
// Commands // Core Protocol Commands
const ( const (
// SendPublicKey: Sending public key back and forth // Sending public key back and forth
SendPublicKey = iota SendPublicKey = iota
// SwitchToSymmetricKey: Sent by the client along with the symmetric key that is going to be used // Sent by the client along with the symmetric key that is going to be used
SwitchToSymmetricKey SwitchToSymmetricKey
// ClientSendHost: Currently unimplemented.
// Client sends what host they are connecting to. // Client sends what host they are connecting to.
// Currently unimplemented.
ClientSendHost ClientSendHost
// GetSigningServers: Currently unimplemented.
// Gets the signing servers trusting/signing the current server. // Gets the signing servers trusting/signing the current server.
// Currently unimplemented.
GetSigningServers GetSigningServers
// GetTrustedDomains: Currently unimplemented.
// Gets the domains that are supported by this certificate (should be cross-checked) // Gets the domains that are supported by this certificate (should be cross-checked)
// Currently unimplemented.
GetTrustedDomains GetTrustedDomains
// InitiateForwarding: Starts forwarding traffic over this protocol. // Starts forwarding traffic over this protocol.
InitiateForwarding InitiateForwarding
) )
// Encryption algorithms // Validation API Commands
const (
// Checks if the domains are valid for a specified key
AreDomainsValidForKey = iota
// Validate a server and keys
ValidateKey
// Status codes
Success
Failure
InternalError
)
// Encryption Algorithms
const ( const (
// Default and only encryption algorithm // Default and only encryption algorithm
XChaCha20Poly1305 = iota XChaCha20Poly1305 = iota
) )
// Unsigned integer limits // Unsigned Integer Limits
const ( const (
BitLimit24 = 16_777_215 BitLimit24 = 16_777_215
BitLimit16 = 65535 BitLimit16 = 65535

View file

@ -1,7 +1,6 @@
package server package server
import ( import (
"fmt"
"net" "net"
core "git.greysoh.dev/imterah/bismuthd/commons" core "git.greysoh.dev/imterah/bismuthd/commons"
@ -13,54 +12,6 @@ import (
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )
// Bismuth Server
type BismuthServer struct {
// Public key to use for transmission
PublicKey *crypto.Key
// Private key to use for transmission
PrivateKey *crypto.Key
pgp *crypto.PGPHandle
// Algorithm to use for encryption (currently XChaCha20Poly1305 is the only option)
SymmetricEncryptionAlgorithm int
// Servers that are signing this server. If none, this server becomes self-signed
// in the clients eyes
SigningServers []string
// Called after a successful handshake & connection.
HandleConnection func(conn net.Conn) error
}
func (bismuth BismuthServer) encryptMessage(aead cipher.AEAD, msg []byte) ([]byte, error) {
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return []byte{}, err
}
encryptedMsg := aead.Seal(nonce, nonce, msg, nil)
return encryptedMsg, nil
}
func (bismuth BismuthServer) decryptMessage(aead cipher.AEAD, encMsg []byte) ([]byte, error) {
if len(encMsg) < aead.NonceSize() {
return []byte{}, fmt.Errorf("ciphertext too short")
}
// Split nonce and ciphertext.
nonce, ciphertext := encMsg[:aead.NonceSize()], encMsg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
decryptedData, err := aead.Open(nil, nonce, ciphertext, nil)
if err != nil {
return []byte{}, err
}
return decryptedData, nil
}
// Called to handle a connnection for Bismuth. The conn argument is the client you'd like to handle // Called to handle a connnection for Bismuth. The conn argument is the client you'd like to handle
func (bismuth BismuthServer) HandleProxy(conn net.Conn) error { func (bismuth BismuthServer) HandleProxy(conn net.Conn) error {
serverState := "keyHandshake" serverState := "keyHandshake"
@ -229,33 +180,3 @@ func (bismuth BismuthServer) HandleProxy(conn net.Conn) error {
} }
} }
} }
// Initializes a Bismuth server.
//
// Both `pubKey` and `privKey` are armored PGP public and private keys respectively.
func NewBismuthServer(pubKey string, privKey string, signServers []string, encryptionAlgo int, connHandler func(conn net.Conn) error) (*BismuthServer, error) {
publicKey, err := crypto.NewKeyFromArmored(pubKey)
if err != nil {
return nil, err
}
privateKey, err := crypto.NewKeyFromArmored(privKey)
if err != nil {
return nil, err
}
pgp := crypto.PGP()
bismuth := BismuthServer{
PublicKey: publicKey,
PrivateKey: privateKey,
HandleConnection: connHandler,
SigningServers: signServers,
SymmetricEncryptionAlgorithm: encryptionAlgo,
pgp: pgp,
}
return &bismuth, nil
}

26
server/typing.go Normal file
View file

@ -0,0 +1,26 @@
package server
import (
"net"
"github.com/ProtonMail/gopenpgp/v3/crypto"
)
// Bismuth Server
type BismuthServer struct {
// Public key to use for transmission
PublicKey *crypto.Key
// Private key to use for transmission
PrivateKey *crypto.Key
pgp *crypto.PGPHandle
// Algorithm to use for encryption (currently XChaCha20Poly1305 is the only option)
SymmetricEncryptionAlgorithm int
// Servers that are signing this server. If none, this server becomes self-signed
// in the clients eyes
SigningServers []string
// Called after a successful handshake & connection.
HandleConnection func(conn net.Conn) error
}

69
server/utils.go Normal file
View file

@ -0,0 +1,69 @@
package server
import (
"crypto/cipher"
"crypto/rand"
"fmt"
"net"
"github.com/ProtonMail/gopenpgp/v3/crypto"
)
func (bismuth BismuthServer) encryptMessage(aead cipher.AEAD, msg []byte) ([]byte, error) {
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(msg)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
return []byte{}, err
}
encryptedMsg := aead.Seal(nonce, nonce, msg, nil)
return encryptedMsg, nil
}
func (bismuth BismuthServer) decryptMessage(aead cipher.AEAD, encMsg []byte) ([]byte, error) {
if len(encMsg) < aead.NonceSize() {
return []byte{}, fmt.Errorf("ciphertext too short")
}
// Split nonce and ciphertext.
nonce, ciphertext := encMsg[:aead.NonceSize()], encMsg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
decryptedData, err := aead.Open(nil, nonce, ciphertext, nil)
if err != nil {
return []byte{}, err
}
return decryptedData, nil
}
// Initializes a Bismuth server.
//
// Both `pubKey` and `privKey` are armored PGP public and private keys respectively.
func NewBismuthServer(pubKey string, privKey string, signServers []string, encryptionAlgo int, connHandler func(conn net.Conn) error) (*BismuthServer, error) {
publicKey, err := crypto.NewKeyFromArmored(pubKey)
if err != nil {
return nil, err
}
privateKey, err := crypto.NewKeyFromArmored(privKey)
if err != nil {
return nil, err
}
pgp := crypto.PGP()
bismuth := BismuthServer{
PublicKey: publicKey,
PrivateKey: privateKey,
HandleConnection: connHandler,
SigningServers: signServers,
SymmetricEncryptionAlgorithm: encryptionAlgo,
pgp: pgp,
}
return &bismuth, nil
}