[PD2] Relatorio inicio

Co-authored-by: tsousa111 <tiagao2001@hotmail.com>
This commit is contained in:
Afonso Franco 2024-05-31 23:14:06 +01:00
parent 6f8219d991
commit b86992a10a
Signed by: afonso
SSH key fingerprint: SHA256:PQTRDHPH3yALEGtHXnXBp3Orfcn21pK20t0tS1kHg54
10 changed files with 192 additions and 289 deletions
Projs/PD2

View file

@ -1,214 +1,99 @@
# Relatório do Projeto de Desenvolvimento 1
# Relatório do Projeto de Desenvolvimento 2
## 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.
Neste segundo projeto de desenvolvimento (PD2), realizamos várias alterações em relação ao PD1, visando melhorar a estrutura e a segurança do sistema de mensagens seguro e autenticado. A principal mudança foi a introdução de uma API Gateway entre o cliente e o servidor, responsável pela autenticação dos utilizadores e pelo encaminhamento dos pedidos para o servidor. Este relatório detalha as modificações implementadas e os benefícios alcançados com essas mudanças.
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.
Falar do gin
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.
## Mudanças Implementadas
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.
### Microsserviços
Algumas notas sobre o projeto:
![Arquitetura](report_content/microservices-pd2.png)
- 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.
#### Gateway
- Implementamos algumas funcionalidades extra, como o armazenamento dos dados no servidor numa base de dados **sqlite3**
A principal alteração na arquitetura foi a introdução de uma API Gateway, que atua como intermediária entre o cliente e o servidor. A API Gateway é responsável pela autenticação dos utilizadores, criação de um canal seguro, e encaminhamento dos pedidos ao servidor.
Nas secções seguintes iremos detalhar cada componente do sistema, bem como as funcionalidades implementadas.
##### Funções da Gateway
1. **Autenticação de Utilizadores**: A API Gateway lida com os processos de login e registo dos utilizadores, armazenando o ID do utilizador e uma hash da palavra-passe, e validando o certificado do utilizador.
1. **Encaminhamento de Pedidos**: A API Gateway recebe os pedidos dos clientes, verifica a autenticidade com tokens JWT, e encaminha-os para o servidor.
## Análise de Risco
1. **Criação de Canal Seguro**: A comunicação entre o cliente e a API Gateway, assim como entre a API Gateway e o servidor, é protegida utilizando o protocolo TLS, garantindo a segurança dos dados transmitidos.
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.
##### Endpoints da Gateway
### Potenciais Vulnerabilidades
Foram adicionados novos endpoints à API Gateway para lidar com a autenticação e as operações de mensagens:
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. **Autenticação e Registo**:
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.
- `POST /register`: Permite que um novo utilizador se registe enviando a sua palavra-passe e certificado.
- `POST /login`: Permite que um utilizador existente faça login enviando o seu ID e palavra-passe. Se as credenciais forem válidas, um token JWT é gerado e enviado ao cliente.
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. **Operações de Mensagens**:
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.
- `GET /message/:num`: Obtém uma mensagem específica para o utilizador autenticado.
- `GET /queue`: Obtém informações sobre mensagens não lidas.
- `GET /cert/:user`: Obtém o certificado de outro utilizador.
- `POST /message`: Envia uma mensagem para um destinatário.
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.
### Servidor
### Possíveis Ameaças:
O servidor foi ajustado para trabalhar em conjunto com a API Gateway.
Aceita conexões apenas provenientes da API Gateway, verificando isso através do certificado enviado pela gateway no início da conexão TLS.
O servidor confia plenamente na Gateway, enviando qualquer informação que seja pedida.
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.
#### Endpoints do Servidor
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.
Foram mantidos e ajustados os seguintes endpoints no servidor para corresponder às novas funcionalidades da API Gateway:
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.
- `GET /message/:user/:num`: Devolve uma mensagem específica para um utilizador.
- `GET /queue/:user`: Devolve informações sobre mensagens não lidas de um utilizador.
- `GET /cert/:user`: Devolve o certificado de um utilizador.
- `POST /message/:user`: Armazena uma mensagem para um utilizador.
- `POST /cert/:user`: Armazena o certificado de um utilizador.
1. **Exploração de Vulnerabilidades de *Software*:** - Vulnerabilidades conhecidas ou desconhecidas no *software* utilizado podem ser exploradas para comprometer a segurança do sistema.
### Token de Autenticação JWT
### Propriedades Requiridas:
Ao fazer login, a API Gateway gera um token JWT para o utilizador autenticado. Esse token é enviado ao cliente, que deve incluí-lo no campo "Token" do header de cada request subsequente.
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.
### Base de Dados da API Gateway
A API Gateway utiliza uma base de dados SQLite3 para armazenar os utilizadores e as hashes das suas palavra-passes.
## 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.
O mecanismo de cifra das mensagens manteve-se, com a exceção de uma pequena alteração na assinatura do conteúdo. Decidimos colocar o id do recetor na assinatura digital, visando garantir que este tenha a certeza de que a mensagem é para ele.
![Digital Envelope](report_content/digital-envelope-diagram.jpg)
![Digital Envelope](report_content/digital_envelope.jpeg)
## Execução
### Networking
### Gateway
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.
A gateway utiliza o valor da variável de ambiente "SECRET_KEY" para criar os tokens JWT.
Esta variável pode ser inicializada desta forma
```bash
SECRET_KEY=thisisasecretkey go run ./cmd/gateway/gateway.go
```
### Servidor
### Protocolo de Comunicação
O servidor pode ser corrido da seguinte forma.
```bash
go run ./cmd/server/server.go
```
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**.
### Cliente
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.
O cliente pode ser corrido da seguinte forma.
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.
```bash
go run ./cmd/client/client.go -user ./certs/client2/client2.p12 COMANDO_AQUI
```
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.
## Conclusão
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.
As mudanças implementadas no PD2, com a introdução da API Gateway e as melhorias na segurança e na estrutura de autenticação, resultaram em um sistema de mensagens mais seguro e robusto. A API Gateway não apenas facilita a autenticação e a gestão de sessões com tokens JWT, mas também garante que as operações entre clientes e servidor sejam realizadas de forma segura e eficiente. Essas modificações reforçam a confidencialidade, integridade e autenticidade das comunicações no sistema, mantendo um alto padrão de segurança para as informações trocadas.

