CS50 : S2 | Cifra de César - Parte 1
Tags: braziliandevs
Published: 2022-05-06 17:22:26

## Cifra de César

> Em criptografia, a Cifra de César, também conhecida como cifra de troca, código de César ou troca de César, é uma das mais simples e conhecidas técnicas de criptografia. É um tipo de cifra de substituição na qual cada letra do texto é substituída por outra, que se apresenta no alfabeto abaixo dela um número fixo de vezes. Por exemplo, com uma troca de três posições, A seria substituído por D, B se tornaria E, e assim por diante. O nome do método é em homenagem a Júlio César, que o usou para se comunicar com os seus generais.
-- Wikipedia

Nestes problemas que seguem, o algoritmo de César criptografa mensagens rotacionando as letras de acordo com **k** posições. Veremos abaixo, nas etapas como transferimos aquela fórmula matemática para o nosso código.

### Quebrando o código

- Pseudocódigo
1) Receber do usuário uma chave que corresponderá em quantas posições vai girar
2) Receber do usuário uma mensagem
3) Iterar sobre cada letra da mensagem
	- Se for maiúscula, preservar, e trocar o caracter de acordo com a chave.
	- Se for minúscula, preservar, e trocar o caracter de acordo com a chave
    - Se não for uma letra, preservar o caracter da mensagem original
4) Imprimir mensagem criptografada em tela
<br/>


- Código em C


```c
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void stringCipher(string text, int key);

int main(int argc, string argv[])
{
    if(argc != 2) {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    int key = atoi(argv[1]);

    string plaintext = get_string("plaintext: ");
    stringCipher(plaintext, key);
}

void stringCipher(string text, int key) {
    char cypher[strlen(text)];

    string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
    string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    for(int i = 0; i < strlen(text); i++) {
        if(isalpha(text[i])) {
            if(islower(text[i])) {
                int position = text[i] - 97;
                int c = (position + key) % 26;
                cypher[i] = lowerAlphabet[c];
            } else if(isupper(text[i])) {
                int position = text[i] - 65;
                int c = (position + key) % 26;
                cypher[i] = upperAlphabet[c];
            }
        } else {
                cypher[i] = text[i];
        }
    }
    printf("ciphertext: %s\n", cypher);
}
``` 

#### Recebendo a Chave do usuário

Na [aula 2](https://dev.to/mpfdev/cs50-passando-pela-semana-2-191i) vimos sobre a Interface de Linha de Comando e como podemos receber argumentos do usuário através do `argv[]`.

Sabendo-se que toda informação que vem pelo `argv[]` é do tipo **string** (por conta do `cs50.h`). Precisamos converter para o tipo **int**, para que seja um número, e assim, usarmos na fórmula matemática. Para isto, usaremos a função `atoi()` que faz parte da biblioteca `stdlib.h`. 

Assim, quando o usuário entrar com um argumento, esse número não será uma string, e sim um **número inteiro**.

`int key = atoi(argv[1]);`

#### Função para a Criptografia

Agora vamos falar sobre a função que faz a mágica acontecer.

```c
void stringCipher(string text, int key) {
    char cypher[strlen(text)];

    string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz";
    string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    for(int i = 0; i < strlen(text); i++) {
        if(isalpha(text[i])) {
            if(islower(text[i])) {
                int position = text[i] - 97;
                int c = (position + key) % 26;
                cypher[i] = lowerAlphabet[c];
            } else if(isupper(text[i])) {
                int position = text[i] - 65;
                int c = (position + key) % 26;
                cypher[i] = upperAlphabet[c];
            }
        } else {
                cypher[i] = text[i];
        }
    }
    printf("ciphertext: %s\n", cypher);
}
``` 

1) **Criar uma array de caracteres.**

O `char cypher[strlen(text)]` veio para fazer isso. Em C, temos que especificar o tamanho da array que vamos criar, como o tamanho pode ser variável, a depender de qual mensagem o usuário vai colocar, eu optei para que seja criado sempre com o mesmo tamanho da mensagem do usuário.

Dessa maneira, faz-se o uso do `strlen()` que faz parte da biblioteca `string.h`. Ela calcula o tamanho de uma string, e uma string é o que? Uma string é uma array de caracteres.
E então, seja qual foi o tamanho da **string** inicial, traduzirá para essa array de caracteres onde eu vou **armazenar** as letras *criptografadas*.

2) **Uma string é um array de caracteres**

Partindo desse pensamento, criei duas strings, uma para o abcdário minúsculo, e outro para maiúsculo. No enunciado, o problema levanta a ideia da **letra A** estar na posição **0**, a **letra B** estar na posição **1**, e por aí vai.

