package server import ( "encoding/json" "fmt" "os" "forge.redroom.link/yves/meowlib" "github.com/ProtonMail/gopenpgp/v2/helper" "google.golang.org/protobuf/proto" ) const key = "3pw0c8#6ZG8{75b5;3?fe80$2" type Identity struct { ServerName string `json:"servername,omitempty"` ServerDesc string `json:"serverdesc,omitempty"` ServerKp meowlib.KeyPair `json:"server_kp,omitempty"` Status string `json:"status,omitempty"` OwnerName string `json:"owner_name,omitempty"` OwnerPublicKey string `json:"owner_public_key,omitempty"` ArchiveClients []string `json:"archive_clients,omitempty"` KnownServers []meowlib.ServerCard `json:"known_servers,omitempty"` } func CreateIdentity(ServerName string, ServerDesc string) *Identity { var id Identity id.ServerName = ServerName id.ServerDesc = ServerDesc id.ServerKp = meowlib.NewKeyPair() return &id } func LoadIdentity(File string) (*Identity, error) { var id Identity indata, err := os.ReadFile(File) if err != nil { return nil, err } pass, err := helper.DecryptMessageWithPassword([]byte(key), string(indata)) if err != nil { return nil, err } err = json.Unmarshal([]byte(pass), &id) return &id, err } func (id *Identity) Save(file string) error { b, _ := json.Marshal(id) armor, err := helper.EncryptMessageWithPassword([]byte(key), string(b)) if err != nil { return err } err = os.WriteFile(file, []byte(armor), 0600) return err } // // Inbound processing chain // // Unpack a protobuf received packed message func (id *Identity) UnpackReceived(message []byte) (fromPublicKey string, encryptedMessage []byte, signature []byte, err error) { pmsg := &meowlib.PackedServerMessage{} if err := proto.Unmarshal(message, pmsg); err != nil { return "", nil, nil, err } return pmsg.From, pmsg.Payload, pmsg.Signature, nil } // AsymDecryptMessage reads a message from a specific client contact func (id *Identity) AsymDecryptMessage(ClientPublicKey string, Message []byte, Signature []byte) (DecryptedMsg []byte, err error) { DecryptedMsg, err = meowlib.AsymDecryptAndCheck(id.ServerKp.Private, ClientPublicKey, Message, Signature) if err != nil { fmt.Println(err.Error()) return nil, err } return DecryptedMsg, err } // Decode decrypted ToServerMessage func (id *Identity) DeserializeToServerMessage(toServerMessage []byte) (*meowlib.ToServerMessage, error) { tsmsg := &meowlib.ToServerMessage{} if err := proto.Unmarshal(toServerMessage, tsmsg); err != nil { return nil, err } return tsmsg, nil } // Inbound helper function func (id *Identity) ProcessInbound(message []byte) (*meowlib.ToServerMessage, error) { // Unpack srv_from, srv_encmsg, srv_signature, err := id.UnpackReceived(message) if err != nil { return nil, err } // Decrypt srv_clear, err := id.AsymDecryptMessage(srv_from, srv_encmsg, srv_signature) if err != nil { return nil, err } // Decode msg srv_msg, err := id.DeserializeToServerMessage(srv_clear) if err != nil { return nil, err } return srv_msg, nil } // // Outbound processing chain // func (id *Identity) BuildSimpleAckResponseMessage(uuidToAck string) (fromServerMessage *meowlib.FromServerMessage, err error) { var msg meowlib.FromServerMessage msg.ServerPublicKey = id.ServerKp.Public msg.UuidAck = uuidToAck return &msg, nil } func (id *Identity) SerializeFromServerMessage(msg *meowlib.FromServerMessage) (encodedFromServerMessage []byte, err error) { out, err := proto.Marshal(msg) if err != nil { return nil, err } return out, nil } // AsymEncryptMessage prepares a message to send to a specific peer contact func (id *Identity) AsymEncryptMessage(peerPublicKey string, Message []byte) (*meowlib.EncryptedMessage, error) { var enc *meowlib.EncryptedMessage enc, err := meowlib.AsymEncryptAndSign(peerPublicKey, id.ServerKp.Private, Message) if err != nil { fmt.Println(err.Error()) return nil, err } return enc, err } func (id *Identity) PackForSending(encryptedMessage []byte, signature []byte) (fromServerMessage []byte, err error) { var pmsg meowlib.PackedServerMessage pmsg.Payload = encryptedMessage pmsg.Signature = signature pmsg.From = id.ServerKp.Public out, err := proto.Marshal(&pmsg) if err != nil { return nil, err } return out, nil } // Outbound helper function func (id *Identity) ProcessOutbound(peerPublicKey string, msg *meowlib.FromServerMessage) (fromServerMessage []byte, err error) { encoded_srv_fromServerMessage, err := id.SerializeFromServerMessage(msg) if err != nil { return nil, err } srv_resp, err := id.AsymEncryptMessage(peerPublicKey, encoded_srv_fromServerMessage) if err != nil { return nil, err } resp, err := id.PackForSending(srv_resp.Data, srv_resp.Signature) if err != nil { return nil, err } return resp, nil }