Binary file not shown.

View file

@ -137,7 +137,7 @@ func Run() {
os.Exit(1)
}
err := registerUser(myUID, password, clientKeyStore)
err := registerUser(password, clientKeyStore)
if err != nil {
printError(err.Error())
os.Exit(1)
@ -188,8 +188,8 @@ func getHTTPClient(tlsConfig *tls.Config) *http.Client {
return &http.Client{Transport: transport}
}
func registerUser(userId string, password string, clientKeyStore cryptoUtils.KeyStore) error {
postRegister := protocol.NewPostRegister(userId, password, clientKeyStore.GetCert().Raw)
func registerUser(password string, clientKeyStore cryptoUtils.KeyStore) error {
postRegister := protocol.NewPostRegister(password, clientKeyStore.GetCert().Raw)
jsonData, err := json.Marshal(postRegister)
if err != nil {

View file

@ -18,174 +18,173 @@ func getHTTPClient(tlsConfig *tls.Config) *http.Client{
return &http.Client{Transport: transport}
}
func forwardStoreUserCert(tlsConfig *tls.Config,uid string,storeUserCertificate protocol.StoreUserCert) (int,[]byte,error) {
client := getHTTPClient(tlsConfig)
func forwardStoreUserCert(tlsConfig *tls.Config, uid string, storeUserCertificate protocol.StoreUserCert) (int, []byte, error) {
client := getHTTPClient(tlsConfig)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("certs")
parsedURL = parsedURL.JoinPath(uid)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0, nil, fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("certs")
parsedURL = parsedURL.JoinPath(uid)
jsonData, err := json.Marshal(storeUserCertificate)
if err != nil {
return 0,nil,fmt.Errorf("error marshaling JSON: %v", err)
return 0, nil, fmt.Errorf("error marshaling JSON: %v", err)
}
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(jsonData))
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(jsonData))
if err != nil {
return 0,nil,fmt.Errorf("error creating request: %v", err)
return 0, nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := client.Do(req)
if err != nil {
return 0,nil,fmt.Errorf("error making request: %v", err)
resp, err := client.Do(req)
if err != nil {
return 0, nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
// Read response
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0,nil,fmt.Errorf("error reading response body: %v", err)
return 0, nil, fmt.Errorf("error reading response body: %v", err)
}
return resp.StatusCode,body,nil
return resp.StatusCode, body, nil
}
func forwardGetMessage(tlsConfig *tls.Config,uid string,num string) (int,[]byte,error) {
client := getHTTPClient(tlsConfig)
func forwardGetMessage(tlsConfig *tls.Config, uid string, num string) (int, []byte, error) {
client := getHTTPClient(tlsConfig)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("message")
parsedURL = parsedURL.JoinPath(uid)
parsedURL = parsedURL.JoinPath(num)
req, err := http.NewRequest("GET", parsedURL.String(), nil)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error creating request: %v", err)
return 0, nil, fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("message")
parsedURL = parsedURL.JoinPath(uid)
parsedURL = parsedURL.JoinPath(num)
req, err := http.NewRequest("GET", parsedURL.String(), nil)
if err != nil {
return 0, nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := client.Do(req)
if err != nil {
return 0,nil,fmt.Errorf("error making request: %v", err)
resp, err := client.Do(req)
if err != nil {
return 0, nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
// Read response
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0,nil,fmt.Errorf("error reading response body: %v", err)
return 0, nil, fmt.Errorf("error reading response body: %v", err)
}
return resp.StatusCode,body,nil
return resp.StatusCode, body, nil
}
func forwardGetUnreadMsgsInfo(tlsConfig *tls.Config,uid string,page string,pagesize string) (int,[]byte,error) {
client := getHTTPClient(tlsConfig)
func forwardGetUnreadMsgsInfo(tlsConfig *tls.Config, uid string, page string, pagesize string) (int, []byte, error) {
client := getHTTPClient(tlsConfig)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("queue")
parsedURL = parsedURL.JoinPath(uid)
query := parsedURL.Query()
query.Set("page", page)
query.Set("pagesize", pagesize)
parsedURL.RawQuery = query.Encode()
req, err := http.NewRequest("GET", parsedURL.String(), nil)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error creating request: %v", err)
return 0, nil, fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("queue")
parsedURL = parsedURL.JoinPath(uid)
query := parsedURL.Query()
query.Set("page", page)
query.Set("pagesize", pagesize)
parsedURL.RawQuery = query.Encode()
req, err := http.NewRequest("GET", parsedURL.String(), nil)
if err != nil {
return 0, nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := client.Do(req)
if err != nil {
return 0,nil,fmt.Errorf("error making request: %v", err)
resp, err := client.Do(req)
if err != nil {
return 0, nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
// Read response
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0,nil,fmt.Errorf("error reading response body: %v", err)
return 0, nil, fmt.Errorf("error reading response body: %v", err)
}
return resp.StatusCode,body,nil
return resp.StatusCode, body, nil
}
func forwardGetUserCert(tlsConfig *tls.Config,uid string) (int,[]byte,error) {
client := getHTTPClient(tlsConfig)
func forwardGetUserCert(tlsConfig *tls.Config, uid string) (int, []byte, error) {
client := getHTTPClient(tlsConfig)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("cert")
parsedURL = parsedURL.JoinPath(uid)
req, err := http.NewRequest("GET", parsedURL.String(), nil)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error creating request: %v", err)
return 0, nil, fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("cert")
parsedURL = parsedURL.JoinPath(uid)
req, err := http.NewRequest("GET", parsedURL.String(), nil)
if err != nil {
return 0, nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := client.Do(req)
if err != nil {
return 0,nil,fmt.Errorf("error making request: %v", err)
resp, err := client.Do(req)
if err != nil {
return 0, nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
// Read response
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0,nil,fmt.Errorf("error reading response body: %v", err)
return 0, nil, fmt.Errorf("error reading response body: %v", err)
}
return resp.StatusCode,body,nil
return resp.StatusCode, body, nil
}
func forwardSendMessage(tlsConfig *tls.Config,uid string,sendMsg protocol.SendMsg) (int,[]byte,error) {
client := getHTTPClient(tlsConfig)
func forwardSendMessage(tlsConfig *tls.Config, uid string, sendMsg protocol.SendMsg) (int, []byte, error) {
client := getHTTPClient(tlsConfig)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0,nil,fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("message")
parsedURL = parsedURL.JoinPath(uid)
// Parse the base URL
parsedURL, err := url.Parse(baseURL)
if err != nil {
return 0, nil, fmt.Errorf("error parsing URL: %v", err)
}
parsedURL = parsedURL.JoinPath("message")
parsedURL = parsedURL.JoinPath(uid)
jsonData, err := json.Marshal(sendMsg)
if err != nil {
return 0,nil,fmt.Errorf("error marshaling JSON: %v", err)
return 0, nil, fmt.Errorf("error marshaling JSON: %v", err)
}
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(jsonData))
req, err := http.NewRequest("POST", parsedURL.String(), bytes.NewBuffer(jsonData))
if err != nil {
return 0,nil,fmt.Errorf("error creating request: %v", err)
return 0, nil, fmt.Errorf("error creating request: %v", err)
}
resp, err := client.Do(req)
if err != nil {
return 0,nil,fmt.Errorf("error making request: %v", err)
resp, err := client.Do(req)
if err != nil {
return 0, nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()
// Read response
// Read response
body, err := io.ReadAll(resp.Body)
if err != nil {
return 0,nil,fmt.Errorf("error reading response body: %v", err)
return 0, nil, fmt.Errorf("error reading response body: %v", err)
}
return resp.StatusCode,body,nil
return resp.StatusCode, body, nil
}

View file

@ -104,27 +104,37 @@ func HandleRegister(c *gin.Context, dataStore DataStore, keyStore cryptoUtils.Ke
c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid"})
return
}
err = keyStore.CheckCert(userCert, postRegister.UID, "MSG SERVICE")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "User certificate is invalid, not trusted, belongs to another user or has incorrect usage field"})
if err := keyStore.CheckCertCA(userCert); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := keyStore.CheckCertTime(userCert); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := keyStore.CheckCertUsage(userCert, "MSG SERVICE"); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
hashedPassword, err := HashPassword(postRegister.Password)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not hash password"})
c.JSON(http.StatusBadRequest, gin.H{"error": "Could not hash password"})
return
}
err = dataStore.InsertUser(postRegister.UID, hashedPassword)
uid,err := keyStore.GetCertPseudonym(userCert)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = dataStore.InsertUser(uid, hashedPassword)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not insert user into DB"})
c.JSON(http.StatusBadRequest, gin.H{"error": "Could not insert user into DB"})
return
}
storeUserCertificate := protocol.NewStoreUserCert(userCert.Raw)
statusCode, body, err := forwardStoreUserCert(keyStore.GetGatewayOutgoingTLSConfig(), postRegister.UID, storeUserCertificate)
statusCode, body, err := forwardStoreUserCert(keyStore.GetGatewayOutgoingTLSConfig(),uid, storeUserCertificate)
if err != nil {
log.Println(err.Error())
} else {

View file

@ -43,7 +43,6 @@ type (
}
PostRegister struct {
UID string `json:"uid"`
Password string `json:"password"`
Certificate []byte `json:"certificate"`
}
@ -85,9 +84,8 @@ func NewMsgInfo(num int, fromUID string, subject []byte, timestamp time.Time) Ms
}
}
func NewPostRegister(UID string, Password string, Certificate []byte) PostRegister {
func NewPostRegister(Password string, Certificate []byte) PostRegister {
return PostRegister{
UID: UID,
Password: Password,
Certificate: Certificate,
}

View file

@ -101,15 +101,25 @@ func (k KeyStore) CheckCertTime(cert *x509.Certificate) error {
func (k KeyStore) CheckCertPseudonym(cert *x509.Certificate, pseudonym string) error {
oidMap := ExtractAllOIDValues(cert)
if oidMap["2.5.4.65"] != pseudonym {
return errors.New("Certificate does not belong to the correct pseudonym")
return errors.New("certificate does not belong to the correct pseudonym")
}
return nil
}
// Check if the pseudonym field is set to the correct pseudonym
func (k KeyStore) GetCertPseudonym(cert *x509.Certificate) (string,error){
oidMap := ExtractAllOIDValues(cert)
uid := oidMap["2.5.4.65"]
if uid == "" {
return "",errors.New("certificate does not have a pseudonym field")
}
return uid, nil
}
func (k KeyStore) CheckCertUsage(cert *x509.Certificate, usage string) error {
oidMap := ExtractAllOIDValues(cert)
if oidMap["2.5.4.11"] != usage {
return errors.New("Certificate does not have the correct usage")
return errors.New("certificate does not have the correct usage")
}
return nil
}

Binary file not shown.

View file

@ -1 +1 @@
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcyNjEzOTQsInN1YiI6IkNMMiJ9.lE-zUVbwLBwCLPh8z78-pp5lnu_UwR2j_ARWTManfs8
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcyNzg4OTMsInN1YiI6IkNMMiJ9.v8_aRomq2oYTMBKwr0yWyJj808t3ju7mmLG1gD7ZuRY

1
Projs/PD2/token/CL3 Normal file
View file

@ -0,0 +1 @@
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTcyNzg5MTQsInN1YiI6IkNMMyJ9.5yFFA_UhmKacLs5WIOaCwe7urfrjU6bFIrx7F28Ivzo