Então quando eu tenho:
`lowerAlphabet[0]` eu tenho acesso ao valor **a**
`lowerAlphabet[1]` eu tenho acesso ao valor **b**

Conseguindo assim replicar o enunciado do problema em questão.

3) **Iterando e verificando se é uma letra do alfabeto**

Começamos iterando sobre toda o tamanho da mensagem original.

```c
for(int i = 0; i < strlen(text); i++) {
	//todo
}
```

E agora usamos mais uma função, que a [doc do cs50](manual.cs50.io) fornece, `isalpha()` que pertence a biblioteca `ctype.h`. Dessa maneira, conseguiremos verificar posição-a-posição, se é um caracter alfabético ou não.

- Se for, aí começa o processo de encriptar.
- Se não, replica esses caracteres para a mensagem cifrada como são originalmente.

4) **A lógica por trás e como ASCII é necessário**

De novo, como no problema de [readability](https://dev.to/mpfdev/cs50-s2-readability-e-a-complexidade-textual-25jl), que já fiz uma explicação sobre, precisaremos da tabela de ASCII para descobrir a localização dos caracteres.

![ASCII Chart](https://s2.glbimg.com/RPbabV4SBKRMLI0glhOnIRbK6GM=/0x0:695x415/984x0/smart/filters:strip_icc()/i.s3.glbimg.com/v1/AUTH_08fbf48bc0524877943fe86e43087e7a/internal_photos/bs/2021/J/r/3dDbw9SueCiU9I8We1tA/2015-02-12-imagem28.jpg)

A lógica para letras maiúsculas é praticamente a mesma para a letras minúsculas, por isso falarei só das letras minúsculas.

Seguimos,

```c
if(islower(text[i])) {
	//bloco de comandos
}
```

Usamos a função `islower()`, da biblioteca `ctype.h`, em nossa condicional. Caso seja verdadeiro, executurá esse bloco de comandos

```c
	int position = text[i] - 97;
	int c = (position + key) % 26;
	cypher[i] = lowerAlphabet[c];
```

Vamos por partes agora, de acordo com a **tabela ASCII** a letra a corresponde ao valor **97**.
Queremos que ela venha valer 0. Por quê?
Porque se ela valer 0, eu posso dizer que a **letra a** está na **posição 0**. Assim, para qualquer **chave** eu posso andar sobre a minha string **lowerAlphabet** e trocar o valor, assm ter a minha mensagem encriptada.

- Então primeiro eu quero a posição:

`int position = text[i] - 97;`
Fazer uma subtração assim, vai forçar o C a transformar esse **char** na sua **int** correspondente

`int position = 'a' - 97;`    --------------- char: a -> int: 97
`int position = 0`

E assim valerá para todos os caracteres que corresponderem ao abcedário de **a** a **z**.

- Aplicar a fórmula da criptografia de acordo com o exercício proposto

`int c = (position + key) % 26;`

Pegamos a posição da letra da mensagem original e somamos com a quantidade de *casas* que vai pular, pegando assim o seu resto ao fazer a divisão por 26.

Então por exemplo:

	- Letra a + key 1

      - Char: a => Int: 97
      - position = 97 - 97 => position = 0
      - c = (position + key) % 26 => c = (0 + 1) % 26 => c = 1
      - lowerAlphabet[1] = b
    
	- Letra z + key 16

      - Char: z => Int: 122
      - position = 122 - 97 => position = 25
      - c = (position + key) % 26 => c = (25 + 16) % 26 => c = 15
      - lowerAlphabet[15] = p
    


- Armazenando esse valor em nossa array criptografada

`cypher[i] = lowerAlphabet[c];`

Seguindo a letra encontrada, armazena a nova letra na posição indicada.

E assim, ao terminar a iteração em toda a extensão da **string da mensagem original**, podemos imprimir a nova mensagem, agora criptograda atráves da nossa array `cypher[]` de chars.

Atráves da,
`printf("ciphertext: %s\n", cypher);`

#### E as letras maiúsculas?

Seguindo a mesma lógica acima, olhe a **tabela ASCII** e verifique, o que você mudaria?
Depois confira no código e repita os passos acima, a lógica é a mesma.

Não existe só uma maneira de resolver, nem a melhor. A melhor maneira, é aquela que você entende e onde você consegue resolver o problema da questão envolvida.

![final image](https://i.imgur.com/sDuhD0u.png)

### Conclusão

Eu ia comentar sobre o exercício da substituição nesse mesmo post, mas vai ficar muito longo.

Ficará para uma parte 2.

Espero que este post tenha te ajudado a entender mais sobre essa manipulação de arrays, e como a biblioteca fornecida pelo docs do cs50 é importante.

Te vejo na próxima, e não se esqueça de me seguir no [twitter](https://www.twitter.com/mpfdev).