From 49a29e43a7535099d1ba810754f26ee3c911b689 Mon Sep 17 00:00:00 2001 From: afonso Date: Tue, 28 May 2024 20:08:25 +0100 Subject: [PATCH] [PD2] Server done? Co-authored-by: tsousa111 --- Projs/PD1/internal/server/datastore.go | 4 +- Projs/PD1/internal/server/server.go | 2 - Projs/PD1/server.db | Bin 32768 -> 36864 bytes Projs/PD2/README.md | 214 ++++++++++++ Projs/PD2/certs/CA/CA.key | 54 +++ Projs/PD2/certs/CA/CA.pem | 29 ++ Projs/PD2/certs/CA/CA.srl | 1 + Projs/PD2/certs/FakeCA/CA.key | 54 +++ Projs/PD2/certs/FakeCA/CA.pem | 29 ++ Projs/PD2/certs/FakeCA/CA.srl | 1 + Projs/PD2/certs/FakeClient1/client1.crt | 30 ++ Projs/PD2/certs/FakeClient1/client1.csr | 26 ++ Projs/PD2/certs/FakeClient1/client1.key | 52 +++ Projs/PD2/certs/FakeClient1/client1.p12 | Bin 0 -> 5634 bytes Projs/PD2/certs/FakeServer/server.crt | 29 ++ Projs/PD2/certs/FakeServer/server.csr | 26 ++ Projs/PD2/certs/FakeServer/server.key | 52 +++ Projs/PD2/certs/FakeServer/server.p12 | Bin 0 -> 5616 bytes Projs/PD2/certs/FakeServer/server/server.crt | 30 ++ Projs/PD2/certs/FakeServer/server/server.csr | 27 ++ Projs/PD2/certs/FakeServer/server/server.key | 52 +++ Projs/PD2/certs/FakeServer/server/server.p12 | Bin 0 -> 5632 bytes Projs/PD2/certs/README.md | 48 +++ Projs/PD2/certs/client1/client1.crt | 30 ++ Projs/PD2/certs/client1/client1.csr | 26 ++ Projs/PD2/certs/client1/client1.key | 52 +++ Projs/PD2/certs/client1/client1.p12 | Bin 0 -> 5634 bytes Projs/PD2/certs/client2/client2.crt | 30 ++ Projs/PD2/certs/client2/client2.csr | 26 ++ Projs/PD2/certs/client2/client2.key | 52 +++ Projs/PD2/certs/client2/client2.p12 | Bin 0 -> 5634 bytes Projs/PD2/certs/client3/client3.crt | 30 ++ Projs/PD2/certs/client3/client3.csr | 26 ++ Projs/PD2/certs/client3/client3.key | 52 +++ Projs/PD2/certs/client3/client3.p12 | Bin 0 -> 5634 bytes Projs/PD2/certs/server/server.crt | 29 ++ Projs/PD2/certs/server/server.csr | 26 ++ Projs/PD2/certs/server/server.key | 52 +++ Projs/PD2/certs/server/server.p12 | Bin 0 -> 5616 bytes Projs/PD2/cmd/client/client.go | 9 + Projs/PD2/cmd/gateway/gateway.go | 9 + Projs/PD2/cmd/server/server.go | 9 + Projs/PD2/go.mod | 38 +++ Projs/PD2/go.sum | 93 +++++ Projs/PD2/internal/client/client.go | 323 ++++++++++++++++++ Projs/PD2/internal/client/datastore.go | 47 +++ Projs/PD2/internal/client/interface.go | 92 +++++ Projs/PD2/internal/gateway/gateway.go | 5 + Projs/PD2/internal/protocol/protocol.go | 119 +++++++ Projs/PD2/internal/server/datastore.go | 245 +++++++++++++ Projs/PD2/internal/server/interface.go | 14 + Projs/PD2/internal/server/server.go | 151 ++++++++ .../internal/utils/cryptoUtils/cryptoUtils.go | 283 +++++++++++++++ Projs/PD2/internal/utils/networking/client.go | 23 ++ .../internal/utils/networking/connection.go | 51 +++ Projs/PD2/internal/utils/networking/server.go | 56 +++ .../digital-envelope-diagram.drawio.png | Bin 0 -> 48257 bytes .../digital-envelope-diagram.jpg | Bin 0 -> 33942 bytes Projs/PD2/server.db | Bin 0 -> 36864 bytes Projs/PD2/tokefile.toml | 23 ++ TPs/TP02/py/cfich_aes_cbc.py | 0 TPs/TP02/py/cfich_chacha20.py | 0 TPs/TP02/py/chacha20_int_attck.py | 0 TPs/TP02/py/input.txt.enc | 1 - TPs/TP03/pbenc_aes_ctr_hmac | Bin TPs/TP03/py/plaintext.txt.enc | Bin 77 -> 0 bytes 66 files changed, 2777 insertions(+), 5 deletions(-) create mode 100644 Projs/PD2/README.md create mode 100644 Projs/PD2/certs/CA/CA.key create mode 100644 Projs/PD2/certs/CA/CA.pem create mode 100644 Projs/PD2/certs/CA/CA.srl create mode 100644 Projs/PD2/certs/FakeCA/CA.key create mode 100644 Projs/PD2/certs/FakeCA/CA.pem create mode 100644 Projs/PD2/certs/FakeCA/CA.srl create mode 100644 Projs/PD2/certs/FakeClient1/client1.crt create mode 100644 Projs/PD2/certs/FakeClient1/client1.csr create mode 100644 Projs/PD2/certs/FakeClient1/client1.key create mode 100644 Projs/PD2/certs/FakeClient1/client1.p12 create mode 100644 Projs/PD2/certs/FakeServer/server.crt create mode 100644 Projs/PD2/certs/FakeServer/server.csr create mode 100644 Projs/PD2/certs/FakeServer/server.key create mode 100644 Projs/PD2/certs/FakeServer/server.p12 create mode 100644 Projs/PD2/certs/FakeServer/server/server.crt create mode 100644 Projs/PD2/certs/FakeServer/server/server.csr create mode 100644 Projs/PD2/certs/FakeServer/server/server.key create mode 100644 Projs/PD2/certs/FakeServer/server/server.p12 create mode 100644 Projs/PD2/certs/README.md create mode 100644 Projs/PD2/certs/client1/client1.crt create mode 100644 Projs/PD2/certs/client1/client1.csr create mode 100644 Projs/PD2/certs/client1/client1.key create mode 100644 Projs/PD2/certs/client1/client1.p12 create mode 100644 Projs/PD2/certs/client2/client2.crt create mode 100644 Projs/PD2/certs/client2/client2.csr create mode 100644 Projs/PD2/certs/client2/client2.key create mode 100644 Projs/PD2/certs/client2/client2.p12 create mode 100644 Projs/PD2/certs/client3/client3.crt create mode 100644 Projs/PD2/certs/client3/client3.csr create mode 100644 Projs/PD2/certs/client3/client3.key create mode 100644 Projs/PD2/certs/client3/client3.p12 create mode 100644 Projs/PD2/certs/server/server.crt create mode 100644 Projs/PD2/certs/server/server.csr create mode 100644 Projs/PD2/certs/server/server.key create mode 100644 Projs/PD2/certs/server/server.p12 create mode 100644 Projs/PD2/cmd/client/client.go create mode 100644 Projs/PD2/cmd/gateway/gateway.go create mode 100644 Projs/PD2/cmd/server/server.go create mode 100644 Projs/PD2/go.mod create mode 100644 Projs/PD2/go.sum create mode 100644 Projs/PD2/internal/client/client.go create mode 100644 Projs/PD2/internal/client/datastore.go create mode 100644 Projs/PD2/internal/client/interface.go create mode 100644 Projs/PD2/internal/gateway/gateway.go create mode 100644 Projs/PD2/internal/protocol/protocol.go create mode 100644 Projs/PD2/internal/server/datastore.go create mode 100644 Projs/PD2/internal/server/interface.go create mode 100644 Projs/PD2/internal/server/server.go create mode 100644 Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go create mode 100644 Projs/PD2/internal/utils/networking/client.go create mode 100644 Projs/PD2/internal/utils/networking/connection.go create mode 100644 Projs/PD2/internal/utils/networking/server.go create mode 100644 Projs/PD2/report_content/digital-envelope-diagram.drawio.png create mode 100644 Projs/PD2/report_content/digital-envelope-diagram.jpg create mode 100644 Projs/PD2/server.db create mode 100644 Projs/PD2/tokefile.toml mode change 100755 => 100644 TPs/TP02/py/cfich_aes_cbc.py mode change 100755 => 100644 TPs/TP02/py/cfich_chacha20.py mode change 100755 => 100644 TPs/TP02/py/chacha20_int_attck.py delete mode 100644 TPs/TP02/py/input.txt.enc mode change 100755 => 100644 TPs/TP03/pbenc_aes_ctr_hmac delete mode 100644 TPs/TP03/py/plaintext.txt.enc diff --git a/Projs/PD1/internal/server/datastore.go b/Projs/PD1/internal/server/datastore.go index d8ace3d..0ee3b66 100644 --- a/Projs/PD1/internal/server/datastore.go +++ b/Projs/PD1/internal/server/datastore.go @@ -90,7 +90,7 @@ func (ds DataStore) GetMessage(toUID string, position int) protocol.Packet { err := row.Scan(&serverMessage.FromUID, &serverMessage.ToUID, &serverMessage.Subject, &serverMessage.Body, &serverMessage.Timestamp) if err == sql.ErrNoRows { log.Printf("No message with NUM %v for UID %v\n", position, toUID) - errorMessage := fmt.Sprintf("MSG SERVICE: unknown message!") + errorMessage := fmt.Sprintln("MSG SERVICE: unknown message!") return protocol.NewReportErrorPacket(errorMessage) } @@ -217,7 +217,7 @@ func (ds DataStore) userExists(uid string) bool { err := ds.db.QueryRow(query, uid).Scan(&count) if err != nil || count == 0 { log.Printf("user with UID %v does not exist\n", uid) - return false + return false } return true } diff --git a/Projs/PD1/internal/server/server.go b/Projs/PD1/internal/server/server.go index 54b62da..127dac0 100644 --- a/Projs/PD1/internal/server/server.go +++ b/Projs/PD1/internal/server/server.go @@ -7,8 +7,6 @@ import ( "log" ) -//TODO: LOGGING SYSTEM - func clientHandler(connection networking.Connection[protocol.Packet], dataStore DataStore) { defer connection.Conn.Close() diff --git a/Projs/PD1/server.db b/Projs/PD1/server.db index 0ec34a200ece4866ff0c12ccb80fbb3c3b17e107..c995c32148bb474d21cd8ceaa51687e88df7c3e6 100644 GIT binary patch delta 2348 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 SE{%;bR`+SFQ42{`G71H;G+deh delta 89 zcmZozz|_#dG(nnGkb!}LW1@mRqu|DbCHg!}{NI2A3>^Hw`M+&!%w*qOX|6|`}%WiZt|})008cX7McJ6 diff --git a/Projs/PD2/README.md b/Projs/PD2/README.md new file mode 100644 index 0000000..40b2122 --- /dev/null +++ b/Projs/PD2/README.md @@ -0,0 +1,214 @@ +# Relatório do Projeto de Desenvolvimento 1 + +## Introdução + +A comunicação eficaz dentro de uma organização é essencial para a eficiência do seu funcionamento. No entanto, num ambiente cada vez mais digital, garantir a segurança e autenticidade das comunicações tem-se vindo a tornar uma preocupação fundamental. Em resposta a esta necessidade, este primeiro projeto de desenvolvimento visa criar um serviço de mensagens seguro e autenticado. + +Para contextualizar o projeto, consideremos uma organização onde informações confidenciais são frequentemente trocadas entre membros de equipas distribuídas geograficamente. Neste cenário, é crucial que as mensagens enviadas e recebidas sejam protegidas contra acessos não autorizados e manipulação por partes externas. Além disso, garantir que a identidade do remetente e a integridade da mensagem sejam verificadas é essencial para manter a confiança e a segurança das comunicações internas. + +Perante estas necessidades, o projeto de desenvolvimento propõe a criação de um sistema cliente/servidor que oferece um serviço de mensagens seguro e autenticado. Através deste sistema, os membros da organização poderão trocar mensagens com garantias de autenticidade, protegendo assim a confidencialidade e integridade das comunicações. + +Ao longo deste relatório iremos detalhar as decisões mais importantes tomadas no desenvolvimento do projeto, bem como as medidas de segurança implementadas para garantir a confidencialidade, integridade e autenticidade das mensagens trocadas entre os utilizadores. + +Algumas notas sobre o projeto: + +- Optamos por escolher **Golang** como linguagem visando uma implementação mais eficiente, robusta e segura ao nível de concorrência. O modelo de concorrência baseado em goroutines e canais facilita a criação de programas concorrentes e sistemas distribuídos. Com uma sintaxe simples, semelhante a **C**, o **Go** promove a escrita de código legível e de alta qualidade. Além disso, o **Go** possui um ecossistema robusto de bibliotecas e ferramentas, tornando-o uma escolha adequada para o desenvolvimento de sistemas distribuídos e serviços de back-end. + +- Implementamos algumas funcionalidades extra, como o armazenamento dos dados no servidor numa base de dados **sqlite3** + +Nas secções seguintes iremos detalhar cada componente do sistema, bem como as funcionalidades implementadas. + + + +## Análise de Risco + +Esta análise de risco do sistema visa identificar as potenciais vulnerabilidades e ameaças que possam comprometer a segurança do sistema de mensagens. É essencial considerar os diversos fatores que podem impactar a integridade, confidencialidade e disponibilidade das mensagens trocadas entre os utilizadores. + +### Potenciais Vulnerabilidades + +1. **Comunicação Não Segura** - Se a comunicação entre os clientes e o servidor não foi cifrada, qualquer *man in the middle* consegue ler o conteúdo a ser transmitido. + +1. **Armazenamento Inseguro de Chaves Privadas** - Se as chaves privadas dos utilizadores forem armazenadas de forma inadequada, como em arquivos desprotegidos, existe o risco de acesso não autorizado, comprometendo a segurança e autenticidade das mensagens. + +1. **Autenticação Fraca** - Um sistema de autenticação vulnerável pode permitir que utilizadores mal-intencionados obtenham acesso não autorizado às contas dos utilizadores legítimos. + +1. **Manipulação de Mensagens** - A ausência de mecanismos eficazes de controlo pode facilitar a manipulação do conteúdo das mensagens durante a transmissão, comprometendo sua integridade. + +1. **Vulnerabilidades de *Software*** - Falhas de segurança no *software* desenvolvido e utilizado para implementar o sistema podem ser exploradas para obter acesso não autorizado ou comprometer a segurança dos dados. + +### Possíveis Ameaças: + +1. **Ataques de Intercetação de Dados** - Atacantes podem tentar intercetar a comunicação entre o cliente e o servidor para obter informações sensíveis, como chaves privadas ou conteúdo de mensagens. + +1. **Ataques de *Denial of Service (DOS)*** - Um ataque de *DOS* pode tornar o servidor inacessível ao sobrecarregá-lo com um grande volume de solicitações, prejudicando a disponibilidade do serviço. + +1. **Ataques de Engenharia Social:** - Atacantes podem tentar manipular os utilizadores legítimos para obter acesso às suas credenciais de acesso por meio de técnicas de engenharia social. + +1. **Exploração de Vulnerabilidades de *Software*:** - Vulnerabilidades conhecidas ou desconhecidas no *software* utilizado podem ser exploradas para comprometer a segurança do sistema. + +### Propriedades Requiridas: + +1. **Autenticidade do Remetente** - O cliente deseja ter a garantia de que a mensagem recebida foi realmente enviada pelo remetente indicado. + +1. **Confidencialidade das Mensagens** - O cliente quer assegurar que apenas ele possui a capacidade de decifrar as mensagens que lhe foram enviadas, garantindo assim a privacidade das comunicações. + +1. **Servidor Malicioso** - Os clientes pretendem proteger-se contra a possibilidade de o servidor agir de forma maliciosa, garantindo que as suas interações sejam seguras e protegidas, necessitando de mecanismos que garantam a segurança das suas interações independentemente da confiabilidade do servidor, como a utilização de criptografia *end-to-end*. + +1. **Comunicação Segura com o Servidor** - Os clientes exigem que a comunicação com o servidor seja segura, protegida contra acesso não autorizado e intercetação por partes não autorizadas, garantindo assim a integridade e confidencialidade dos dados transmitidos. + +### Medidas de Mitigação: + +1. **Protocolo de comunicação** - Utilizar um protocolo de comunicação que garanta a confidencialidade para proteger a comunicação entre o cliente e o servidor. + +1. **Armazenamento Seguro de Chaves Privadas** - Adotar práticas seguras de armazenamento para proteger as chaves privadas dos utilizadores contra acesso não autorizado, como utilizar *passphrases* para proteger o acesso à *key store*. + +1. **Fortalecimento da Autenticação** - Implementar métodos robustos de autenticação, como certificados digitais, para garantir a identidade dos utilizadores e proteger contra acesso não autorizado. + +1. **Validação de Dados** - Implementar controles de validação de dados para garantir a integridade das mensagens e prevenir a manipulação de dados por partes não autorizadas, como, por exemplo, assinar "hashes" das mensagens enviadas. + +1. **Atualizações de *Software*** - Manter o *software* utilizado atualizado para mitigar o risco de exploração de vulnerabilidades conhecidas e garantir a segurança do sistema. + +Esta breve análise de risco destaca a importância de identificar e mitigar potenciais vulnerabilidades e ameaças para garantir a segurança do sistema desenvolvido. A implementação de medidas de segurança adequadas é essencial para proteger os dados e garantir o funcionamento seguro. + + +## Decisões de Arquitetura e Implementação + +Tendo em consideração as vulnerabilidades e ameaças identificadas na análise de risco, foram tomadas várias decisões de design e implementação para garantir a segurança e autenticidade do sistema de mensagens. As decisões tomadas visam proteger a confidencialidade, integridade e autenticidade das mensagens trocadas entre os utilizadores, bem como garantir a segurança da comunicação entre o cliente e o servidor. + +1. **TLS (Transport Layer Security)** + + - Cada conexão entre cliente e servidor é protegida pelo protocolo TLS, garantindo que a comunicação seja segura e privada. + - Cliente e servidor trocam certificados para autenticar as suas identidades. + - Ambos verificam se o certificado foi emitido pela Autoridade de Certificação (CA) central. + - O cliente verifica se comunica com o servidor legítimo. + +1. **End-to-End Encryption (E2EE)** + + - Ao enviar uma mensagem, o cliente assina a *hash* do texto simples com a sua chave privada. + - A assinatura é anexada ao texto limpo e esse conjunto é cifrado com uma chave de sessão gerada aleatoriamente. + - A chave de sessão é cifrada com a chave pública do destinatário, Isso garante que apenas o destinatário possa decifrar a mensagem. + +1. **Visualização da Lista de Mensagens Não Lidas** + + - Quando um cliente solicita a sua lista de mensagens não lidas, apenas o assunto é enviado, não o conteúdo cifrado. + - O cliente deve decifrar o assunto para visualizá-lo. + +1. **Visualização de Mensagens** + + - Quando um cliente solicita uma mensagem, é enviado o conteúdo todo da mensagem. + - O cliente deve decifrar o assunto e o corpo da mensagem para visualizá-los. + +1. **Troca de Chaves Públicas** + + - Quando um cliente precisa da chave pública de outro cliente, solicita o certificado desse cliente ao servidor. + - Verifica-se se o certificado foi emitido pela CA central e se pertence ao cliente desejado. + +1. **Verificação de Inputs** + + - Tanto cliente quanto servidor realizam verificações básicas nos *inputs* para garantir a sua integridade. + - Ambos desconfiam um do outro e verificam cuidadosamente todos os *inputs*. + +1. **Confiança na CA Central** + + - A única confiança absoluta neste sistema é depositada na Autoridade de Certificação central, responsável por emitir os certificados. + + +## Certificates and Keys + +Para gerar os certificados e chaves necessárias para a comunicação segura entre o cliente e o servidor, foram seguidos os seguintes passos utilizando a ferramenta **OpenSSL**. Estes passos incluem a geração de chaves privadas, certificados e *keystores* para o servidor e clientes, bem como a assinatura dos certificados pela CA central. + + +1. **Gerar *CA key* e o *certificate*** + +```bash +openssl genrsa -aes256 -out CA/CA.key 4096 +openssl req -x509 -new -nodes -key CA/CA.key -sha256 -days 18250 -out CA/CA.pem -subj "/2.5.4.3=CA" +``` +A *passhphrase* da CA é 1234 + +2. **Gerar a *server key* e *CSR*** + +```bash +openssl genrsa -out server/server.key 4096 +openssl req -new -key server/server.key -out server/server.csr -subj "/2.5.4.11=MSG SERVICE/2.5.4.65=SERVER" +``` + +3. **Assinar o *CSR* do *server* com a *CA*** + +```bash +openssl x509 -req -in server/server.csr -CA CA/CA.pem -CAkey CA/CA.key -CAcreateserial -out server/server.crt -days 1825 -sha256 +``` + +4. **Gerar o *keystore* do *server*** + +```bash +openssl pkcs12 -export -out server/server.p12 -inkey server/server.key -in server/server.crt -certfile CA/CA.pem -name "ServerKeyStore" +``` +A passphrase usada para o *keystore* é server + +5. **Gerar as chaves e *CSR* de cada *client*** + +```bash +openssl genrsa -out client{NUM}/client{NUM}.key 4096 +openssl req -new -key client{NUM}/client{NUM}.key -out client{NUM}/client{NUM}.csr -subj "/2.5.4.11=MSG SERVICE/2.5.4.65=CL{NUM}/2.5.4.3=Client {NUM}" +``` + +6. **Assinar os *CSR* dos clientes com a *CA*** + +```bash +openssl x509 -req -in client/client.csr -CA CA/CA.pem -CAkey CA/CA.key -CAcreateserial -out client/client.crt -days 1825 -sha256 +``` +7. **Gerar o *keystore* do *client*** + +```bash +openssl pkcs12 -export -out client{NUM}/client{NUM}.p12 -inkey client{NUM}/client{NUM}.key -in client{NUM}/client{NUM}.crt -certfile CA/CA.pem -name "Client{NUM}KeyStore" +``` +A passphrase usada para o *keystore* é client{NUM} + +Neste processo, foram geradas as chaves privadas, certificados e *keystores* necessários para estabelecer uma comunicação segura entre os clientes e o servidor. Os certificados foram assinados pela Autoridade de Certificação (CA) central, garantindo a autenticidade e integridade dos certificados emitidos. Os *keystores* contêm tanto o certificado quanto a chave privada do cliente ou servidor, protegidos por *passhprase* para garantir a confidencialidade e segurança das chaves privadas. Este processo de geração de certificados e *keystores* é essencial para estabelecer uma comunicação segura e autenticada entre os componentes do sistema. + +### Certificados +- **Autenticidade**: Os certificados são assinados digitalmente pela Autoridade de Certificação (CA) central, garantindo sua autenticidade. Isso significa que os clientes podem verificar se o certificado foi emitido por uma entidade confiável. +- **Criptografia**: Os certificados contêm a chave pública do cliente ou do servidor, que é usada para estabelecer uma comunicação segura por meio de criptografia assimétrica. Isso permite que as mensagens sejam cifradas pelo remetente e decifradas apenas pelo destinatário. +- **Verificação**: Antes de confiar num certificado, os clientes verificam sua validade, incluindo a data de expiração e a correspondência com a entidade emissora. Isso ajuda a evitar a utilização de certificados inválidos ou falsificados. + +### *Keystores* +- **Armazenamento Seguro**: Os *keystores* são arquivos protegidos por *passphrase* que contêm tanto o certificado quanto a chave privada do cliente ou servidor. Essas informações sensíveis são protegidas por meio de criptografia, garantindo que apenas o proprietário autorizado possa acessá-las. +- **Proteção da Chave Privada**: A *passphrase* do *keystore* protege a chave privada contra acesso não autorizado. Isso é crucial, pois a chave privada é usada para decifrar as mensagens recebidas e assinar as mensagens enviadas, garantindo a autenticidade e integridade da comunicação. +- **Confidencialidade**: Como os *keystores* são protegidos por *passphrase*, mesmo que alguém obtenha acesso ao arquivo, não poderá extrair a chave privada sem a *passphrase* correta. Isso ajuda a manter a confidencialidade das chaves privadas dos usuários. + + +## Criptografia + +É importante destacar que, para garantir a segurança e integridade das mensagens, implementamos um protocolo de comunicação seguro. Este protocolo utiliza tanto criptografia simétrica quanto assimétrica. As mensagens são cifradas com uma chave de sessão gerada aleatoriamente, que, é cifrada com a chave pública do destinatário para garantir a confidencialidade. As mensagens são também assinadas com a chave privada do emissor para autenticidade. Dessa forma, asseguramos que as mensagens sejam protegidas contra acessos não autorizados e que a sua origem possa ser verificada. + +![Digital Envelope](report_content/digital-envelope-diagram.jpg) + + +### Networking + +O canal de comunicação estabelecido entre o cliente e o servidor nesta implementação garante uma troca de dados segura e criptografada utilizando o protocolo TLS (Transport Layer Security). Ambos, cliente e servidor, empregam configurações TLS para cifrar os dados durante a transmissão, assegurando confidencialidade e integridade. Durante o handshake TLS, o servidor valida o certificado do cliente para verificar sua autenticidade, prevenindo acessos não autorizados. Este mecanismo robusto de segurança protege o canal de comunicação contra escutas, adulterações e ataques do tipo "man in the middle", garantindo uma troca de informações segura e confiável entre o cliente e o servidor. + +### Protocolo de Comunicação + +O package **protocol.go** define um conjunto de estruturas e funções que representam os diferentes tipos de pacotes que podem ser transmitidos entre o cliente e o servidor. Cada tipo de pacote é representado por uma constante PacketType, que indica a natureza da informação contida no pacote através de uma **flag**. + +As estruturas de dados definidas, como `GetUserCert`, `GetUnreadMsgsInfo`, `GetMsg`, `SendMsg`, `AnswerGetUserCert`, `AnswerGetUnreadMsgsInfo` e `AnswerGetMsg`, descrevem os formatos específicos de cada tipo de pacote a ser enviado e recebido. Cada estrutura contém os campos necessários para armazenar e representar os dados associados a cada tipo de pacote. + +Além disso, foram implementadas funções auxiliares para criar instâncias de cada tipo de pacote, como `NewGetUserCert`, `NewGetUnreadMsgsInfo`, `NewGetMsg`, `NewSendMsg`, `NewAnswerGetUserCert`, `NewAnswerGetUnreadMsgsInfo` e `NewAnswerGetMsg`. Estas funções facilitam a criação de pacotes com os dados necessários de forma estruturada. + +Para facilitar a serialização e desserialização dos pacotes em formato JSON, foram implementadas funções `Unmarshal` específicas para cada tipo de pacote. Estas funções convertem os dados do pacote entre o formato JSON e as estruturas de dados correspondentes, permitindo a comunicação eficiente entre o cliente e o servidor. + +Este package serve como uma camada de abstração que facilita a comunicação entre os componentes cliente e servidor, garantindo que os dados sejam transmitidos de forma estruturada e *standardized*, facilitando o desenvolvimento, manutenção e expansão do sistema de comunicação. + +### Sqlite3 Database + +Como mencionado anteriormente neste relatório, uma das funcionalidades adicionais implementadas foi o armazenamento dos dados do servidor numa base de dados persistente. Neste projeto, optamos por utilizar o **SQLite3**. Este é utilizado para armazenar as mensagens enviadas e recebidas pelos utilizadores, além dos certificados digitais dos clientes. A escolha de uma base de dados permite a persistência segura e eficiente dos dados, assegurando que as mensagens e certificados sejam armazenados de maneira duradoura e acessível. + +Em relação à segurança contra ataques como *SQL Injection*, é crucial adotar medidas para mitigar esse tipo de ameaça. A utilização de *prepared statements* é uma prática essencial para prevenir ataques deste tipo. Com *prepared statements*, os valores dos parâmetros são tratados como dados e não como parte do comando SQL, o que reduz significativamente o risco de injeção de código malicioso. Essa abordagem fortalece a segurança do sistema, garantindo a integridade e confiabilidade das operações da base de dados. + + + +### Verificações e Testes de Segurança + +Para realizar testes e verificações de segurança implementamos também um *Fake Client, Server e CA*, que permitem testar a segurança do sistema em diferentes cenários, como tentativas de intercetação de dados, manipulação de mensagens, autenticação fraca e outros tipos de ataques. diff --git a/Projs/PD2/certs/CA/CA.key b/Projs/PD2/certs/CA/CA.key new file mode 100644 index 0000000..1b522db --- /dev/null +++ b/Projs/PD2/certs/CA/CA.key @@ -0,0 +1,54 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/Projs/PD2/certs/CA/CA.pem b/Projs/PD2/certs/CA/CA.pem new file mode 100644 index 0000000..c656bc1 --- /dev/null +++ b/Projs/PD2/certs/CA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE/TCCAuWgAwIBAgIUeu0iePpZFCl6i+Ox7QbXywinn+wwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwIBcNMjQwNDE5MDAyMDE5WhgPMjA3NDA0MDcwMDIw +MTlaMA0xCzAJBgNVBAMMAkNBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEAv7oZ8bld3ImFrkmRf28EbkFZ3xv2FxJP8+eqv8qufKeYyEm9VEzAM7kpsaIG +OoEC5yBOVQ4uhC8aCcknm9OU/m5IFfMGAXwj9cWee9KZZM5ma2W/rvO3z6JcBTP6 +mEuQZI8GVST5RqDzEhDZSujerN9/SaHnCwqPshUUbft/yMF0oHyEhmpNg+0Uu8WF +4ck0W9rlBS+z+PfMy2Y7iTM9o21q2fPRbXDxoDSCebMN8NiB9/RK/kAcRZqTYd+u +LsIx61nTphhk4uNs7PQ82ABXhQTKnU1svTVInjQfYDAypr5cPMwut1TSieCBS7/N +Xaod/b2voKZihqQ1yYWwdanj7QarySK6MC/JAoLlq4KE6/YL2788k+eu7cP6v4Yf +k2o2IPA4/9LcZ4nMLmKszamw5OZmyzGtYifE2wvabileitn06oiutMIdm9EUthrs +/6h/OkILQeh6tOuy3NqSj1rf0rs62/OC3k3BWf/WFwqLileCpxwQZXOWiXFznuvP +0T9QxCFj3HacdhiXo4oejpIlGnclBSZ7B96dR7xGAaXoOL8EatYVZGB8LKpx8H3/ +vgehVevNRz2/WvYfJATnvaakM+i/TYhX027Exi+LvdyMH4C1xRiqDvC3kYzZwakN +1ZCpz6fYmhWNqW0rzu3ePRpYHSGC0hq1WTRfHaQvAVMJiUcCAwEAAaNTMFEwHQYD +VR0OBBYEFMVE1jz77WweC8ao7bVYxujCdbDRMB8GA1UdIwQYMBaAFMVE1jz77Wwe +C8ao7bVYxujCdbDRMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB +AI7KNfTFRFCdLIxDkVzG6/FZx5ue++xGMdxwrVX8sX2mib9yMaAMbj3TPX0f/PDD +avUBK5pgNi9cV/GsXw0vnrJ9R9Ou5pYJ+NeaQZoO+YTHDnqJL7Ro3Q1BcRG8S+Q6 ++YwoiXzghLebq7r81yhQXeS3Ax7SHlz+rXoDQJFSdDBPMJSFgJs2YPTRDPNEveW2 +wvFAdIK5KzB2gaeQRT/vix4jFasXUogRpLXWCDFJFYPd0iaTrzP1K1mDTHDD/pFB +R3AnMxWp3Plxxr/jO6Djb0GgRjp5q4uoZAYpwZfE70M9jafqoA20t2Rxtorj+SA0 ++o2uG72ssTbw5cfQy+uBnQiUghvsw3U4D62d+IxW9gtbOBGES4TIflKsUnJ36RKx +EQaPYJ6VhgBDyGoqBmANjfV4u3Jz7IlxQyeA0JzhuOSfenQaRQzjvaj/4SlYYfhm +tKgEuQf6XaiXa/PWKIwwT49TZ7ZQB+g1xTD43s9PZ883byZPEolLe12cvJ918jQf +/8VFLCHCuV+k+g8FIt/dOgalHmM1hh8uzqiIk1Rtp8YPsuUNO4ZeHQ+ANGO1WqXx +GYNa4Unhuz3+VNxbctAaSNExvzwYIqEdNdZjxOYw09fOYQUkYDN+7gB90GCstCsJ +10KMhfRQQm3Fq8CtnOomgUmgcawPDuFOThLuU4m1dkcT +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/CA/CA.srl b/Projs/PD2/certs/CA/CA.srl new file mode 100644 index 0000000..ce4190e --- /dev/null +++ b/Projs/PD2/certs/CA/CA.srl @@ -0,0 +1 @@ +7C475B59D1510F54E042BF4BFDBE811BF4EDAF37 diff --git a/Projs/PD2/certs/FakeCA/CA.key b/Projs/PD2/certs/FakeCA/CA.key new file mode 100644 index 0000000..2262576 --- /dev/null +++ b/Projs/PD2/certs/FakeCA/CA.key @@ -0,0 +1,54 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/Projs/PD2/certs/FakeCA/CA.pem b/Projs/PD2/certs/FakeCA/CA.pem new file mode 100644 index 0000000..027e942 --- /dev/null +++ b/Projs/PD2/certs/FakeCA/CA.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE/TCCAuWgAwIBAgIUNae6TxoDs5d/kuQMGrNstWsNYCUwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwIBcNMjQwNDE5MDAyNTAzWhgPMjA3NDA0MDcwMDI1 +MDNaMA0xCzAJBgNVBAMMAkNBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC +AgEAuYf0lxxLL6o2XkvhyAH5v454URbhRS1s4K0U2F31wY5DpmveKI2/amRuvNUD +URMV5VB+REWSMMJmY4bxqJ6CxqBeKNE/RXTb30N3XDyZ5tqKb/R4GnvHXZ0QE6xx +Gar0ao50/K4pcZmUjhVk2pLoBp+ffGym8ZKBkODDMzVjwEq/pWgcBJK6qe1N/Dyj +qurysdc+xklV7hJhTU88/lVUe5cvXzD1JSVCsJlkZWlftQ7ARmyPTpAi+yI+R0V5 +ivCBvMgHvfxmzrBQbMX2JrM52wuQFN+ORCSrhIjUUr4s8lKiIqbwdqBLwMREWcfA +/uUGz0iZCQN2qcScQer3vLsw36u1xbnuVSs+pLgZ9RRzjRCuBs8P4xUqpmagqDov +itB8v65C0s0KOmBlyUKyS3SH9jx5efTAvy4f4HTmyGoTBV+ioitgE9gcCSn1tvXd +c/vyxUQfGCa15ILrbI/QFvbaFyqUVfsVbP/VtugaGd+3asrS/9nLiyAkXYTePOBp +e2UvHVbBwQoCawEycthq1cUBMBe5OPmMr20A08OTNLsHa8/tFfN2+3Kv+Ri13AX2 +NMFy+U5bJV0+WMF8vu0dIXRVajNu/PmclcsZLQ11bvUI+x+JemNpaVvojXqpI/KN +PdLo37OeGOtm1uskc96n2fjurPJTBVfmmJ+L5eGC5mODkPUCAwEAAaNTMFEwHQYD +VR0OBBYEFNVmKiwSu16jTsYiNfN2oyxpsY9tMB8GA1UdIwQYMBaAFNVmKiwSu16j +TsYiNfN2oyxpsY9tMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIB +AHCnrPuTW2NNuQRgwOFSp+llH0Jn4dbCl1IDYzmr6nZBtxWaWr/NxKq6SLY4btF+ +6C/TAwHw5etmdmzSI/9J/3fEf5C1xvWbDbzDu5W+/pZZ2KPDnPeqnDj9OzMhliEA +SgHKnwg7cBMaRRRiJJcDKUlj9zzHu5loAhwmHRkhvXmQFeEiDmacjU0Xhk9RiObJ +9i+LVFiCHupJ/iIusk+PpKoBtbWdkFHhPvb7xEvLRrM82/fK0jMkJsnYGK6aNsUH +qnqgZHa/3RP6zZStqE3FggsWHv2iC1NX0joMgg6lo/716SlyzL4ZdsPJWAhx5jNf +qTT3doBBZ4OMoKsbQL4UTO8yINzRY/1G7bVDrYl7VOI0XgKfqYsrSsIQgCr7gj4W +IM7Kyib7VOgooCvanxvZg1awIWMqiiGeG895kvtf4SkQkAMgfpE95lR2B6Ziz86J +AS/MKXbUtEAP7pr29svLHPv9IKqsXWrMdSVsDT3jkb0IYmm936vXDfmj/sLgfa03 +GgIq8qhpNML/5b0sX7UqDGVXO2lxtCDrlRTiViwqyEsmfMNHOCyO43AwZTnRbO/0 +jJFaB6zUsRKQrBUyIB2ZYdMbHarJHGahtiN2YT6cf8vKqvj56gpbaRq4EDYAnNqj +vO7rjSuTrXhevYHYUI/9qlMl00iz829IR5ixaa4k1sk4 +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/FakeCA/CA.srl b/Projs/PD2/certs/FakeCA/CA.srl new file mode 100644 index 0000000..cae53a9 --- /dev/null +++ b/Projs/PD2/certs/FakeCA/CA.srl @@ -0,0 +1 @@ +7F4C6BBD8E095E37521D85095EBE463D9916EFB7 diff --git a/Projs/PD2/certs/FakeClient1/client1.crt b/Projs/PD2/certs/FakeClient1/client1.crt new file mode 100644 index 0000000..58148c0 --- /dev/null +++ b/Projs/PD2/certs/FakeClient1/client1.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFDCCAvygAwIBAgIUf0xrvY4JXjdSHYUJXr5GPZkW77cwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwHhcNMjQwNDE5MDAyNTE3WhcNMjkwNDE4MDAyNTE3 +WjA3MRQwEgYDVQQLDAtNU0cgU0VSVklDRTEMMAoGA1UEQQwDQ0wxMREwDwYDVQQD +DAhDbGllbnQgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMw0zgbG +HdyiHu8ktYTH1BvdbhC5ml4MC9SEfTtCK4PGo4bUIQvjM3hYBu90tH8/6Jzx4dJ8 +AvWFDUnQJ6bkUFLLA7TivggBMQM6lbsX1Aqd4XO3+U31O3GJRyC5ikqv/JHSSKbP +HE2jbUUR3StJqKMVLmTxVkLsU+USDEj3+dRMST/IHIIL+hrO7mMsI7XzjMQELAUi +GCF6Em+CuitpNr3mMQhOMpA0ggM1D5vtzale4WYcj4sEo+9GSBKRwVBqhxKM/3Kn +1yY8G399RLqQAX+tHmb2jNnKwUm3oblqLqxaqvaRUv0HRcvMuKdQjWki+lwJE1Fd +OintXOGoFx7fRF4v3kAdLFDF4jXV7roBCWchWNKFTBWHP3Fu4MnI3whO8ixRyWid +FQS8mdEpEnjLeRohmX1PQ84x5Ln1EhhC/laJlfMr3koxrQEtYd2CHYm2y+L0ms9s +SVIQrSkhjYvFFckB60sQ6EAx8+BlJ0W5AcHOhGUZ+3uWN2SgWaCQon01ArV/sIT4 +YFg31RB0ikL10HnpHrUZZbhZJDp8RT2lp3QdXonY3M9gap/K5UFW+0fVER1UrBXk +DGDkbvAMLFCAmUnbFgFZ4DOYoK3L29z8XomfhFP/J4OP8a/LrPrP8XFb1UtYey9J +ceTb7pJjbPD21KdBmbKtCeI/Y9xCC6OhE2ZZAgMBAAGjQjBAMB0GA1UdDgQWBBQj +r4/kiltPFckuHavkpQM+dkvY1DAfBgNVHSMEGDAWgBTVZiosErteo07GIjXzdqMs +abGPbTANBgkqhkiG9w0BAQsFAAOCAgEAJKTSFdUCVPDTgUC0x5gVKn8f+sYVkmga +fQwkEL8+E0fDul0Wa6vc9B4qLzRlpiY1TXSBVzI3M/Hpx9ffchHf80CBKvprdWaa +PO7GnTFsLueT0F74BQhk+64xeQjEGpooJCX6dxeAkSbPuLThs5zC7oRb02uLH0oY +mNgZ1MRfw2uDWLwODgkIrYZjzG2MV2nRRY0XWkiYBQFHAIqpklGN2LggwtADWVOl +baFVWQ8JVw1agrUnXpIybIhXoKGZQwM3H66XdVUoyORX647rr3kq6By/oPvkZXoM +gmJb2qO5ruiCw/KTw1BGG+OxXU0xPPBAj7qddb7foAdvHPvEGArRa+Pbc1nOF4O4 +2TDLfcsSp/dDL3AgRuXhcLaUeIgbaKZiLLQHL1Tgtt1BO0Qhc8SibnWIprS5itqv +SmIodC5Vly1s2cefA+xwex9qAqmnHI1lKwZ1Aq6wqm7AP2YzJ6/uGN46wSZghfLv +Gzzxd3qHnISvRzY7/2AbA2H7QpgWuJlQRznUPJ4gcTD2HZpoQBcqNBApwtA/aKUh +jVTTG84fGvsmOG1zZiWxR8jdaU6iszh+u1Vn5rCa3wuIVoNNQkwJXUH7tEfeulwp +7xr1nN9k9IrieB6MQ1Mmg2GDYPQHWx3HV/j46adye0GMap4mMEYm1vN0ZV4hw/yv +z1Oh6ifZdsQ= +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/FakeClient1/client1.csr b/Projs/PD2/certs/FakeClient1/client1.csr new file mode 100644 index 0000000..1ac8ead --- /dev/null +++ b/Projs/PD2/certs/FakeClient1/client1.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEfDCCAmQCAQAwNzEUMBIGA1UECwwLTVNHIFNFUlZJQ0UxDDAKBgNVBEEMA0NM +MTERMA8GA1UEAwwIQ2xpZW50IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDMNM4Gxh3coh7vJLWEx9Qb3W4QuZpeDAvUhH07QiuDxqOG1CEL4zN4WAbv +dLR/P+ic8eHSfAL1hQ1J0Cem5FBSywO04r4IATEDOpW7F9QKneFzt/lN9TtxiUcg +uYpKr/yR0kimzxxNo21FEd0rSaijFS5k8VZC7FPlEgxI9/nUTEk/yByCC/oazu5j +LCO184zEBCwFIhghehJvgroraTa95jEITjKQNIIDNQ+b7c2pXuFmHI+LBKPvRkgS +kcFQaocSjP9yp9cmPBt/fUS6kAF/rR5m9ozZysFJt6G5ai6sWqr2kVL9B0XLzLin +UI1pIvpcCRNRXTop7VzhqBce30ReL95AHSxQxeI11e66AQlnIVjShUwVhz9xbuDJ +yN8ITvIsUclonRUEvJnRKRJ4y3kaIZl9T0POMeS59RIYQv5WiZXzK95KMa0BLWHd +gh2Jtsvi9JrPbElSEK0pIY2LxRXJAetLEOhAMfPgZSdFuQHBzoRlGft7ljdkoFmg +kKJ9NQK1f7CE+GBYN9UQdIpC9dB56R61GWW4WSQ6fEU9pad0HV6J2NzPYGqfyuVB +VvtH1REdVKwV5Axg5G7wDCxQgJlJ2xYBWeAzmKCty9vc/F6Jn4RT/yeDj/Gvy6z6 +z/FxW9VLWHsvSXHk2+6SY2zw9tSnQZmyrQniP2PcQgujoRNmWQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggIBAKkdNU5DjB7stz9pVaU7fee9l4c7V0Qzcsk3ZHAtWR7h +DtP8c44d0Dk4Gb8YIgHcBH8x8RNYjWDUui74H5klhahWtuyaUXF8wh1KgFZ9qr05 +xlZ0al6wBRlDclWZNciCDAyDzk9NYHeV6vIsNvlZcf9rdAxdfNdx1ufQno6yhcvW +xeJBy6TE+6xfj0YMagTCRQ3hXH/75BbMalgJmuAXoy1XhTISSOqwzm4AGbOhxwLB +aeaj5YsSYvliZP8lSMfak4OMN3yqmS++q2G1si2KIXYRN+v3sFPjdKnfwBWc99nH +4NyoKg/lWR4Bd4wmVESjAnS3YdtZ64L+XRGn+y2kdQPFBCEetnSY7qdOYBWvsHAc +4qYtmbMEmOr029s+c5qeSsA1+3lb98bpnaDPMIpltIK9ZNbGJ0vB+Y4rzGpHyGzu +D6bnuNRpB9e1+3nfY8W4WgQlt3wAtmtJ+3sG0VvHkIhADE2bkcreSvSJDc8J8gnc +EmgdlhBvjbaTdjbfbH6YZ/4+2QOQf7k/h00lnc7VqBXT9ly7TN7gvRWCVQdod2NS +3NjOTAocLRgZNzMFFGScbs6+UtpO0ySaWMUyyAs+TukDSbtEQIQQkKEbCJF1V1zH +FXEw7Ex1VXL8zkO72/BovMQRurSd1Jeaqy5nf7EgHDSA45Tuj5XlTnuYuy8TzwTO +-----END CERTIFICATE REQUEST----- diff --git a/Projs/PD2/certs/FakeClient1/client1.key b/Projs/PD2/certs/FakeClient1/client1.key new file mode 100644 index 0000000..0ba254a --- /dev/null +++ b/Projs/PD2/certs/FakeClient1/client1.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +nlSNqNapuhs7gJb7GzcRetc4RG/EJUE= +-----END PRIVATE KEY----- diff --git a/Projs/PD2/certs/FakeClient1/client1.p12 b/Projs/PD2/certs/FakeClient1/client1.p12 new file mode 100644 index 0000000000000000000000000000000000000000..35c8aa848db2e369d45e0f2666bc241327775241 GIT binary patch literal 5634 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 J2l+1<{s#uvqyYc` literal 0 HcmV?d00001 diff --git a/Projs/PD2/certs/FakeServer/server.crt b/Projs/PD2/certs/FakeServer/server.crt new file mode 100644 index 0000000..74e7f40 --- /dev/null +++ b/Projs/PD2/certs/FakeServer/server.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFBDCCAuygAwIBAgIUf0xrvY4JXjdSHYUJXr5GPZkW77YwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwHhcNMjQwNDE5MDAyNTAzWhcNMjkwNDE4MDAyNTAz +WjAnMRQwEgYDVQQLDAtNU0cgU0VSVklDRTEPMA0GA1UEQQwGU0VSVkVSMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo9N5whjSzDHjlxb0q/AjYRljsT90 +CFSUc84rvYmkgaHAtOQ0YjGuLXbjCeKgmk3qfg282T3qiVtZsjYZ5fzFON/q2pNu +tchfg7I327iKTMKb1EKbgTxXCNen6gZuHp1QxkedaKphZ/RT/Mk/MU2h+jyhdvPS +r1syVAae3M+u8/WAoliR/Utt2zXRbYv64fVnKgbilBtu364Pmr5bedkc70LX5DuJ +UIvYmn76SpFXLfTMF7NgfkuvZTJxIThncd4dXKgdXdGbmtLUsWJrjl2nBnbE0ir7 +U8h9pi20LkZFAZLwGi8dAT7unObwwbtJojEezWu3esbh1TEKIfZRR2vY/xJLsLcn +FB1wZr0rq3my1B4IMnnQIIIfS+isNYLyUxBM6cZJxcLfW7FBP3n5ut4fnHjgq+dL +rO25qX6o6PAs5j3+/Bjs/c4NhYhhKd59fHbRbrE6YV6XX85RgLgPf6lKbazDGaDg +aX6BD8/gxjZXs80eN+nEVfyUS+VDlwI8QxRpIAs6s3FJ8g84qqo3Bi45cjQRUcl3 +0TE/AlayKAK+BP22XMZfCO1LN8KSO/1mUXlbj1eWJkCuiJmY1NaQyid2NLWtWtc8 +QwS34Qs7OmGYaKm7FvDhflOmPuj3jgreNmXUQCPZmkEwXj15sr/hgkgv7DOXkqtH +Pv76HGbZjLD1ywcCAwEAAaNCMEAwHQYDVR0OBBYEFOitNMCTz/jVd9CIPHAlpD9D +VomhMB8GA1UdIwQYMBaAFNVmKiwSu16jTsYiNfN2oyxpsY9tMA0GCSqGSIb3DQEB +CwUAA4ICAQB0YDLjCyueHMq/HemqJhqcWLmccyPzNYuGxDTbDp6Rz3pfuSi2+UBz +oz9swcBer+3dbcxlOD05g/SReiyT2J15YZnsWd49ul1MYDQvi6YpnGP8OG3jT8E2 +YTH55nWaAGpM6POdhmeEdSYC3sb13GArKHJAJqbumrdXUm3kjQwPrFrfsqWo3FGl +cjl2+2XXcfS388KYfw9XuacAeKrtBNpGuLVzvNvOWqo5YWfsgWnS6VI5x7gKcjrJ +sIFv3E3y6VR3TLG5D2GsHE9gS3TeMSaYtySl+NzlmfUaUBYdLyz6gPbO2ph9WdzO +0bVAtpZef6nuIBpWuVxOKTfgZKVPJly61iJZC2vFfKUUXduRbmhdcCWfKIw/VGeD +sX12oSMo2RvOBi6GMYj9z/1ZuzVPGm3muFYVtGfCr6ggbKHTnsQj+qwCnWrPQsub +olrascGR2mYXO5Tn+j1KswJElwZJvz/jvATxCVwITtn9K6yqwLAHJ8ZtlQzzDV4s +WcasX1msLGDZsJ9zwT1e6hudoGe1G58Bd2JKC73ZWqMJZVk9mTElfwZxcn7yMCv+ +jL+RvWjPMrKQ50b/odpo1/y8PSS4Es4v39YKNzkfQ2FAOtZo3+2tKz+tN3Qqli0/ +V3PQ3IzTk+WDwLgzzSxohNYl7GC75c4EC1qx+bGM/ryj6VIXjWBWxQ== +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/FakeServer/server.csr b/Projs/PD2/certs/FakeServer/server.csr new file mode 100644 index 0000000..4f6a5e8 --- /dev/null +++ b/Projs/PD2/certs/FakeServer/server.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEbDCCAlQCAQAwJzEUMBIGA1UECwwLTVNHIFNFUlZJQ0UxDzANBgNVBEEMBlNF +UlZFUjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKPTecIY0swx45cW +9KvwI2EZY7E/dAhUlHPOK72JpIGhwLTkNGIxri124wnioJpN6n4NvNk96olbWbI2 +GeX8xTjf6tqTbrXIX4OyN9u4ikzCm9RCm4E8VwjXp+oGbh6dUMZHnWiqYWf0U/zJ +PzFNofo8oXbz0q9bMlQGntzPrvP1gKJYkf1Lbds10W2L+uH1ZyoG4pQbbt+uD5q+ +W3nZHO9C1+Q7iVCL2Jp++kqRVy30zBezYH5Lr2UycSE4Z3HeHVyoHV3Rm5rS1LFi +a45dpwZ2xNIq+1PIfaYttC5GRQGS8BovHQE+7pzm8MG7SaIxHs1rt3rG4dUxCiH2 +UUdr2P8SS7C3JxQdcGa9K6t5stQeCDJ50CCCH0vorDWC8lMQTOnGScXC31uxQT95 ++breH5x44KvnS6ztual+qOjwLOY9/vwY7P3ODYWIYSnefXx20W6xOmFel1/OUYC4 +D3+pSm2swxmg4Gl+gQ/P4MY2V7PNHjfpxFX8lEvlQ5cCPEMUaSALOrNxSfIPOKqq +NwYuOXI0EVHJd9ExPwJWsigCvgT9tlzGXwjtSzfCkjv9ZlF5W49XliZAroiZmNTW +kMondjS1rVrXPEMEt+ELOzphmGipuxbw4X5Tpj7o944K3jZl1EAj2ZpBMF49ebK/ +4YJIL+wzl5KrRz7++hxm2Yyw9csHAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA +eYzSOqlm8wzB76yDNwIxzam0Kpufzn6FlrgE0Wj2DmpvbCXT3jzApaSUXCbBqEe9 +9iMqQ7jHvVc8bpZa2KXSYYWsq4RShraReAJG8FA+vuILVCKbwN6lDETvt0Ik/5kI +shNH8nYqdcmnuvMJrgeAzU+BBrguAXQN6IL3FX+yvAph/MHcLA+VZB+Mfpf6HJ7w +pmRc+6B919llu8JR6DewXbqaxFd6bhYQafeHAARYXvP83Qk78Qdg472zURoWaDsr +s8Y1rYL79Mc6CHPm9CdTxwIHl7U4qqAzuW6wOJzXDEr9/N4ujBISeE/b0Rlr1KPP +u+FnCk45KZb52lYDvIzZbtUxfLlWRWFix/1n/5x5JpJXThIWPV3GscOoWFraBkNe +4GbfXcl+TY6HHyf5ghL16cHNp7417tB0n6HezB+5tvHobfx9/TKMHckBdnj8ZcPN +df1nDdEleImzbVTBEI4kne0PvdvanbFNMKUPQ4UXWbLyIYNWH1376xOIS0TOVqZz +UDPpIZrFEidJzrVODyj8Miwxq+c/CekReyeaVhCDZBlQ2ek2GtK78GpkC2ACGd+J +I5E5IcLaDMg2nB4FwDHvgjwilXZdTqwSyQFkVLLV+gE/meSSfN52v7NgxFGMaR26 +4UtJ68JWEkj56wzRrInMzOoMUUgm+Pm4Mk2c4BcdmIY= +-----END CERTIFICATE REQUEST----- diff --git a/Projs/PD2/certs/FakeServer/server.key b/Projs/PD2/certs/FakeServer/server.key new file mode 100644 index 0000000..3923655 --- /dev/null +++ b/Projs/PD2/certs/FakeServer/server.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +F+3k0JHCVQEeL4cEA/KpAw6UnU2d6w== +-----END PRIVATE KEY----- diff --git a/Projs/PD2/certs/FakeServer/server.p12 b/Projs/PD2/certs/FakeServer/server.p12 new file mode 100644 index 0000000000000000000000000000000000000000..ce1d36c81c4f9d44fd57765b1abc72301ea69bea GIT binary patch literal 5616 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 C9h8Fr literal 0 HcmV?d00001 diff --git a/Projs/PD2/certs/README.md b/Projs/PD2/certs/README.md new file mode 100644 index 0000000..900385d --- /dev/null +++ b/Projs/PD2/certs/README.md @@ -0,0 +1,48 @@ +# Generating keys + +1. Generate CA key and certificate: + +```bash +openssl genrsa -aes256 -out CA/CA.key 4096 +openssl req -x509 -new -nodes -key CA/CA.key -sha256 -days 18250 -out CA/CA.pem -subj "/2.5.4.3=CA" +``` +The CA passphrase is 1234 + +2. Generate server key and CSR: + +```bash +openssl genrsa -out server/server.key 4096 +openssl req -new -key server/server.key -out server/server.csr -subj "/2.5.4.11=MSG SERVICE/2.5.4.65=SERVER" +``` + +3. Sign the server CSR with CA: + +```bash +openssl x509 -req -in server/server.csr -CA CA/CA.pem -CAkey CA/CA.key -CAcreateserial -out server/server.crt -days 1825 -sha256 +``` + +4. Generate the server's keystore: + +```bash +openssl pkcs12 -export -out server/server.p12 -inkey server/server.key -in server/server.crt -certfile CA/CA.pem -name "ServerKeyStore" +``` +The passphrase used for the keystore is server + +5. Generate each client's key and CSR: + +```bash +openssl genrsa -out client{NUM}/client{NUM}.key 4096 +openssl req -new -key client{NUM}/client{NUM}.key -out client{NUM}/client{NUM}.csr -subj "/2.5.4.11=MSG SERVICE/2.5.4.65=CL{NUM}/2.5.4.3=Client {NUM}" +``` + +6. Sign the client CSR with CA: + +```bash +openssl x509 -req -in client/client.csr -CA CA/CA.pem -CAkey CA/CA.key -CAcreateserial -out client/client.crt -days 1825 -sha256 +``` +7. Generate the client's keystore: + +```bash +openssl pkcs12 -export -out client{NUM}/client{NUM}.p12 -inkey client{NUM}/client{NUM}.key -in client{NUM}/client{NUM}.crt -certfile CA/CA.pem -name "Client{NUM}KeyStore" +``` +The passphrase used for the keystore is client{NUM} diff --git a/Projs/PD2/certs/client1/client1.crt b/Projs/PD2/certs/client1/client1.crt new file mode 100644 index 0000000..783ba54 --- /dev/null +++ b/Projs/PD2/certs/client1/client1.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFDCCAvygAwIBAgIUfEdbWdFRD1TgQr9L/b6BG/TtrzUwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwHhcNMjQwNDE5MDAyMDI4WhcNMjkwNDE4MDAyMDI4 +WjA3MRQwEgYDVQQLDAtNU0cgU0VSVklDRTEMMAoGA1UEQQwDQ0wxMREwDwYDVQQD +DAhDbGllbnQgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKPqlFVk +jPsXRitfIlY10cfUH4Dd3E4i+lL+AuiTP49BWpYPa6Z0lXlcNnR4vpxhVbZyraHP +qlg+/THqi7KQzQkeNxh+ep5IXguBPsWksOsB/LePS++bvtkYMIB4LA8K0HmUcoZA +3hgblK3fDiSh4e4shNHKNyef079Va7Fww9hIwAk1vTylNqvmbtHEF7rvbQGYjsmh +TbFO8dOToI2lNcx0M8q3v2D+ht2NKJfAD3EA1Zqd52/HqABiSmG/6cD624qE9+Vf +uoxoXsx3fGYtnwFE29Ia2b/MZPTgq9MUTwr15iZLhKmZ7pl1/7yVGzulPkaNUutm +zYv4lv76KeMax4PlTwWk6PnnjZewCJMZFLrlUvW071elitkVhC9iMewa0WuczkUL +Te0REYWDPAhIIuCGRpt74HRiWxq5sq9q50w5NIKpgE0WEKahoNz7xpLwUNP514jZ +Tx9rAxHk2xzGn2xuoNoW+WROWuyYizozgaxhqNqEt6UXOk5ptcQ4v76KxcNeZ+iA +cKydGzEm377NLoGlPe1eRhQVXZ3sKRZS7+Wlr1gMP+gQGDfMNetk3LP0P5nZ82eN +dep74VwjX4ZPOrUhQ9IT0VpKmxpRo+Z82eupr+aVJr+5gvrIrSFAzG56iguz0vYr +t3NoT3i5BC04W82XcR3MejDXs0iPsp0HlEK1AgMBAAGjQjBAMB0GA1UdDgQWBBRJ +MH7dvIzSSdQerDiVwC7aAtfMOTAfBgNVHSMEGDAWgBTFRNY8++1sHgvGqO21WMbo +wnWw0TANBgkqhkiG9w0BAQsFAAOCAgEALD+u8ieLA9tcZVoX9rhfOxXoqxxvRzKi +rHkHV1Oa0Ju6T/mnvkFafwjOUGHo1prTW6MyL1re1l1xVJmgas9RigsbztBl/5n5 +l/5RCK+kjgABH/jutJhHaU6CHxhyuzeQUzCuYtALOMWzRVm53P5mQXuFhwGxB64o +oDfyMoYn44Jjpb/dWkY+k49vprXwfaMf+JtzeOSAeqfqt6AHKoNRb1fVc3E132k+ +hBTnhYgDjquQNJOhKKkACAwMPTtC21F+MObRx9CxJRR78y5jF82YsTdzKtWwliCC +j6A3Wl3TzVpiNc6ifsnqGA/49UKOh108gt8+yJx9fQFduzaPt7mV19zTSoqq3Q9/ +2awep4ObDwUY3jqFLXYBPcr27fh7ygHFTqbFieK0nH52IMv3ZxRs94wBbmHykxPq +3ka+XryMVc9Ld+P9AIHeMyXdkqGNP0SrkolSfgNigO/l/NSdcn4qibduZG9IlUys +S1JztvWHjrYYeE4he7eVz2BdKpjmAJtaM1zWytyCYVXqUrbw+wN0JC75LD3bcW8J +cjK1IcsQSrFeLiwtfrQp8K2Saxa43t3D6iCceji+8tV3YTrIfi85F3sq+Crrej3a +vtRJAiSKH3UKk9TBv/MvHrMkkTyId8HSdngRcj4KqBahluoo9lPDQGwaXfXAeSI1 +xNijtO4t6eM= +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/client1/client1.csr b/Projs/PD2/certs/client1/client1.csr new file mode 100644 index 0000000..1c6f632 --- /dev/null +++ b/Projs/PD2/certs/client1/client1.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEfDCCAmQCAQAwNzEUMBIGA1UECwwLTVNHIFNFUlZJQ0UxDDAKBgNVBEEMA0NM +MTERMA8GA1UEAwwIQ2xpZW50IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCj6pRVZIz7F0YrXyJWNdHH1B+A3dxOIvpS/gLokz+PQVqWD2umdJV5XDZ0 +eL6cYVW2cq2hz6pYPv0x6ouykM0JHjcYfnqeSF4LgT7FpLDrAfy3j0vvm77ZGDCA +eCwPCtB5lHKGQN4YG5St3w4koeHuLITRyjcnn9O/VWuxcMPYSMAJNb08pTar5m7R +xBe6720BmI7JoU2xTvHTk6CNpTXMdDPKt79g/obdjSiXwA9xANWanedvx6gAYkph +v+nA+tuKhPflX7qMaF7Md3xmLZ8BRNvSGtm/zGT04KvTFE8K9eYmS4Spme6Zdf+8 +lRs7pT5GjVLrZs2L+Jb++injGseD5U8FpOj5542XsAiTGRS65VL1tO9XpYrZFYQv +YjHsGtFrnM5FC03tERGFgzwISCLghkabe+B0YlsaubKvaudMOTSCqYBNFhCmoaDc ++8aS8FDT+deI2U8fawMR5Nscxp9sbqDaFvlkTlrsmIs6M4GsYajahLelFzpOabXE +OL++isXDXmfogHCsnRsxJt++zS6BpT3tXkYUFV2d7CkWUu/lpa9YDD/oEBg3zDXr +ZNyz9D+Z2fNnjXXqe+FcI1+GTzq1IUPSE9FaSpsaUaPmfNnrqa/mlSa/uYL6yK0h +QMxueooLs9L2K7dzaE94uQQtOFvNl3EdzHow17NIj7KdB5RCtQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggIBAATwXmX8jOpyPeH6PiC0pXo06CGpBtEXkcNeBt2qWway +XKa83AJ8jZxE0GBuFtqLYW4snI1IleEfhWQKEweVXYoBWeWfWj8EeGOx3+ow35Cg +IkSNJ96zl63L1N3DURqHfU0gCHB2/kY4h6XjawOolQtOPShPEW4oB8jj2txmgmzR +Cd74KzACymNdS+LzSFDp9rZkWWOZS6XOaqZ47DndveYc8GvdubsChZbUApnHOWw4 +IYcqRAaMGOXVKino9RTp/3TLUSyIVdxJKSzBqEKFRAgElns5bixCtr1PpnpCyE3h +mCtU4It9nqZU2zi++elgun4yIHLvZW5bZtyKJvQhgSKoX24fx/YzZUY4doMcsttD +I6FiWLyxuX0qMUpwMoz156yFhLFisFm+Xz14KhIJ2ZFxWKkAz8LqV9qS1JHFiwax +wiR9qXHwBtCPneQFLjdR4Thk9f1bFJC0xXPMbWOPch8+FRlN/1dhxqmgfYNEw8sB +Y94QtwmGplrjgatWE7J+Hy1NR9Q9UHhTxB4mEQ6sp5OoRtHl1qVBW+Y7Tbsg0Fp8 +U+dPvR17o7KA4GlHGC4O+lN0u2tZyg+RAz/SdSBMppjkMbN0WFtBRMaDjJc0dT9t +fmPSVBrK2kjlsTp4GPCQL+W5XhIgCv59muMUqexv/Hx7pRyAZxG5VPxij+j3blC1 +-----END CERTIFICATE REQUEST----- diff --git a/Projs/PD2/certs/client1/client1.key b/Projs/PD2/certs/client1/client1.key new file mode 100644 index 0000000..0c7ab1c --- /dev/null +++ b/Projs/PD2/certs/client1/client1.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +V9adr9w9IqxWjYWPMhfeyCbQgFcWoA== +-----END PRIVATE KEY----- diff --git a/Projs/PD2/certs/client1/client1.p12 b/Projs/PD2/certs/client1/client1.p12 new file mode 100644 index 0000000000000000000000000000000000000000..020ee3293768292595857baf176563c5c0ff23fd GIT binary patch literal 5634 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 G!~X!wqp6Gl literal 0 HcmV?d00001 diff --git a/Projs/PD2/certs/server/server.crt b/Projs/PD2/certs/server/server.crt new file mode 100644 index 0000000..dd3a398 --- /dev/null +++ b/Projs/PD2/certs/server/server.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFBDCCAuygAwIBAgIUfEdbWdFRD1TgQr9L/b6BG/TtrzQwDQYJKoZIhvcNAQEL +BQAwDTELMAkGA1UEAwwCQ0EwHhcNMjQwNDE5MDAyMDIwWhcNMjkwNDE4MDAyMDIw +WjAnMRQwEgYDVQQLDAtNU0cgU0VSVklDRTEPMA0GA1UEQQwGU0VSVkVSMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2fFMnYrXlQ8rPwOrMHFCRHbJe6fF +b+ZuVcXBakexI3a4d8unQJKeEqVX5POndEKNERUPXOcGrifV7ehxfmF/6oK2Xx4u +IrLHibV0XjAXY7YcTQj+ao18BgdVdrUi7cS8YYyyKoT+SP+GkEVYF5vJEgoTRy1h +dQQLZYp5AqsqoBbXr4rVaUdXDD8c1zWMwW6NGDIXWe0eAMMXyjqJRkdZ3FO4+53Y +4Zg2qUeF1GcDRamyC0dGykHeYmaly9M2tO6Mhwuh+wlMEbj55wxpPu3rlboMGIgi ++G2H3cHJLBn/1TkO5BZK3+2DhhUn0KuB3nfLsSP8v5H2A7FnnDuQaB64G4cRHprI +new7k02UnPXNefrX8JqlmSIIEzaMXSP4BNhKVMSSUmS5NHvkvxTZBlC7CBoB6W7y +10Ja807h0mHbMkV+FAVbfY8q2wAsUq3JPWizq6pZ+dgapDmZ0xCOZRnXqv2kBXas +UHwxWUL18T4VwlW97+aUr8afIkATZU11O6GXJbRbRjy8ofP7gcSIkeWOZUDrJlRM +K5PEkhVBOFuVVuty6uZLZleSBNkUOzsCeFxsdaJE9TKlVzxp6ewvtu4PTelKj31h +mTMCenTPcS9sa6gZTGIkdscOMy7lZjsMdlcyAxjUD59w1ruzDQyTn2tP9I6lLnKT +cCMmFKQfbyAZNcMCAwEAAaNCMEAwHQYDVR0OBBYEFEWIGqx7p7sYgYjtB/oUbChu +MdH3MB8GA1UdIwQYMBaAFMVE1jz77WweC8ao7bVYxujCdbDRMA0GCSqGSIb3DQEB +CwUAA4ICAQCIYQ5e0FbeZKwjdktLHw0cnGA3aVZhjbxJKU8rcDzeKDDH5SkwS25U +qIv4uvz+YY4DieSD0o3caTQhl4tx67Y9VcHmIQMjcMqFvzHBRAFZLidOgrqdJeIx +wD2c5kgrRf+8XTBQ9AG+D+XbI13dawlpAbJpu8fNdNO2XGzKu/qF+2f8u6E2Hx/U +LwJ1zqCXisr10CBIAwPrcsWBgM6oY9/YTaKRnLv4McZ9nil5yI5Y4odGTFs9zB8O +HrWlmCIQI47EevZdMJ+48xrGp2tkvAExGixcIS9reWkHVNomysg7pK+nE0jpTqAk +ZvcCXBKS1Bv+GWxrhKOA66SWTO9uTSr98D8hLKwpr3O76MGhtoqnxAwdX3KhdJe4 +HUyFSb7uwizuNKNigknJwQtXB6lbqUEzoL5jSLEmHQ2v80felr6QDfrKD9sw590o +Gmwaa1riSqmnzZhE8ROumn+zknFjnovzde0RUIZ7o6zqM1hfSllNPPAMx2fzvXkI +KYjvBNgVsmZmklkEpVkAB0XijNDYGC/iwdG2os72jCxPAOMoBAnz1LFI4Rl044Ly +6MIdk7iPvGLLfkCFt/qb8/iSRKW1B6caqZ292vN34c+sLJOkrjDVRtKVdTAUyDNU +O01F9HUPOjVWmfZbCNfIz1gyMEeJtQ7eyZMC6Eg4DV2Gft4lHX4pNQ== +-----END CERTIFICATE----- diff --git a/Projs/PD2/certs/server/server.csr b/Projs/PD2/certs/server/server.csr new file mode 100644 index 0000000..9c5c4de --- /dev/null +++ b/Projs/PD2/certs/server/server.csr @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEbDCCAlQCAQAwJzEUMBIGA1UECwwLTVNHIFNFUlZJQ0UxDzANBgNVBEEMBlNF +UlZFUjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANnxTJ2K15UPKz8D +qzBxQkR2yXunxW/mblXFwWpHsSN2uHfLp0CSnhKlV+Tzp3RCjREVD1znBq4n1e3o +cX5hf+qCtl8eLiKyx4m1dF4wF2O2HE0I/mqNfAYHVXa1Iu3EvGGMsiqE/kj/hpBF +WBebyRIKE0ctYXUEC2WKeQKrKqAW16+K1WlHVww/HNc1jMFujRgyF1ntHgDDF8o6 +iUZHWdxTuPud2OGYNqlHhdRnA0WpsgtHRspB3mJmpcvTNrTujIcLofsJTBG4+ecM +aT7t65W6DBiIIvhth93BySwZ/9U5DuQWSt/tg4YVJ9Crgd53y7Ej/L+R9gOxZ5w7 +kGgeuBuHER6ayJ3sO5NNlJz1zXn61/CapZkiCBM2jF0j+ATYSlTEklJkuTR75L8U +2QZQuwgaAelu8tdCWvNO4dJh2zJFfhQFW32PKtsALFKtyT1os6uqWfnYGqQ5mdMQ +jmUZ16r9pAV2rFB8MVlC9fE+FcJVve/mlK/GnyJAE2VNdTuhlyW0W0Y8vKHz+4HE +iJHljmVA6yZUTCuTxJIVQThblVbrcurmS2ZXkgTZFDs7AnhcbHWiRPUypVc8aens +L7buD03pSo99YZkzAnp0z3EvbGuoGUxiJHbHDjMu5WY7DHZXMgMY1A+fcNa7sw0M +k59rT/SOpS5yk3AjJhSkH28gGTXDAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEA +jBlPoy8e+RHAB/mf49rHLELrcgG35tSdyPxxzMlbeN+zCwLIP00k0RKI+YvZS8mM +L8Ao1aUq8bCHrL2J1/wJh/yT9G/DYZqvfSkX+om+IGddQL/SKSdR/3oqaUuX7NMr +b9eR+HSUAMhUIIzuHiqGIgCwUtagdVU8BAJuEDoepEdS+2+sMCgDOAQNM0+qH+R0 +33uWuZEokqwWaNc08h3mRtS1sLzcSQ9161iVzKJB44e6dWM/jqCZippNVWI0Skiu +UfP+uoYVuv1U9lEjX8cz54mL7iOs5snXJVpt8oO17zKozfLAyCFygU+gUNNnh/K/ +T3EtvI7TlAAFMpYi5q95D4Mj3j6l2P0WcoLFrytCtRnLic6NCE5HYj2vScGN9WCh +GWcs4h+2MIY/VTxzn6AP82zXsJRusdfHoVAP/MDnP8YeIU9gtbWTJCl9DmdHQYp3 +Xw6/TBCQwnQhbGquHVl4WFj8aO7Mm3jtVm5eLTRXNMCYPvqbOlaeeKZRsJkoyInf +gYj+LTZ2ke4moZ00tG4PwSvTj1CKuswa6HfB5l1UHmCuEhm4saS6MbgORj6UHh0W +L7gLtdUINzu/7KE3ZTI+d4kgpM2QFozjTa5SRYCBkZh/WhRMbI1lleWFw2dKFuyJ +IxJPaCw5XRVz8TM2jAEMqPSA9hhwhKl42ieQKMbBTqU= +-----END CERTIFICATE REQUEST----- diff --git a/Projs/PD2/certs/server/server.key b/Projs/PD2/certs/server/server.key new file mode 100644 index 0000000..5e2de24 --- /dev/null +++ b/Projs/PD2/certs/server/server.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +f1Qiiw4+bNeBK2XZZKVXVltYUHrmUQ== +-----END PRIVATE KEY----- diff --git a/Projs/PD2/certs/server/server.p12 b/Projs/PD2/certs/server/server.p12 new file mode 100644 index 0000000000000000000000000000000000000000..96f3046bdf4fb92942ef61278d8eda465370422a GIT binary patch literal 5616 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 hY$h% 3 { + printError("MSG SERVICE: command error!") + showHelp() + os.Exit(1) + } + pageInput := flag.Arg(1) + page := 1 + if pageInput != "" { + if val, err := strconv.Atoi(pageInput); err == nil { + page = max(1, val) + } + } + pageSizeInput := flag.Arg(2) + pageSize := 5 + if pageSizeInput != "" { + if val, err := strconv.Atoi(pageSizeInput); err == nil { + pageSize = max(1, val) + } + } + + err := askQueueCommand(clientKeyStore, page, pageSize) + if err != nil { + log.Fatalln(err) + } + + case "getmsg": + if flag.NArg() < 2 { + printError("MSG SERVICE: command error!") + showHelp() + os.Exit(1) + } + numString := flag.Arg(1) + num, err := strconv.Atoi(numString) + if err != nil { + log.Fatalln(err) + } + err = getMsgCommand(clientKeyStore, num) + if err != nil { + printError(err.Error()) + } + + case "help": + showHelp() + + default: + printError("MSG SERVICE: command error!") + showHelp() + } + +} + +func sendCommand(clientKeyStore cryptoUtils.KeyStore, plainSubject, plainBody, uid string) error { + //Turn content to bytes + plainSubjectBytes, err := Marshal(plainSubject) + if err != nil { + return err + } + plainBodyBytes, err := Marshal(plainBody) + if err != nil { + return err + } + + cl, err := networking.NewClient[protocol.Packet](&clientKeyStore) + if err != nil { + return err + } + defer cl.Connection.Conn.Close() + + receiverCert, err := getUserCert(cl, clientKeyStore, uid) + if err != nil { + return err + } + subject, err := clientKeyStore.EncryptMessageContent(receiverCert, plainSubjectBytes) + if err != nil { + return err + } + body, err := clientKeyStore.EncryptMessageContent(receiverCert, plainBodyBytes) + if err != nil { + return err + } + sendMsgPacket := protocol.NewSendMsgPacket(uid, subject, body) + if err := cl.Connection.Send(sendMsgPacket); err != nil { + return err + } + answerSendMsg, err := cl.Connection.Receive() + if err != nil { + return err + } + if answerSendMsg.Flag == protocol.FlagReportError { + reportError, err := protocol.UnmarshalReportError(answerSendMsg.Body) + if err != nil { + return err + } + return errors.New(reportError.ErrorMessage) + } + return nil + +} + +func getMsgCommand(clientKeyStore cryptoUtils.KeyStore, num int) error { + cl, err := networking.NewClient[protocol.Packet](&clientKeyStore) + if err != nil { + return err + } + defer cl.Connection.Conn.Close() + packet := protocol.NewGetMsgPacket(num) + if err := cl.Connection.Send(packet); err != nil { + return err + } + + receivedMsgPacket, err := cl.Connection.Receive() + if err != nil { + return err + } + if receivedMsgPacket.Flag == protocol.FlagReportError { + reportError, err := protocol.UnmarshalReportError(receivedMsgPacket.Body) + if err != nil { + return err + } + return errors.New(reportError.ErrorMessage) + } + answerGetMsg, err := protocol.UnmarshalAnswerGetMsg(receivedMsgPacket.Body) + if err != nil { + return err + } + senderCert, err := getUserCert(cl, clientKeyStore, answerGetMsg.FromUID) + if err != nil { + return err + } + decSubjectBytes, err := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Subject) + if err != nil { + return err + } + decBodyBytes, err := clientKeyStore.DecryptMessageContent(senderCert, answerGetMsg.Body) + if err != nil { + return err + } + subject, err := Unmarshal(decSubjectBytes) + if err != nil { + return err + } + body, err := Unmarshal(decBodyBytes) + if err != nil { + return err + } + message := newClientMessage(answerGetMsg.FromUID, answerGetMsg.ToUID, subject, body, answerGetMsg.Timestamp) + showMessage(message) + return nil +} + +func getUserCert(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore, uid string) (*x509.Certificate, error) { + getUserCertPacket := protocol.NewGetUserCertPacket(uid) + if err := cl.Connection.Send(getUserCertPacket); err != nil { + return nil, err + } + var answerGetUserCertPacket *protocol.Packet + answerGetUserCertPacket, err := cl.Connection.Receive() + if err != nil { + return nil, err + } + if answerGetUserCertPacket.Flag == protocol.FlagReportError { + reportError, err := protocol.UnmarshalReportError(answerGetUserCertPacket.Body) + if err != nil { + return nil, err + } + return nil, errors.New(reportError.ErrorMessage) + } + answerGetUserCert, err := protocol.UnmarshalAnswerGetUserCert(answerGetUserCertPacket.Body) + if err != nil { + return nil, err + } + userCert, err := x509.ParseCertificate(answerGetUserCert.Certificate) + if err != nil { + return nil, err + } + if err := keyStore.CheckCert(userCert, uid); err != nil { + return nil, err + } + return userCert, nil +} + +func getManyMessagesInfo(cl networking.Client[protocol.Packet], keyStore cryptoUtils.KeyStore) (protocol.AnswerGetUnreadMsgsInfo, map[string]*x509.Certificate, error) { + answerGetUnreadMsgsInfoPacket, err := cl.Connection.Receive() + if err != nil { + return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil, err + } + if answerGetUnreadMsgsInfoPacket.Flag == protocol.FlagReportError { + reportError, err := protocol.UnmarshalReportError(answerGetUnreadMsgsInfoPacket.Body) + if err != nil { + return protocol.AnswerGetUnreadMsgsInfo{}, nil, err + } + return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, nil), nil, errors.New(reportError.ErrorMessage) + } + answerGetUnreadMsgsInfo, err := protocol.UnmarshalAnswerGetUnreadMsgsInfo(answerGetUnreadMsgsInfoPacket.Body) + if err != nil { + return protocol.AnswerGetUnreadMsgsInfo{}, nil, err + } + + //Create Set of needed certificates + senderSet := map[string]bool{} + for _, messageInfo := range answerGetUnreadMsgsInfo.MessagesInfo { + senderSet[messageInfo.FromUID] = true + } + certificatesMap := map[string]*x509.Certificate{} + //Get senders' certificates + for senderUID := range senderSet { + senderCert, err := getUserCert(cl, keyStore, senderUID) + if err == nil { + certificatesMap[senderUID] = senderCert + } + } + return answerGetUnreadMsgsInfo, certificatesMap, nil +} + +func askQueueCommand(clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) error { + cl, err := networking.NewClient[protocol.Packet](&clientKeyStore) + if err != nil { + return err + } + defer cl.Connection.Conn.Close() + return askQueueRec(cl, clientKeyStore, page, pageSize) +} + +func askQueueRec(cl networking.Client[protocol.Packet], clientKeyStore cryptoUtils.KeyStore, page int, pageSize int) error { + + requestUnreadMsgsQueuePacket := protocol.NewGetUnreadMsgsInfoPacket(page, pageSize) + if err := cl.Connection.Send(requestUnreadMsgsQueuePacket); err != nil { + return err + } + unreadMsgsInfo, certificates, err := getManyMessagesInfo(cl, clientKeyStore) + if err != nil { + return err + } + var clientMessages []ClientMessageInfo + for _, message := range unreadMsgsInfo.MessagesInfo { + var clientMessageInfo ClientMessageInfo + senderCert, ok := certificates[message.FromUID] + if !ok { + clientMessageInfo = newClientMessageInfo(message.Num, + message.FromUID, + "", + message.Timestamp, + errors.New("certificate needed to decrypt not received")) + clientMessages = append(clientMessages, clientMessageInfo) + continue + } + decryptedSubjectBytes, err := clientKeyStore.DecryptMessageContent(senderCert, message.Subject) + if err != nil { + clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, "", message.Timestamp, err) + clientMessages = append(clientMessages, clientMessageInfo) + continue + } + subject, err := Unmarshal(decryptedSubjectBytes) + if err != nil { + clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, "", message.Timestamp, err) + clientMessages = append(clientMessages, clientMessageInfo) + continue + } + clientMessageInfo = newClientMessageInfo(message.Num, message.FromUID, subject, message.Timestamp, nil) + clientMessages = append(clientMessages, clientMessageInfo) + } + //Sort the messages + sort.Slice(clientMessages, func(i, j int) bool { + return clientMessages[i].Num > clientMessages[j].Num + }) + + action := showMessagesInfo(unreadMsgsInfo.Page, unreadMsgsInfo.NumPages, clientMessages) + switch action { + case -1: + return askQueueRec(cl, clientKeyStore, max(1, unreadMsgsInfo.Page-1), pageSize) + case 1: + return askQueueRec(cl, clientKeyStore, max(1, unreadMsgsInfo.Page+1), pageSize) + default: + return nil + } +} diff --git a/Projs/PD2/internal/client/datastore.go b/Projs/PD2/internal/client/datastore.go new file mode 100644 index 0000000..7036d9e --- /dev/null +++ b/Projs/PD2/internal/client/datastore.go @@ -0,0 +1,47 @@ +package client + +import ( + "encoding/json" + "time" +) + +type ClientMessage struct { + FromUID string + ToUID string + Subject string + Body string + Timestamp time.Time +} + +type ClientMessageInfo struct { + Num int + FromUID string + Timestamp time.Time + Subject string + decryptError error +} + +func newClientMessage(fromUID string, toUID string, subject string, body string, timestamp time.Time) ClientMessage { + return ClientMessage{FromUID: fromUID, ToUID: toUID, Subject: subject, Body: body, Timestamp: timestamp} +} + +func newClientMessageInfo(num int, fromUID string, subject string, timestamp time.Time, err error) ClientMessageInfo { + return ClientMessageInfo{Num: num, FromUID: fromUID, Subject: subject, Timestamp: timestamp, decryptError: err} +} + +func Marshal(data any) ([]byte, error) { + subject, err := json.Marshal(data) + if err != nil { + return nil, err + } + return subject, nil +} + +func Unmarshal(data []byte) (string, error) { + var c string + err := json.Unmarshal(data, &c) + if err != nil { + return "", err + } + return c, nil +} diff --git a/Projs/PD2/internal/client/interface.go b/Projs/PD2/internal/client/interface.go new file mode 100644 index 0000000..e891746 --- /dev/null +++ b/Projs/PD2/internal/client/interface.go @@ -0,0 +1,92 @@ +package client + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +func readStdin(message string) string { + fmt.Println(message) + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + return scanner.Text() +} + +func printError(err string) { + fmt.Fprintln(os.Stderr, err) +} + +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.") + fmt.Println("send : Envia uma mensagem com assunto destinada ao utilizador com identificador . O conteúdo da mensagem será lido do stdin, e o tamanho deve ser limitado a 1000 bytes.") + fmt.Println("askqueue: Solicita ao servidor que lhe envie a lista de mensagens não lidas da queue do utilizador.") + fmt.Println("getmsg : Solicita ao servidor o envio da mensagem da sua queue com número .") + fmt.Println("help: Imprime instruções de uso do programa.") +} + +func showMessagesInfo(page int, numPages int, messages []ClientMessageInfo) int { + if messages == nil { + fmt.Println("No unread messages in the queue") + return 0 + } + for _, message := range messages { + if message.decryptError != nil { + fmt.Printf("ERROR: %v:%v:%v:", message.Num, message.FromUID, message.Timestamp) + fmt.Println(message.decryptError) + } else { + fmt.Printf("%v:%v:%v:%v\n", message.Num, message.FromUID, message.Timestamp, message.Subject) + } + } + fmt.Printf("Page %v/%v\n", page, numPages) + return messagesInfoPageNavigation(page, numPages) +} + +func messagesInfoPageNavigation(page int, numPages int) int { + var action string + + switch page { + case 1: + if page == numPages { + return 0 + } else { + action = readStdin("Actions: quit/next") + } + case numPages: + action = readStdin("Actions: prev/quit") + default: + action = readStdin("prev/quit/next") + } + + switch strings.ToLower(action) { + case "prev": + if page == 1 { + fmt.Println("Unavailable action: Already in first page") + messagesInfoPageNavigation(page, numPages) + } else { + return -1 + } + case "quit": + return 0 + case "next": + if page == numPages { + fmt.Println("Unavailable action: Already in last page") + messagesInfoPageNavigation(page, numPages) + } else { + return 1 + } + default: + fmt.Println("Unknown action") + messagesInfoPageNavigation(page, numPages) + } + return 0 +} + +func showMessage(message ClientMessage) { + fmt.Printf("From: %s\n", message.FromUID) + fmt.Printf("To: %s\n", message.ToUID) + fmt.Printf("Subject: %s\n", message.Subject) + fmt.Printf("Body: %s\n", message.Body) +} diff --git a/Projs/PD2/internal/gateway/gateway.go b/Projs/PD2/internal/gateway/gateway.go new file mode 100644 index 0000000..65093c8 --- /dev/null +++ b/Projs/PD2/internal/gateway/gateway.go @@ -0,0 +1,5 @@ +package gateway + +func Run(){ + +} diff --git a/Projs/PD2/internal/protocol/protocol.go b/Projs/PD2/internal/protocol/protocol.go new file mode 100644 index 0000000..5987c11 --- /dev/null +++ b/Projs/PD2/internal/protocol/protocol.go @@ -0,0 +1,119 @@ +package protocol + +import ( + "time" +) + +type Body interface{} + +type ( + GetUserCert struct { + UID string `json:"uid"` + } + + GetUnreadMsgsInfo struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` + } + + GetMsg struct { + Num int `json:"num"` + } + + SendMsg struct { + ToUID string `json:"to_uid"` + Subject []byte `json:"subject"` + Body []byte `json:"body"` + } + + AnswerGetUserCert struct { + UID string `json:"uid"` + Certificate []byte `json:"certificate"` + } + + AnswerGetUnreadMsgsInfo struct { + Page int `json:"page"` + NumPages int `json:"num_pages"` + MessagesInfo []MsgInfo `json:"messages_info"` + } + + MsgInfo struct { + Num int `json:"num"` + FromUID string `json:"from_uid"` + Subject []byte `json:"subject"` + Timestamp time.Time `json:"timestamp"` + } + + AnswerGetMsg struct { + FromUID string `json:"from_uid"` + ToUID string `json:"to_uid"` + Subject []byte `json:"subject"` + Body []byte `json:"body"` + Timestamp time.Time `json:"timestamp"` + } + + ReportError struct { + ErrorMessage string `json:"error"` + } +) + +func NewGetUserCert(UID string) GetUserCert { + return GetUserCert{ + UID: UID, + } +} + +func NewGetUnreadMsgsInfo(page int, pageSize int) GetUnreadMsgsInfo { + return GetUnreadMsgsInfo{ + Page: page, + PageSize: pageSize} +} + +func NewGetMsg(num int) GetMsg { + return GetMsg{ + Num: num, + } +} + +func NewSendMsg(toUID string, subject []byte, body []byte) SendMsg { + return SendMsg{ + ToUID: toUID, + Subject: subject, + Body: body, + } +} + +func NewAnswerGetUserCert(uid string, certificate []byte) AnswerGetUserCert { + return AnswerGetUserCert{ + UID: uid, + Certificate: certificate, + } +} + +func NewAnswerGetUnreadMsgsInfo(page int, numPages int, messagesInfo []MsgInfo) AnswerGetUnreadMsgsInfo { + return AnswerGetUnreadMsgsInfo{Page: page, NumPages: numPages, MessagesInfo: messagesInfo} +} +func NewMsgInfo(num int, fromUID string, subject []byte, timestamp time.Time) MsgInfo { + return MsgInfo{ + Num: num, + FromUID: fromUID, + Subject: subject, + Timestamp: timestamp, + } +} + +func NewAnswerGetMsg(fromUID, toUID string, subject []byte, body []byte, timestamp time.Time, last bool) AnswerGetMsg { + return AnswerGetMsg{ + FromUID: fromUID, + ToUID: toUID, + Subject: subject, + Body: body, + Timestamp: timestamp, + } +} + +func NewReportError(errorMessage string) ReportError { + return ReportError{ + ErrorMessage: errorMessage, + } +} diff --git a/Projs/PD2/internal/server/datastore.go b/Projs/PD2/internal/server/datastore.go new file mode 100644 index 0000000..dc8a722 --- /dev/null +++ b/Projs/PD2/internal/server/datastore.go @@ -0,0 +1,245 @@ +package server + +import ( + "PD1/internal/protocol" + "crypto/x509" + "database/sql" + "errors" + "fmt" + "log" + "time" + + _ "github.com/mattn/go-sqlite3" +) + +type DataStore struct { + db *sql.DB +} + +func OpenDB() (DataStore, error) { + db, err := sql.Open("sqlite3", "server.db") + if err != nil { + return DataStore{}, err + } + ds := DataStore{db: db} + err = ds.CreateTables() + if err != nil { + return DataStore{}, err + } + return ds, nil +} + +func (ds DataStore) CreateTables() error { + // Create users table + _, err := ds.db.Exec(`CREATE TABLE IF NOT EXISTS users ( + UID TEXT PRIMARY KEY, + userCert BLOB + )`) + if err != nil { + return err + } + + // Create messages table + _, err = ds.db.Exec(`CREATE TABLE IF NOT EXISTS messages ( + fromUID TEXT, + toUID TEXT, + timestamp TIMESTAMP, + queue_position INT DEFAULT 0, + subject BLOB, + body BLOB, + status INT CHECK (status IN (0,1)), + PRIMARY KEY (toUID, fromUID, timestamp), + FOREIGN KEY(fromUID) REFERENCES users(UID), + FOREIGN KEY(toUID) REFERENCES users(UID) + )`) + if err != nil { + return err + } + + // Define a trigger to automatically assign numbers for each message of each user starting from 1 + _, err = ds.db.Exec(` + CREATE TRIGGER IF NOT EXISTS assign_queue_position + AFTER INSERT ON messages + FOR EACH ROW + BEGIN + UPDATE messages + SET queue_position = ( + SELECT COUNT(*) + FROM messages + WHERE toUID = NEW.toUID + ) + WHERE toUID = NEW.toUID AND rowid = NEW.rowid; + END; + `) + if err != nil { + return err + } + + return nil +} + +func (ds DataStore) GetMessage(toUID string, position int) (*protocol.AnswerGetMsg, error) { + + var serverMessage protocol.AnswerGetMsg + query := ` + SELECT fromUID, toUID, subject, body, timestamp + FROM messages + WHERE toUID = ? AND queue_position = ? + ` + // Execute the query + row := ds.db.QueryRow(query, toUID, position) + err := row.Scan(&serverMessage.FromUID, &serverMessage.ToUID, &serverMessage.Subject, &serverMessage.Body, &serverMessage.Timestamp) + if err == sql.ErrNoRows { + log.Printf("No message with NUM %v for UID %v\n", position, toUID) + errorMessage := fmt.Sprintln("MSG SERVICE: unknown message!") + error := errors.New(errorMessage) + return nil, error + } + + answer := protocol.NewAnswerGetMsg(serverMessage.FromUID, serverMessage.ToUID, serverMessage.Subject, serverMessage.Body, serverMessage.Timestamp, true) + return &answer, nil + +} + +func (ds DataStore) MarkMessageInQueueAsRead(toUID string, position int) { + query := ` + UPDATE messages + SET status = 1 + WHERE (fromUID,toUID,timestamp) = ( + SELECT fromUID,toUID,timestamp + FROM messages + WHERE toUID = ? AND queue_position = ? + ) + ` + + // Execute the SQL statement + _, err := ds.db.Exec(query, toUID, position) + if err != nil { + log.Printf("Error marking the message in position %v from UID %v as read: %v", position, toUID, err) + } +} + +func (ds DataStore) GetUnreadMsgsInfo(toUID string, page int, pageSize int) (protocol.AnswerGetUnreadMsgsInfo, error) { + + // Retrieve the total count of unread messages + var totalCount int + err := ds.db.QueryRow("SELECT COUNT(*) FROM messages WHERE toUID = ? AND status = 0", toUID).Scan(&totalCount) + if err == sql.ErrNoRows { + return protocol.NewAnswerGetUnreadMsgsInfo(0, 0, []protocol.MsgInfo{}), nil + } + + // Query to retrieve all messages from the user's queue + query := ` + SELECT + fromUID, + toUID, + timestamp, + queue_position, + subject, + status + FROM messages + WHERE + toUID = ? AND status = 0 + ORDER BY + queue_position DESC + LIMIT ? OFFSET ?; + ` + + // Execute the query + rows, err := ds.db.Query(query, toUID, pageSize, (page-1)*pageSize) + if err != nil { + log.Printf("Error getting unread messages for UID %v: %v", toUID, err) + } + defer rows.Close() + + messageInfoPackets := []protocol.MsgInfo{} + for rows.Next() { + var fromUID string + var subject []byte + var timestamp time.Time + var queuePosition, status int + if err := rows.Scan(&fromUID, &toUID, ×tamp, &queuePosition, &subject, &status); err != nil { + return protocol.AnswerGetUnreadMsgsInfo{}, err + } + answerGetUnreadMsgsInfo := protocol.NewMsgInfo(queuePosition, fromUID, subject, timestamp) + messageInfoPackets = append(messageInfoPackets, answerGetUnreadMsgsInfo) + } + if err := rows.Err(); err != nil { + log.Printf("Error when getting messages for UID %v: %v", toUID, err) + return protocol.AnswerGetUnreadMsgsInfo{}, err + } + numberOfPages := (totalCount + pageSize - 1) / pageSize + currentPage := min(numberOfPages, page) + return protocol.NewAnswerGetUnreadMsgsInfo(currentPage, numberOfPages, messageInfoPackets), nil +} + +func (ds DataStore) AddMessageToQueue(fromUID string, message protocol.SendMsg) error { + query := ` + INSERT INTO messages (fromUID, toUID, subject, body, timestamp, status) + VALUES (?, ?, ?, ?, ?, 0) + ` + + // Execute the SQL statement + currentTime := time.Now() + _, err := ds.db.Exec(query, fromUID, message.ToUID, message.Subject, message.Body, currentTime) + if err != nil { + log.Printf("Error adding message to UID %v: %v", fromUID, err) + return err + } + return nil +} + +func (ds DataStore) GetUserCertificate(uid string) (protocol.AnswerGetUserCert,error) { + query := ` + SELECT userCert + FROM users + WHERE UID = ? + ` + + // Execute the SQL query + var userCertBytes []byte + err := ds.db.QueryRow(query, uid).Scan(&userCertBytes) + if err == sql.ErrNoRows { + errorMessage := fmt.Sprintf("No certificate for UID %v found in the database", uid) + log.Println(errorMessage) + return protocol.AnswerGetUserCert{},errors.New(errorMessage) + } + return protocol.NewAnswerGetUserCert(uid, userCertBytes),nil +} + +func (ds DataStore) userExists(uid string) bool { + // Prepare the SQL statement for checking if a user exists + query := ` + SELECT COUNT(*) + FROM users + WHERE UID = ? + ` + + var count int + // Execute the SQL query + err := ds.db.QueryRow(query, uid).Scan(&count) + if err != nil || count == 0 { + log.Printf("user with UID %v does not exist\n", uid) + return false + } + return true +} + +func (ds DataStore) storeUserCertIfNotExists(uid string, cert x509.Certificate) error { + // Check if the user already exists + if ds.userExists(uid) { + return nil + } + + // Insert the user certificate + insertQuery := ` + INSERT INTO users (UID, userCert) + VALUES (?, ?) + ` + _, err := ds.db.Exec(insertQuery, uid, cert.Raw) + if err != nil { + return fmt.Errorf("error storing user certificate for UID %s: %v", uid, err) + } + log.Printf("User certificate for UID %s stored successfully.\n", uid) + return nil +} diff --git a/Projs/PD2/internal/server/interface.go b/Projs/PD2/internal/server/interface.go new file mode 100644 index 0000000..40e156f --- /dev/null +++ b/Projs/PD2/internal/server/interface.go @@ -0,0 +1,14 @@ +package server + +import ( + "bufio" + "fmt" + "os" +) + +func readStdin(message string) string { + fmt.Println(message) + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + return scanner.Text() +} diff --git a/Projs/PD2/internal/server/server.go b/Projs/PD2/internal/server/server.go new file mode 100644 index 0000000..e4118cb --- /dev/null +++ b/Projs/PD2/internal/server/server.go @@ -0,0 +1,151 @@ +package server + +import ( + "PD1/internal/protocol" + "PD1/internal/utils/cryptoUtils" + "log" + "net/http" + "strconv" + + "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) + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) + } else { + c.JSON(http.StatusOK, userCertPacket) + } +} + +func HandleGetUnreadMsgsInfo(c *gin.Context, dataStore DataStore) { + user := c.Param("user") + + var getUnreadMsgsInfo protocol.GetUnreadMsgsInfo + if err := c.BindJSON(getUnreadMsgsInfo); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if getUnreadMsgsInfo.Page <= 0 || getUnreadMsgsInfo.PageSize <= 0 { + c.JSON(http.StatusBadRequest, gin.H{"error": "Page and PageSize need to be >= 1"}) + return + } + unreadMsgsInfo, err := dataStore.GetUnreadMsgsInfo(user, getUnreadMsgsInfo.Page, getUnreadMsgsInfo.PageSize) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, unreadMsgsInfo) +} + +func HandleSendMessage(c *gin.Context, dataStore DataStore) { + sender := c.Param("user") + + var message protocol.SendMsg + if err := c.BindJSON(message); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if message.ToUID == sender { + c.JSON(http.StatusBadRequest, gin.H{"error": "Message sender and receiver cannot be the same user"}) + return + } + if !dataStore.userExists(message.ToUID) { + c.JSON(http.StatusBadRequest, gin.H{"error": "Message receiver does not exist"}) + return + } + err := dataStore.AddMessageToQueue(sender, message) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, nil) +} + +func HandleGetMessage(c *gin.Context, dataStore DataStore) { + user := c.Param("user") + numStr := c.Param("num") + num, err := strconv.Atoi(numStr) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + } + + message, reportError := dataStore.GetMessage(user, num) + if reportError != nil { + c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) + } + dataStore.MarkMessageInQueueAsRead(user, num) + c.JSON(http.StatusOK, message) +} + +func Run() { + //Open connection to DB + dataStore, err := OpenDB() + if err != nil { + log.Fatalln(err) + } + defer dataStore.db.Close() + + //Read server keystore + keystorePassphrase := readStdin("Insert keystore passphrase") + serverKeyStore, err := cryptoUtils.LoadKeyStore("certs/server/server.p12", keystorePassphrase) + if err != nil { + log.Fatalln(err) + } + + r := gin.Default() + + r.GET("/message/:user/:num", func(c *gin.Context) { + HandleGetMessage(c, dataStore) + }) + + r.GET("/queue/:user", func(c *gin.Context) { + HandleGetUnreadMsgsInfo(c, dataStore) + }) + + r.GET("/cert/:user", func(c *gin.Context) { + HandleGetUserCert(c, dataStore) + }) + + r.POST("/message/:user", func(c *gin.Context) { + HandleSendMessage(c, dataStore) + }) + + server := http.Server{ + Addr: "0.0.0.0:8080", + Handler: r, + TLSConfig: serverKeyStore.GetTLSConfig(), + } + + err = server.ListenAndServeTLS("", "") + if err!=nil { + log.Fatal(err.Error()) + } +} diff --git a/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go b/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go new file mode 100644 index 0000000..6e4d4bb --- /dev/null +++ b/Projs/PD2/internal/utils/cryptoUtils/cryptoUtils.go @@ -0,0 +1,283 @@ +package cryptoUtils + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/tls" + "crypto/x509" + "encoding/binary" + "errors" + "time" + + "log" + "os" + + "golang.org/x/crypto/chacha20poly1305" + "software.sslmate.com/src/go-pkcs12" +) + +type KeyStore struct { + cert *x509.Certificate + caCertChain []*x509.Certificate + 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 +} + +func ExtractAllOIDValues(cert *x509.Certificate) map[string]string { + oidValueMap := make(map[string]string) + for _, name := range cert.Subject.Names { + oid := name.Type.String() + value := name.Value.(string) + oidValueMap[oid] = value + } + return oidValueMap +} + +func LoadKeyStore(keyStorePath string, password string) (KeyStore, error) { + + var privKey *rsa.PrivateKey + + keystoreBytes, err := os.ReadFile(keyStorePath) + if err != nil { + return KeyStore{}, err + } + + privKeyInterface, cert, caCerts, err := pkcs12.DecodeChain(keystoreBytes, password) + if err != nil { + return KeyStore{}, err + } + privKey, ok := privKeyInterface.(*rsa.PrivateKey) + if !ok { + return KeyStore{}, err + } + + 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 { + caCertPool.AddCert(caCert) + } + opts := x509.VerifyOptions{ + Roots: 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 + } + + if cert.NotAfter.Before(time.Now()) { + return errors.New("certificate has expired") + } + if cert.NotBefore.After(time.Now()) { + return errors.New("certificate is not valid yet") + } + + //Check if the pseudonym field is set to UID + oidMap := ExtractAllOIDValues(cert) + if oidMap["2.5.4.65"] != uid { + log.Println("Certificate does not belong to the message's receiver") + return err + } + return nil +} + +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 { + 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 cert.NotBefore.After(time.Now()) { + return errors.New("certificate is not valid yet") + } + + // Check if the certificate is signed by the specified CA + _, err = cert.Verify(opts) + if err != nil { + return errors.New("certificate not signed by trusted CA") + } + } + return nil + } + return tlsConfig +} + +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.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 cert.NotBefore.After(time.Now()) { + return errors.New("certificate is not valid yet") + } + oidMap := ExtractAllOIDValues(cert) + + // Check if the certificate is signed by the specified CA + _, err = cert.Verify(opts) + if err != nil { + return errors.New("certificate not signed by trusted CA") + } + + //Check if the pseudonym field is set to "SERVER" + if oidMap["2.5.4.65"] != "SERVER" { + return errors.New("peer isn't the server") + } + } + return nil + } + return tlsConfig +} + +func (k KeyStore) EncryptMessageContent(receiverCert *x509.Certificate, content []byte) ([]byte, error) { + // Digital envolope + + // Create a random symmetric key + dataKey := make([]byte, 32) + if _, err := rand.Read(dataKey); err != nil { + return nil, err + } + + cipher, err := chacha20poly1305.New(dataKey) + if err != nil { + return nil, err + } + + nonce := make([]byte, cipher.NonceSize(), cipher.NonceSize()+len(content)+cipher.Overhead()) + if _, err = rand.Read(nonce); err != nil { + return nil, err + } + + // sign the message and append the signature + hashedContent := sha256.Sum256(content) + signature, err := rsa.SignPKCS1v15(nil, k.privKey, crypto.SHA256, hashedContent[:]) + if err != nil { + return nil, err + } + content = pair(signature, content) + ciphertext := cipher.Seal(nonce, nonce, content, nil) + + receiverPubKey := receiverCert.PublicKey.(*rsa.PublicKey) + encryptedDataKey, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, receiverPubKey, dataKey, nil) + if err != nil { + return nil, err + } + return pair(encryptedDataKey, ciphertext), nil +} + +func (k KeyStore) DecryptMessageContent(senderCert *x509.Certificate, cipherContent []byte) ([]byte, error) { + encryptedDataKey, encryptedMsg := unPair(cipherContent) + dataKey, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, k.GetPrivKey(), encryptedDataKey, nil) + if err != nil { + return nil, err + } + // decrypt ciphertext + cipher, err := chacha20poly1305.New(dataKey) + if err != nil { + return nil, err + } + + nonce, ciphertext := encryptedMsg[:cipher.NonceSize()], encryptedMsg[cipher.NonceSize():] + contentAndSig, err := cipher.Open(nil, nonce, ciphertext, nil) + if err != nil { + return nil, err + } + // check signature with sender public key + signature, content := unPair(contentAndSig) + hashedContent := sha256.Sum256(content) + senderKey := senderCert.PublicKey.(*rsa.PublicKey) + if err := rsa.VerifyPKCS1v15(senderKey, crypto.SHA256, hashedContent[:], signature); err != nil { + return nil, err + } + return content, nil +} + +func pair(l []byte, r []byte) []byte { + length := len(l) + lenBytes := make([]byte, 2) + binary.BigEndian.PutUint16(lenBytes, uint16(length)) + + lWithLen := append(lenBytes, l...) + return append(lWithLen, r...) +} + +func unPair(pair []byte) ([]byte, []byte) { + lenBytes := pair[:2] + pair = pair[2:] + length := binary.BigEndian.Uint16(lenBytes) + l := pair[:length] + r := pair[length:] + return l, r +} diff --git a/Projs/PD2/internal/utils/networking/client.go b/Projs/PD2/internal/utils/networking/client.go new file mode 100644 index 0000000..cb49c4c --- /dev/null +++ b/Projs/PD2/internal/utils/networking/client.go @@ -0,0 +1,23 @@ +package networking + +import ( + "crypto/tls" +) + + +type ClientTLSConfigProvider interface { + GetClientTLSConfig() *tls.Config +} + +type Client[T any] struct { + Connection Connection[T] +} + +func NewClient[T any](clientTLSConfigProvider ClientTLSConfigProvider) (Client[T],error) { + dialConn, err := tls.Dial("tcp", "localhost:8080", clientTLSConfigProvider.GetClientTLSConfig()) + if err != nil { + return Client[T]{},err + } + conn := NewConnection[T](dialConn) + return Client[T]{Connection: conn},nil +} diff --git a/Projs/PD2/internal/utils/networking/connection.go b/Projs/PD2/internal/utils/networking/connection.go new file mode 100644 index 0000000..82efba6 --- /dev/null +++ b/Projs/PD2/internal/utils/networking/connection.go @@ -0,0 +1,51 @@ +package networking + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "io" + "log" +) + +type Connection[T any] struct { + Conn *tls.Conn + encoder *json.Encoder + decoder *json.Decoder +} + +func NewConnection[T any](netConn *tls.Conn) Connection[T] { + return Connection[T]{ + Conn: netConn, + encoder: json.NewEncoder(netConn), + decoder: json.NewDecoder(netConn), + } +} + +func (c Connection[T]) Send(obj T) error { + if err := c.encoder.Encode(&obj); err!=nil { + if err == io.EOF { + log.Println("Connection closed by peer") + } + return err + } + //Return true as connection active + return nil +} + +func (c Connection[T]) Receive() (*T, error) { + var obj T + if err := c.decoder.Decode(&obj); err != nil { + if err == io.EOF { + log.Println("Connection closed by peer") + } + return nil,err + } + //Return true as connection active + return &obj, nil +} + +func (c Connection[T]) GetPeerCertificate() *x509.Certificate { + state := c.Conn.ConnectionState() + return state.PeerCertificates[0] +} diff --git a/Projs/PD2/internal/utils/networking/server.go b/Projs/PD2/internal/utils/networking/server.go new file mode 100644 index 0000000..01a6da2 --- /dev/null +++ b/Projs/PD2/internal/utils/networking/server.go @@ -0,0 +1,56 @@ +package networking + +import ( + "crypto/tls" + "log" + "net" +) + +type ServerTLSConfigProvider interface { + GetServerTLSConfig() *tls.Config +} + +type Server[T any] struct { + listener net.Listener + C chan Connection[T] +} + +func NewServer[T any](serverTLSConfigProvider ServerTLSConfigProvider) (Server[T], error) { + + listener, err := tls.Listen("tcp", "127.0.0.1:8080", serverTLSConfigProvider.GetServerTLSConfig()) + if err != nil { + return Server[T]{}, err + } + return Server[T]{ + listener: listener, + C: make(chan Connection[T]), + }, nil +} + +func (s *Server[T]) ListenLoop() { + + for { + listenerConn, err := s.listener.Accept() + if err != nil { + log.Println("Server could not accept connection") + continue + } + tlsConn, ok := listenerConn.(*tls.Conn) + if !ok { + log.Println("Connection is not a TLS connection") + continue + } + if err := tlsConn.Handshake(); err != nil { + log.Println(err) + continue + } + + state := tlsConn.ConnectionState() + if len(state.PeerCertificates) == 0 { + log.Println("Client did not provide a certificate") + continue + } + conn := NewConnection[T](tlsConn) + s.C <- conn + } +} diff --git a/Projs/PD2/report_content/digital-envelope-diagram.drawio.png b/Projs/PD2/report_content/digital-envelope-diagram.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..f54fe9fe1bf4d08e5c385b5393f2200a3f76922c GIT binary patch literal 48257 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 DpbvWl literal 0 HcmV?d00001 diff --git a/Projs/PD2/report_content/digital-envelope-diagram.jpg b/Projs/PD2/report_content/digital-envelope-diagram.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6847d5041c4fdb8995d4c42a724da331dce6caa0 GIT binary patch literal 33942 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 Dx??gl literal 0 HcmV?d00001 diff --git a/Projs/PD2/tokefile.toml b/Projs/PD2/tokefile.toml new file mode 100644 index 0000000..9e98440 --- /dev/null +++ b/Projs/PD2/tokefile.toml @@ -0,0 +1,23 @@ +[targets.setup] +wildcards=[["golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest"]] +cmd="go install @@" + +[targets.check] +wildcards=[["go vet ./...","shadow ./..."]] +cmd="@@" + +[targets.build] +cmd="go build" + +[targets.server] +cmd="go run ./cmd/server/server.go" + +[targets.send] +cmd="go run ./cmd/client/client.go -user certs/client1/client1.p12 send CL2 testsubject" + +[targets.askQueue] +cmd="go run ./cmd/client/client.go -user certs/client2/client2.p12 askqueue" + +[targets.fakeAskQueue] +cmd="go run ./cmd/client/client.go -user certs/FakeClient1/client1.p12 askqueue" + diff --git a/TPs/TP02/py/cfich_aes_cbc.py b/TPs/TP02/py/cfich_aes_cbc.py old mode 100755 new mode 100644 diff --git a/TPs/TP02/py/cfich_chacha20.py b/TPs/TP02/py/cfich_chacha20.py old mode 100755 new mode 100644 diff --git a/TPs/TP02/py/chacha20_int_attck.py b/TPs/TP02/py/chacha20_int_attck.py old mode 100755 new mode 100644 diff --git a/TPs/TP02/py/input.txt.enc b/TPs/TP02/py/input.txt.enc deleted file mode 100644 index ce7432a..0000000 --- a/TPs/TP02/py/input.txt.enc +++ /dev/null @@ -1 +0,0 @@ -US9hM(#cboe@].J?K.k|Davz>Z:"] \ No newline at end of file diff --git a/TPs/TP03/pbenc_aes_ctr_hmac b/TPs/TP03/pbenc_aes_ctr_hmac old mode 100755 new mode 100644 diff --git a/TPs/TP03/py/plaintext.txt.enc b/TPs/TP03/py/plaintext.txt.enc deleted file mode 100644 index dfd60ebb9ae6f7fcbe9d9d94b446cf21286c482e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77 zcmV-T0J8t8xPVM*C7L+n!;KhNA~6H%mG{D7W(&tt^o3ZOo{Ep8Rj0@m@JYpflWH(p jX`@B`#tYcjy8@l8xd1>^{xOyLzk>j>7yP(s%GSX7