Cifra de Vigenère (Vigenère Cipher)¶
A cifra de Vigenère é uma cifra de substituição polialfabética que foi considerada uma das melhores cifras clássicas. Nomeada em homenagem a Blaise de Vigenère, um criptógrafo francês do século 16, ela melhora a simples substituição usando múltiplas cifras de César com diferentes valores de deslocamento baseados em uma palavra-chave.
Fundamento Matemático¶
A Tabela da Cifra (Tabula Recta)¶
A cifra de Vigenère usa uma tabela de alfabetos deslocados ciclicamente:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
A A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
B C D E F G H I J K L M N O P Q R S T U V W X Y Z A
C D E F G H I J K L M N O P Q R S T U V W X Y Z A B
...
Z Z A B C D E F G H I J K L M N O P Q R S T U V W X Y
Fórmula de Criptografia¶
Dado: - Caractere de texto plano $P$ (posição no alfabeto, 0-25) - Caractere da palavra-chave $K$ (posição na palavra-chave, 0-25)
O caractere do texto cifrado $C$ é calculado como:
$$C = (P + K) \mod 26$$
Fórmula de Decifração¶
$$P = (C - K) \mod 26$$
Exemplo¶
Texto Plano: ATTACKATDAWN
Palavra-Chave: LEMON
| Posição | P | L | E | M | O | L | E | M | O | L | E | M |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | A(0) | +L(11) | =L(11) | |||||||||
| 1 | T(19) | +E(4) | =X(23) | |||||||||
| 2 | T(19) | +M(12) | =G(7) | |||||||||
| 3 | A(0) | +O(14) | =O(14) | |||||||||
| 4 | C(2) | +L(11) | =N(13) | |||||||||
| 5 | K(10) | +E(4) | =Q(14) | |||||||||
| 6 | A(0) | +M(12) | =O(14) | |||||||||
| 7 | T(19) | +O(14) | =D(3) | |||||||||
| 8 | A(0) | +L(11) | =M(12) | |||||||||
| 9 | D(3) | +E(4) | =H(7) | |||||||||
| 10 | A(0) | +M(12) | =W(22) | |||||||||
| 11 | W(22) | +O(14) | =G(6) |
Texto Cifrado: LXGONQODMHWG
Implementação em Java¶
public class VigenereCipher {
private static final int ALPHABET_SIZE = 26;
/**
* Cripta uma mensagem usando a cifra de Vigenère.
* @param plaintext A mensagem original (apenas letras)
* @param keyword A chave de criptografia
* @return A mensagem criptografada
*/
public static String encrypt(String plaintext, String keyword) {
StringBuilder ciphertext = new StringBuilder();
int[] keyPositions = getKeywordPositions(keyword);
for (int i = 0; i < plaintext.length(); i++) {
char c = plaintext.charAt(i);
if (Character.isLetter(c)) {
char base = Character.isUpperCase(c) ? 'A' : 'a';
int position = c - base;
int keyPosition = keyPositions[i % keyPositions.length];
int encryptedPosition = (position + keyPosition) % ALPHABET_SIZE;
ciphertext.append((char)(base + encryptedPosition));
} else {
ciphertext.append(c); // Preserva caracteres não alfabéticos
}
}
return ciphertext.toString();
}
/**
* Decifra uma mensagem criptografada com a cifra de Vigenère.
* @param ciphertext A mensagem criptografada
* @param keyword A chave de criptografia
* @return A mensagem decifrada
*/
public static String decrypt(String ciphertext, String keyword) {
StringBuilder plaintext = new StringBuilder();
int[] keyPositions = getKeywordPositions(keyword);
for (int i = 0; i < ciphertext.length(); i++) {
char c = ciphertext.charAt(i);
if (Character.isLetter(c)) {
char base = Character.isUpperCase(c) ? 'A' : 'a';
int position = c - base;
int keyPosition = keyPositions[i % keyPositions.length];
int originalPosition = (position - keyPosition + ALPHABET_SIZE) % ALPHABET_SIZE;
plaintext.append((char)(base + originalPosition));
} else {
plaintext.append(c); // Preserva caracteres não alfabéticos
}
}
return plaintext.toString();
}
/**
* Converte palavra-chave para array de posições (0-25).
*/
private static int[] getKeywordPositions(String keyword) {
int[] positions = new int[keyword.length()];
for (int i = 0; i < keyword.length(); i++) {
char c = Character.toUpperCase(keyword.charAt(i));
positions[i] = c - 'A';
}
return positions;
}
public static void main(String[] args) {
String message = "ATTACKATDAWN";
String keyword = "LEMON";
String encrypted = encrypt(message, keyword);
System.out.println("Texto Plano: " + message);
System.out.println("Palavra-Chave: " + keyword);
System.out.println("Texto Cifrado: " + encrypted);
String decrypted = decrypt(encrypted, keyword);
System.out.println("Decifrado: " + decrypted);
}
}
Criptanálise: Exame de Kasiski e Índice de Coincidência¶
A cifra de Vigenère é vulnerável a criptanálise através de várias técnicas. A mais famosa é o exame de Kasiski.
Exame de Kasiski¶
Esta técnica explora padrões repetidos no texto cifrado que resultam de partes repetidas do texto plano alinhando-se com partes repetidas da palavra-chave.
Passos: 1. Encontre sequências repetidas no texto cifrado (pelo menos 3 caracteres) 2. Calcule as distâncias entre ocorrências 3. O maior divisor comum (MDC) dessas distâncias provavelmente revela o comprimento da chave 4. Uma vez conhecido o comprimento da chave, separe o texto cifrado em várias cifras de César e analise frequências
Exemplo de Análise Kasiski¶
Texto Cifrado: LXGONQODMHWG com análise de padrões repetidos...
Se encontrarmos "ON" aparecendo nas posições 3 e 10 (distância = 7), e outro padrão se repetir a cada 13 caracteres, o MDC pode ser 1. Isso sugere um comprimento de chave de 1 ou múltiplos dele.
Índice de Coincidência (IOC)¶
O IOC mede a probabilidade de que duas letras selecionadas aleatoriamente de um texto sejam idênticas. Para texto em inglês: - IOC esperado ≈ 0,067 (devido à distribuição de frequência das letras) - IOC de texto aleatório ≈ 0,038 (distribuição uniforme)
Calculando o IOC para diferentes comprimentos de chave, podemos determinar estatisticamente o comprimento da chave correta.
Análise de Segurança¶
Pontos Fortes e Fracos¶
| Aspecto | Avaliação |
|---|---|
| Espaço de Chave | $26^n$ onde n é o comprimento da palavra-chave (maior que César) |
| Complexidade | O(n) tempo, O(1) espaço |
| Vulnerabilidade | Quebrável com Kasiski ou análise de frequência em grupos |
| Uso Moderno | Apenas educacional - nunca para segurança real |
Por Que Ainda é Ensinoada¶
Apesar de quebrável, a cifra de Vigenère demonstra conceitos importantes:
- Substituição Polialfabética: Usando múltiplos alfabetos para ocultar frequências de letras
- Impacto do Comprimento da Chave: Chaves mais longas fornecem melhor segurança (embora ainda não seguras)
- Significado Histórico: Usada por governos e militares por séculos
- Fundação para Cifras Modernas: Conceitos evoluíram para cifras de fluxo modernas
Contexto Histórico¶
A cifra de Vigenère foi usada extensivamente durante os séculos 16-19:
- Marinha Francesa: Usada em comunicações navais
- Comunicações Diplomáticas: Protegia segredos de estado
- Primeira Guerra Mundial: Militares alemães usaram variantes (ex: ADFGVX)
Não foi quebrada até 1863 por Friedrich Kasiski, que publicou seu método de análise. Antes disso, era conhecida como a "cifra inexpugnável" (le chiffre indéchiffrable).
Variante Autokey¶
Uma variante mais segura chamada Autokey usa o próprio texto plano como parte do fluxo da chave:
- Chave:
LEMON - Texto Plano:
ATTACKATDAWN - Chave estendida:
LEMONATTAC...(palavra-chave + texto plano)
Isso torna a análise de frequência muito mais difícil, mas ainda vulnerável a ataques mais avançados.
Comparação com Criptografia Moderna¶
| Característica | Vigenère | AES (Moderno) |
|---|---|---|
| Comprimento da Chave | Variável (prático: 10-26 chars) | 128, 192 ou 256 bits |
| Margem de Segurança | Nenhuma - quebrável com suficiente texto cifrado | Provavelmente seguro por décadas |
| Velocidade | Muito rápida (operações simples) | Rápida mas mais complexa |
| Implementação | Fácil de implementar incorretamente | Padronizada e testada |
Referências¶
- Trappe, W., & Washington, L. C. (2006). Introduction to Cryptography with Coding Theory. Pearson.
- Stinson, D. R. (2005). Cryptography: Theory and Practice. CRC Press.
- Kahn, D. (1967). The Codebreakers: The Story of Secret Writing. Scribner.
- Friedman, W. F. (1920). "The Index of Coincidence and Its Application in Cryptography".