Fazer download em pdf ou txt
Fazer download em pdf ou txt
Você está na página 1de 49

Teoria de números e criptografia RSA

Elaine Gouvêa Pimentel

1o Semestre - 2006
(Última Modificação: 4 de Maio de 2006)

1 Bibliografia e referências
Livro texto: S.C. Coutinho Números inteiros e criptografia RSA IMPA/SBM,
2000.
Outras referências:

• Rosen, K. H., Elementary number theory and its applications, Addison-


Wesley,1984.

• Koblitz, N. A course in number theory and criptography, Graduate Texts


in Mathematics 97, Springer-Verlag, 1987.

Ao longo do curso, serão indicadas leituras complementares.


Qualquer dúvida ou comentário, escrever para:

elaine@mat.ufmg.br

2 Introdução
O objetivo desse curso é estudar o método de criptografia de chaves públicas
conhecido como RSA. Para entender como este método funciona, é necessário
o estudo de alguns conceitos de uma área da matemática chamada Teoria de
números. E, é claro, espera-se desenvolver, ao longo do curso, o raciocı́nio
lógico matemático dos alunos, introduzindo métodos de prova de teoremas como
indução matemática e demonstração por absurdo.
Deve ficar bem claro que este é um curso de matemática para cientistas da
computação. Isto é, o rigor nunca será deixado de lado mas a atenção estará
sempre voltada para a aplicação principal proposta: criptografia RSA.

1
2.1 Criptografia
• Criptografia: estuda os métodos para codificar uma mensagem de modo
que só seu destinatário legı́timo consiga interpretá-la.

• Primórdios: Cesar (translação do alfabeto).

• Criptoanálise: arte de decifrar códigos secretos.

• Decodificar x Decifrar (quebrar).

• Substituir letras por sı́mbolos - contagem de frequência:

– vogais são mais frequentes;


– letra mais frequente: A;
– monossı́labo de uma letra = vogal;
– consoantes mais frequentes: S e M

Método de contagem de frequência de caracteres pode ser usado para


decifrar inscrições antigas.
• O surgimento dos computadores torna esse método de cifragem completa-
mente inseguro (decifragem polinomial).

• Internet e criptografia: segurança, assinatura.

• Chave pública: saber codificar não implica saber decodificar!

2.2 Criptografia RSA


• RSA: Rivest, Shamir, Adleman (M.I.T.) 1978.

• Codificação: basta conhecer o produto de dois primos (n = pq). n é


chamado chave pública.

• Decodificação: precisamos conhecer p e q (chave de decodificação).


• Decifrar RSA = fatoração de n. Se n possui 150 algarismos ou mais,
fatorá-lo levaria milhares de anos.

• Obs: É difı́cil determinar os fatores primos de um número composto, mas é


possı́vel verificar se um número é primo ou composto sem tentar fatorá-lo.

• Teoria de números: parte da matemática que estuda números inteiros.

2
2.3 Computação algébrica
• Chave pública do RSA: multiplica-se dois primos muito grandes.

• Pascal, C: não permitem lidar com números dessa magnitude.

• Computação algébrica: trata do cálculo exato com inteiros, frações, etc.


Exemplo: Mathematica, Maple.

• Inteiro de tamanho indeterminado: de tamanho flexı́vel, grandes o sufi-


ciente. Restrições: tamanho da memória, estruturas de dados (vetores de
tamanhos pré-fixados).

• Inteiros = listas! Algarismos = elemento da lista; operações de soma e


multiplicação: usuais, como com lápis e papel. Divisão é mais compli-
cado...

3 Algoritmo da divisão de Euclides

3.1 Algoritmos
• Algoritmo = processo de cálculo baseado em regras formais.

• Especificação de um algoritmo: entrada + instruções + saı́da.

• Perguntas:

– ao executarmos um conjunto de instruções, sempre chegaremos a um


resultado? (ponto fixo)
– o resultado obtido é sempre o desejado? (semântica)

3.2 Algoritmo da divisão


• Objetivo: encontrar o quociente q e o resto r (saı́da) da divisão entre dois
inteiros positivos a e b (entrada):

a = bq + r 0 ≤ r < b.

• Algoritmo da divisão:
Etapa 1: q = 0; r = a
Etapa 2: Se r < b, pare. Nesse caso, o quociente é q e o resto r.
Etapa 3: Se r ≥ b, faça r := r − b, q := q + 1 e volte à Etapa 2.

• Observações:

3
1. O algoritmo sempre para: sequência decrescente de números inteiros
positivos.
2. O resultado da aplicação do algoritmo corresponde às especificações
da saı́da (trivialmente).
3. O algoritmo é extremamente ineficiente, em especial se a >> b.

3.3 Teorema da Divisão

Teorema 1 (Teorema de divisão) Sejam a e b inteiros positivos. Existem


números inteiros q e r tais que

a = bq + r 0≤r<b

Além disso, q e r são únicos.

Prova .
Unicidade - Sejam q, q ′ , r, r′ tais que

a = bq + r 0≤r<b (1)

a = bq ′ + r′ 0 ≤ r′ < b (2)
Subtraindo-se (1) de (2), obtemos:

r − r′ = b(q ′ − q)

Ora, mas 0 ≤ r, r′ < b e portanto 0 ≤ r − r′ < b. Ou seja,

0 ≤ b(q ′ − q) < b

Como b > 0, temos


0 ≤ q − q′ < 1
ou seja, q − q ′ = 0 → q = q ′ e r = r′ .

3.4 Algoritmo Euclideano


• Objetivo: Calcular o mdc entre dois números inteiros.
• Definição: o máximo divisor comum entre a e b é o número d tal
que:
– d|a (ou d é divisor de a)
– d|b
– se d′ é divisor de a e b, então d′ |d (em outras palavras, d é o máximo
divisor de a e b.

4
• Escrevemos d = mdc(a, b). Se mdc(a, b) = 1, dizemos que a e b são
primos entre si .

• Algoritmo Euclideano: Dados dois números inteiros positivos a e


b tais que a ≥ b, divide-se a por b, encontrando resto r1 . Se r1 6= 0,
dividimos b por r1 , obtendo resto r2 . Se r2 6= 0, dividimos r1 por r2 e
assim por diante.
O último resto diferente de zero dessa sequência de divisões é o
mdc(a, b).

• Exemplo:
1234 54 46 8 6 2
46 8 6 2 0
Ou seja, mdc(1234, 54) = 2.

• Perguntas:

1. Por que o último resto não nulo é o mdc?


2. Por que o algoritmo para?

• Respostas:
a = bq1 + r1 e 0 ≤ r1 < b
b = r1 q2 + r2 e 0 ≤ r2 < r1
r1 = r2 q3 + r3 e 0 ≤ r3 < r2
r2 = r3 q4 + r4 e 0 ≤ r4 < r3
.. ..
. .
– Segunda pergunta: observe que

b > r1 > r2 > . . . ≥ 0

Como essa sequência é finita, o algoritmo sempre para. Mais ainda,


o número de divisões efetuadas é no máximo b (por que?).
– Primeira pergunta: demonstração do algoritmo euclideano

3.5 Demonstração do algoritmo euclideano

Lema 2 Sejam a e b números inteiros positivos. Se existem inteiros g e s tais


que a = bg + s, então mdc(a, b) = mdc(b, s).

Prova .
Sejam
d1 = mdc(a, b) e d2 = mdc(b, s).

5
Afirmamos que d1 ≤ d2 . De fato, d1 é o máximo divisor de a e b. Logo d1 divide
a e b e portanto existem inteiros positivos u e v tais que:

a = d1 u eb = d1 v

Substituindo a e b na equação a = bg + s obtemos

s = d1 u − d1 v = d1 (u − vg).

Ou seja, d1 divide s. Como d1 também divide b, d1 é um divisor comum de b e


s. Mas d2 é o maior divisor de b e s e portanto (por definição) d1 ≤ d2 como
querı́amos.
Seguindo um argumento semelhante, podemos provar o inverso, ou seja, d2 ≤ d1 .
Em outras palavras, d1 = d2

Teorema 3 Dados a e b inteiros positivos, o último resto diferente de zero da


sequência de divisões dada pelo algoritmo euclideano para a e b é o máximo
divisor comum entre a e b.

Prova .
Aplicando o algoritmo a a e b, temos:

a = bq1 + r1 e 0 ≤ r1 < b
b = r1 q2 + r2 e 0 ≤ r2 < r1
r1 = r2 q3 + r3 e 0 ≤ r3 < r2
r2 = r3 q4 + r4 e 0 ≤ r4 < r3
.. ..
. .
rn−2 = rn−1 qn e rn = 0

Da última linha, temos que rn−1 divide rn−2 e portanto mdc(rn−1 , rn−2 ) = rn−1 .
Aplicando sucessivamente o lema 2, temos que mdc(a, b) = rn−1 .

3.6 Algoritmo euclideano estendido

O resultado que mais vamos usar durante o curso sobre mdc é o seguinte:

Teorema 4 Sejam a e b inteiros positivos e seja d o máximo divisor comum


entre a e b. Esxistem inteiros α e β tais que

α.a + β.b = d.

Para demonstração desse teorema, veja o livro texto, pag 29-31.


Vamos ilustrar a demonstração através de um exemplo numérico:

6
Exemplo 1 Sejam a = 1234 e b = 54. Temos que:

1234 = 54.22 + 46 ou seja, 46 = 1234 − 54.22

Seguindo pelo algoritmo de euclides,

54 = 46.1 + 8 ou seja, 8 = 54 − 46.1

Agora, observe que sabemos calcular 46 em função de 1234 e 54. Então, substi-
tuindo:

8 = 54−46.1 = 54−(1234−54.22).1 = 54(1+22.1)+1234.(−1) = 54.(23)+1234.(−1)

Continuando,

46 = 8.5 + 6 → 6 = 46 − 8.5
= (1234 − 54.22) − (54.(23) + 1234.(−1)).5
= 1234.(6) + 54.(−22 − (23).5)
= 1234.(6) + 54.(−137)

8 = 6.1 + 2 → 2 = 8−6
= (54.(23) + 1234.(−1)) − (1234.(6) + 54.(−137))
= 1234(−1 − 6) + 54(23 + 137)
= 1234(−7) + 54(160)

Logo, α = −7 e β = 160 uma vez que mdc(1234, 54) = 2.

Observe que o teorema não diz que os valores de α e β são únicos. Na verdade,
existe uma infinidade de números que satisfazem a equação αa + βb = d.
Pergunta: para que serve calcular α e β?
Resposta:

• unicidade de fatoração de um inteiro;

• RSA depende de um método eficiente de cálculo de α e β.

3.7 Exercı́cios propostos

Não deixem de fazer os seguintes exercı́cios do capı́tulo 1:

1(1), 4, 5, 7, 8, 9.

7
4 Fatoração única

4.1 Teorema da fatoração única

Dizemos que um número inteiro positivo p é primo se p 6= 1 e os únicos


divisores de p são p e 1.
Se um número inteiro positivo (diferente de 1) não é primo, então ele é chamado
de composto .

Teorema 5 (Teorema da fatoração única) Dado um inteiro positivo n ≥ 2


podemos sempre escrevê-lo, de maneira única, na forma:

n = pe11 . . . . .pekk

onde 1 < p1 < p2 < . . . < pk são números primos e e1 , . . . , ek são inteiros
positivos (multiplicidades).

4.2 Existência da fatoração

Algoritmo ingênuo: Dado n ≥ 2 inteiro positivo, tente dividir n por cada um


dos inteiros de 2 a n − 1. Se algum desses inteiros (digamos k) dividir n, então
achamos um fator de n.
Perguntas:

1. k é primo ou composto?

2. Quando se deve parar a busca? Em n − 1?

Respostas:

1. k é primo. De fato, suponhamos k composto. Logo, k = a.b com 1 <


a, b < k. Como k divide n, existe (por definição) c inteiro tal que n = k.c.
Logo,
n = a.b.c
ou seja, a e b são fatores de n menores que k, o que contraria a hipótese
da minimalidade de k. Logo, k é primo.

2. Na verdade, podemos parar o algoritmo em n. De fato, n = k.c ou
c = nk . Como√k é o menor fator de n, k ≤ c. Logo, k ≤ nk ou seja,
k 2 ≤ n → k ≤ n.

Podemos utilizar o algoritmo acima para achar todos os fatores primos de n.


Aplicando o algoritmo uma vez, encontramos o fator q1 . Então, aplicamos o

8
algoritmo ao número qn1 , determinando q2 , o segundo fator primo de n. Para
determinar o terceiro fator primo q3 , aplicamos o algoritmo ao número q1n.q2 e
n
assim por diante, até chegarmos em q1 .q2 .....q s−1
= qs , com qs primo. Observe
que q1 ≤ q2 ≤ . . . ≤ qs−1 ≤ qs e
n n n
n> > > ... > > 0,
q1 q1 .q2 q1 .q2 . . . . .qs
ou seja, o algoritmo sempre termina.

Exemplo 2 n = 450 = 2.3.3.5.5

4.3 Eficiência do algoritmo ingênuo de fatoração

O algoritmo é simples mas muito ineficiente!

Exemplo 3 Seja n um √ número primo com 100 ou mais algarismos. Logo,


n ≥ 10100 e portanto n ≥ 1050 . Logo temos que executar pelo menos 1050
loops para determinar que n é primo. Suponhamos que o nosso computador
50
execute 1010 divisões por segundo. Logo levaremos 101010 = 10
40
segundos, ou
seja, 1031 anos na frente da tela do computador aguardando... Observe que o
tempo estimado de existência do universo é 1011 anos!

O algoritmo é bom para números pequenos. É importante ressaltar que não


existe (atualmente) algoritmo de fatoração eficiente para todos os
inteiros . Disso depende a segurança do RSA!
Não se sabe, entretanto, se tal algoritmo não existe mesmo ou se não fomos
espertos o suficiente para inventá-lo...

4.4 Fatoração por Fermat



• Eficiente quando n tem um fator primo não muito menor que n.
• Idéia: tentar achar números inteiros positivos x e y tais que n = x2 − y 2 .
• Caso mais fácil: n = r2 (x = r e y = 0).
• Se y > 0, então p √
x= n + y2 > n

Notação: escrevemos [r] como a parte inteira do número real r.


Algoritmo de Fermat:

Etapa 1: Faça x = [ n]; se n = x2 , pare.

9

Etapa 2: Incremente x de uma unidade e calcule y = x2 − n.
Etapa 3: Repita a etapa 2 até encontrar um valor inteiro para y, ou até que x = n+1
2 .
No primeiro caso, n tem fatores x + y e x − y; no segundo, n é primo.

Exemplo 4 Seja n = 1342127. Temos que x = 1158. Mas

x2 = 11582 = 1340964 < 1342127

Logo, passamos a incrementar x até que


p
x2 − n
n+1
seja inteiro ou x = 2 , que nesse caso vale 671064:

x x2 − n
1159 33, 97
1160 58, 93
1161 76, 11
1162 90, 09
1163 102, 18
1164 113

Logo, x = 1164 e y = 113. Os fatores procurados são x+y = 1277 e x−y = 1051.

Faremos aqui apenas a demonstração de que, se n é primo, então o único valor


possı́vel para x é x = n+1
2 . Relembrando, x e y são inteiros positivos tais que
n = x2 − y 2 . Ou seja,
n = (x − y)(x + y)
Como estamos supondo n primo, temos que x − y = 1 e x + y = n. Logo,
1+n n−1
x= e y=
2 2
como querı́amos.
Veja a demonstração completa do algoritmo no livro texto, páginas 41 a 43.
Observação: Esse algoritmo diz algo importante sobre o RSA. Se escolhermos
p e q muito próximos, então n = p.q é facilmente fatorável pelo algoritmo de
Fermat.

4.5 Propriedade fundamental dos primos

Lema 6 Sejam a, b, c inteiros positivos e suponhamos que a e b são primos entre


si. Então:

1. Se b divide o produto a.c então b divide c.

10
2. Se a e b dividem c então o produto a.b divide c.

Prova mdc(a, b) = 1. Pelo Algoritmo euclideano estendido, existem α e β


tais que
α.a + β.b = 1
Então,
α.a.c + β.b.c = c
Como b divide a.c pela hipótese (1) e como b divide β.b.c, então b divide c.
Para provar a segunda afirmativa, se a divide c, podemos escrever c = at para
algum inteiro t. Mas b também divide c. Como mdc(a, b) = 1, pela afirmação
(1), b divide t. Logo, t = b.k para algum inteiro k e portanto,

c = a.t = a.b.k

Podemos usar o lema acima para provar se seguinte propriedade:


Propriedade fundamental dos primos Seja p um primo e a e b inteiros
positivos. Se p divide o produto a.b, então p divide a ou p divide b.
A demonstração fica como exercı́cio (façam!).

4.6 Unicidade

A prova de unicidade da fatoração de números primos decorre facilmente da


propriedade fundamental dos primos. A demonstração se dá por absurdo.
Seja n o menor inteiro positivo que admite duas fatorações distintas. Podemos
escrever:
n = pe11 . . . . .pekk = q1r1 . . . . .qsrs
onde p1 < p2 < . . . < pk e q1 < q2 < . . . < qs são primos e e1 , . . . , ek , r1 , . . . , rs
são inteiros positivos.
Como p1 divide n, pela propriedade fundamental dos primos p1 deve dividir um
dos fatores do produto da direita. Mas um primo só pode dividir outro se forem
iguais. Então p1 = qj para algum j entre 1 e s. Logo,
r
n = pe11 . . . . .pekk = q1r1 . . . . .qj j . . . . .qsrs
r
= q1r1 . . . . .p1j . . . . .qsrs

Podemos então cancelar p1 que aparece em ambos os lados da equação, obtendo


r −1
m = pe11 −1 . . . . .pekk = q1r1 . . . . .p1j . . . . .qsrs

onde m é um número menor que n que apresenta duas fatorações distintas.


ABSURDO pois isso contraria a minimalidade de n.

11
4.7 Exercı́cios propostos
1. Prove a propriedade fundamental dos primos.

2. Demonstre que, se p é um número primo, então p é um número irracional.
3. Livro texto: 2, 4, 5, 8, 11, 12.

5 Números primos
Até agora:

• propriedades básicas dos números inteiros;


• dois algoritmos fundamentais;

Nessa seção, discutiremos métodos ingênuos para encontrar primos.

5.1 Fórmulas Polinomiais

Considere o polinômio:

f (x) = an .xn + an−1 .xn−1 + . . . + a1 .x + a0

onde an , an−1 , . . . , a1 , a0 são números inteiros e que satisfaz a condição:

f (m) é primo, para todo inteiro positivo m

Exemplo 5 Seja f (x) = x2 + 1 Logo,

x f (x)
1 2
2 5
3 10
4 17
5 26
6 37
7 50
8 65
9 82
2 5

• x ı́mpar → f (x) par;


• f (8) = 65 composto...

12
A pergunta que surge então é: isso é fruto do azar?

Teorema 7 Dado um polinômio f (x) com coeficientes inteiros, existe uma in-
finidade de inteiros positivos m tais que f (m) é composto.

Prova .
Vamos Provar o teorema apenas no caso em que o polinômio tem grau 2. Ou
seja, consideraremos f do tipo:

f (x) = a.x2 + b.x + c

Podemos supor a > 0. Suponhamos que exista m tal que f (m) = p onde p é
primo. Calculando f (m + hp):

f (m + hp) = a(m + hp)2 + b(m + hp) + c


= (am2 + bm + c) + p(2amh + aph2 + bh)
= p(1 + 2amh + aph2 + bh)

Ou seja, se 1+2amh+aph2 +bh é composto então f (m+hp) também é composto.


Mas isso é verdade sempre que

1 + 2amh + aph2 + bh > 1

ou seja, se
2amh + aph2 + bh = h.(2am + aph + b) > 0
Como podemos sempre tomar h positivo, temos:
−b − 2am
2am + aph + b > 0 → h >
a.p
Existe uma infinidade de números dessa forma. Logo, se existe inteiro m tal
que f (m) é primo, então existe uma infinidade de tais números.
Conclusão: não existe uma fórmula polinomial (em uma variável) para
primos .

5.2 Fórmulas exponenciais: números de Mersenne


• Números de Mersenne são aqueles da forma:

M (n) = 2n − 1

onde n é um inteiro não negativo.

• Números perfeitos são aqueles iguais à metade da soma de seus divi-


sores. Ex: 6 = 12/2 e 12 = 1 + 2 + 3 + 6

13
• Nenhum primo é perfeito.

• Resultado: 2n−1 .(2n − 1) é perfeito se 2n − 1 é primo.

• Outro resultado: Todo número perfeito par possui a forma acima. Ex:
6 = 22−1 (22 − 1)

• O que não se sabe: se existem números perfeitos ı́mpares.

• Pergunta: Quais são os números de Mersenne primos? Exemplos: quando


n = 2, 3, 5, 7, 13, 17, 19, 31, 61.... Observe que os expoentes são todos pri-
mos, mas nem todos primos fazem parte dessa lista. Por exemplo,

M (11) = 2047 = 23.89

5.3 Fórmulas exponenciais: números de Fermat


• Números de Fermat são aqueles da forma:
n
F (n) = 22 + 1

onde n é um inteiro não negativo.

• Exemplos de números de Fermat primos: n = 0, 1, 2, 3, 4. F (5) = 18446744073709551617


é composto!

• Poucos primos de Fermat são conhecidos.Até hoje, não se descobriu nen-


hum F (n) primo com n ≥ 5.

5.4 Fórmulas fatoriais

Seja p um primo positivo. Construiremos uma função semelhante ao fatorial, só


que apenas os primos são multiplicados. Vamos chamá-la de p# . Ou seja, p# é
o produto de todos os primos menores ou iguais a p. Ex: 5# = 2.3.5 = 30
Observe que se p e q são primos sucessivos, então

p# = q # .p

Estaremos interessados nos números da forma p# + 1. Embora p# + 1 nem


sempre seja primo (Ex. 13# + 1 = 30031 = 59.509), podemos mostrar que não
tem nenhum fator primo menor ou igual a p. Desta forma, temos um algoritmo
para calcular primo.
Pergunta: qual é o problema de tal algoritmo?
Observação final: p# + 1 quase nunca é primo!

14
5.5 Infinidade de primos

Teorema 8 Existem uma infinidade de primos

Prova .
Digamos que exista uma quantidade finita de primos:

{p1 , p2 , . . . , pk }

Podemos supor que esses primos estão ordenados, de modo que pk é o maior
deles. Considere o número p#
k + 1. Como vimos, esse número possui fator primo
maior que pk . ABSURDO!

5.6 Crivo de Eratóstenes

O crivo de Eratóstenes é o mais antigo dos métodos para encontrar primos.

Etapa 1: Listamos os números ı́mpares de 3 a n.

Etapa 2: Procure o primeiro número k da lista. Risque os demais números da lista,


de k em k.

Etapa 3: Repita a etapa 2 até chegar em n.

Observações:

1. Podemos parar em n...

2. Podemos começara riscar a partir de k 2 ...

5.7 Crivo de Eratóstenes revisado


n−1
Etapa 1: Crie um vetor v de 2 posições, preenchidas com o valor 1; faça P = 3.

Etapa 2: Se P 2 > n, escreva os números 2j + 1 para os quais a j-ésima entrada de


v é 1 e pare;
(P −1)
Etapa 3: Se a posição 2 de v está preenchida com 0 incremente P de 2 e volte
à Etapa 2.

Etapa 4: Atribua o valor P 2 a uma nova variável T ; substitua por zero o valor da
posição (T −1)
2 e incremente T de 2P ; repita até que T > n; incremente P
de 2 e volte à Etapa 2.

15
5.8 Exercı́cios propostos
1. Entenda e implemente o algoritmo da pag 65 do livro texto.
2. Livro texto: 1, 3 a 7, 8 e 10.

6 Aritmética modular
Aritmética modular = aritmética dos fenômenos cı́clicos.
Exemplos: Horas, dias do mês, letras do alfabeto, etc.

6.1 Relações de equivalência

Seja X um conjunto e ∼ uma relação entre elementos de X . Dizemos que ∼ é


uma relação de equivalência se, para todos x, y, z ∈ X :

Reflexiva x ∼ x.
Simétrica Se x ∼ y então y ∼ x.
Transitiva Se x ∼ y e y ∼ z então x ∼ z.

Exemplos:

• < nos inteiros não satisfaz reflexividade;


• ≤ nos inteiros satisfaz reflexividade, mas não satisfaz simetria;
• =
6 é reflexiva, simétrica mas não transitiva;
• relação de equivalência: = nos números inteiros.

Relações de equivalência: são usadas para classificar os elementos de um con-


junto em subconjuntos com propriedades semelhantes. As subdivisões de um
conjunto produzidas por uma relação de equivalência são conhecidas como classes
de equivalência. Formalmente, seja X um conjunto e ∼ uma r.e. definida em
X . Se x ∈ X então a classe de equivalência de x é o conjunto de elementos
de X que são equivalentes a x por ∼. Denotamos:

x = {y ∈ X : y ∼ x}.

Propriedades:

• Qualquer elemento de uma classe de equivalência é um representante de


toda a classe.

16
• X é a união de todas as classes de equivalência.

• Duas classes de equivalência distintas não podem ter um elemento em


comum.

O conjunto das classes de equivalência de ∼ em X é chamado de conjunto


quociente de X por ∼. Observe que os elementos do conjunto quociente são
subconjuntos de X . Isto é, o conjunto quociente não é um subcojunto de X ,
mas um subconjunto das partes de X .

6.2 Inteiros módulo n

Vamos construir uma relação de equivalência no conjunto dos inteiros. Digamos


que, pulando de n em n, todos os inteiros são equivalentes. Ou melhor: dois
inteiros cuja diferença é um múltiplo de n são equivalentes. Formalmente, dize-
mos que dois inteiros a e b são congruentes módulo n se a − b é múltiplo
de n. Escrevemos:
a ≡ b (mod n)

Exemplos:
10 ≡ 0 (mod 5) 23 ≡ 1 (mod 11)

Observação: Congruência módulo n é uma relação de equivalência:

• a ≡ a (mod n) (trivialmente)

• Se a ≡ b (mod n), então a − b é múltiplo de n. Mas b − a = −(a − b);


logo, b − a também é múltiplo de n. Portanto b ≡ a (mod n).

• Transitividade: exercı́cio.

Chamamos de Zn o conjunto de inteiros módulo n. Ou seja, se a ∈ Z, então

a = {a + kn | k ∈ Z}

Em particular, 0 é o conjunto dos múltiplos de n.


Voltemos agora ao algoritmo da divisão de Euclides. Vimos que, dados a e n
inteiros positivos, a > n, existem inteiros q e r tais que

a = n.q + r o≤r ≤n−1

Ou seja, a − r ≡ 0 (mod n) e portanto a ≡ r (mod n).


Em outras palavras,
Zn = {0, 1, . . . , n − 1}
.

17
6.3 Artimética modular

Sejam a e b classes de Zn . Então,

a+b=a+b

Exemplo:
5 + 4 ≡ 9 ≡ 1 (mod 8)
Logo,
5+4=9=1

A diferença entre duas classes é definida de maneira análoga.


A fórmula para a multiplicação das classes a e b de Zn é:

a.b = a.b

Propriedades da adição:

A1 (a + b) + c = a + (b + c).
A2 a + b = b + a.
A3 a + 0 = a.
A4 a + −a = 0.

Propriedades da multiplicação:

M1 (a.b).c = a.(b.c).
M2 a.b = b.a.
M3 a.1 = a.
AM a.(b + c) = a.b + a.c.

Exemplo: em Z6 ,
2.3 = 6 = 0!!!

6.4 Critérios de divisibilidade


• Divisibilidade por 3: 3|a se a soma de todos os algarismos de a é
divisı́vel por 3.
Prova Seja
a = an .an−1 . . . . .a1 .a0
= an .10n + an−1 .10n−1 + . . . + a1 .10 + a0

18
Como 10 ≡ 1 (mod 3),
a ≡ an + an−1 + . . . + a1 + a0 (mod 3)
Logo, a ≡ 0 (mod 3) se e somente se
an + an−1 + . . . + a1 + a0 ≡ 0 (mod 3)

Observe que podemos usar o mesmo argumento para provar que um número
inteiro é divisı́vel por 9 se a soma de seus algarismos é divisı́vel por 9
(10 ≡ 1 (mod 9)).
• Divisibilidade por 11: 11|a se a soma alternada de todos os algaris-
mos de a é divisı́vel por 11. Prova Observe que 10 ≡ −1 (mod 11).
Portanto,
10k ≡ (−1)k (mod 11)
é igual a 1 ou -1 dependendo da paridade de k. Logo,
a ≡ (−1)n .an + (−1n−1 ).an−1 + . . . + a2 − a1 + a0 (mod 11)

6.5 Potências

A aplicação mais importante de congruências no nosso curso é no cálculo de


resto da divisão de uma potência por um número qualquer.
Vamos ilustrar como isso é feito na prática através de um exemplo.
Suponhamos que o objetivo seja calcular
3515 (mod 20)
Em primeiro lugar, escrevemos o expoente 15 na base 2:
15 = 23 + 22 + 2 + 1
Logo,
3 2 2 3
3515 = 352 +2 +2+1 = 35.352 .352 .352
= 35.(35)2 .(352 )2 .((352 )2 )2
Como 35 ≡ 15 (mod 20), 152 ≡ 5 (mod 20) e 52 ≡ 5 (mod 20), temos:

2 3
3515 = 35.352 .352 .352
≡ 15.(15)2 .(352 )2 .((352 )2 )2 (mod 20)
≡ 15.5.(5)2 .((352 )2 )2 (mod 20)
≡ 15.5.5.(5)2 (mod 20)
≡ 15.5.5.5 (mod 20)
≡ 15.5 (mod 20)
≡ 15 (mod 20)

19
6.6 Equações diofantinas

Uma equação diofantina é uma equação em várias incógnitas com co-


eficientes inteiros. Por exemplo, xn + y n = z n . Estaremos interessados em
encontrar as soluções inteiras dessas equações.
É claro que tais equações podem ter infinitas soluçẽs. Por exemplo, x + y = 2.
Ou nenhuma, como no caso da equação

x3 − 117y 3 = 5

É muito fácil ver que isso é verdade através da redução módulo 9. De fato, como
117 é divisı́vel por 9,

x3 − 117y 3 ≡ x3 ≡ 5 (mod 9)

Logo, se a equação acima tivesse solução, deverı́amos ter x3 ≡ 5 (mod 9).


classes módulo 9: 0 1 2 3 4 5 6 7 8
Mas: Ou seja, x3 ≡ 5
cubos módulo 9: 0 1 8 0 1 8 0 1 8
(mod 9) não tem solução.

6.7 Divisão modular

Teorema 9 (Teorema da inversão) A classe a tem inverso em Zn se e so-


mente se a e n são primos entre si.

Prova (⇒) Suponha que a tem inverso. Então existe b tal que

a.b ≡ 1 (mod n)

Logo,
a.b + k.n = 1
e portanto mdc(a, n) = 1.
(⇐) Suponha mdc(a, n) = 1. Logo existem α e β tais que:

α.a + β.n = 1

Ou seja,
α.a ≡ 1 (mod n)
e portanto a tem inverso em Zn .
O conjunto dos elementos de Zn que têm inverso é muito importante. Vamos
denotá-lo por U(n). Em outras palavras,

U(n) = {a ∈ Z(n)|mdc(a, n) = 1}

20
No caso de n = p ser primo,

U(p) = Z(n) \ {0}

Uma propriedade importante de U(n) é que esse conjunto é fechado com


relação à multiplicação . Em outras palavras, o produto de dois elementos
de U(n) é um elemento de U(n). Em particular, podemos dividir a por b em Z(n)
somente se b ∈ U(n); nesse caso, b−1 também pertencerá a U(n) e ab ≡ a.b−1
(mod n).
Podemos utilizar o que aprendemos para resolver congruências lineares em Z(n).
Uma congruência linear é uma equação do tipo:

a.x ≡ b (mod n)

onde a, b ∈ Z. A solução dessa equação é:

x ≡ α.b (mod n)

onde α é o inverso de a módulo n.


Conclusão: Se mdc(a, n) = 1 então a congruência linear a.x ≡ b (mod n)
tem uma e só uma solução em Zn .

6.8 Exercı́cios propostos

4, 5, 6(b), 7, 10 e 11

7 Primeira Prova de Álgebra A


Questão 1 - a) Calcule d = mdc(252, 198).
b) Encontre dois números inteiros a e b tais que:

a.252 + b.198 = d (1)

Resolução: 252=198+54 54=252-198


198=3.54+36 36=198-3.54 =198-3.(252-198)
=-3.252+4.198
54=36+18 18=54-36 =252-198-(-3.252+4.198)
=4.252+(-5).198

Deste modo, mdc(252, 198) = 18 e a = 4, b = −5

21
Questão 2 - Verifique se as proposições abaixo são verdadeiras ou falsas. Dê
uma demonstração (= justificativa clara e bem escrita) ou um contra-exemplo
para justificar a sua conclusão.

(a) Se p é um número primo, então p é um número irracional.
(b) Se um número inteiro A se escreve em base 8 na forma an an−1 ...a1 a0 , com
0 ≤ ai ≤ 7, então 2|A se e somente se a0 = 0.
(c) Se p > 3 é um número primo e p ≡ a( (mod 3)), então mdc(a, 3) = 1.
(d) Todo número inteiro representável com três algarismos iguais na base 10 é
divisı́vel por 37.
(e) Se x e y são inteiros ı́mpares, então x2 + y 2 = p2 para algum primo p.
Resolução:
√ a
a) V- Suponha que existam a, b ∈ ℵ tais que p = b. Podemos supor
mdc(a, b) = 1. Logo,

p.b2 = a2
e portanto p|a2 . Pela propriedade fundamental dos primos, p|a. Logo,
existe c ∈ ℵ tal que a = pc.

p.b2 = p2 .c2 =⇒ b2 = p.c2 =⇒ p|b2 =⇒ p|b


Mas isso é um absurdo uma vez que estamos supondo mdc(a, b) = 1.

b) F - Seja A = an an−1 . . . a1 a0 um número na base 8. Então 2|A se e


somente se A ≡ 0 (mod 2). Observe que

A = an .8n + . . . + a1 .8 + a0 ≡ a0 (mod 2)
ou seja, 2|A se e somente se 2|a0 . Deste modo, 2|A se e somente se
a0 ∈ {0, 2, 4, 6}.

c) V - Se p ≡ a (mod 3), então o resto da divisão de p e a por 3 é o mesmo.


Como p é primo, p > 3, temos que

p≡1 (mod 3) ou p ≡ 2 (mod 3)


Logo, a ≡ 1 (mod 3) ou a ≡ 2 (mod 3), ou seja,

a = 3n + k, com k = 1, 2
Pelo algoritmo euclideano, mdc(a, 3) = mdc(k, 3) = 1 para k = 1, 2.

22
d) V - Seja n = aaa = a(111). Como 111 = 3.37,

aaa ≡ a(111) ≡ 0 (mod 37)

e) F - Se x e y são ı́mpares, então existem n e m tais que

x = 2n + 1, y = 2m + 1

Logo,

x2 + y 2 = 4n2 + 4n + 1 + 4m2 + 4m + 1
= 2(2n2 + 2n + 2m2 + 2m + 1)
= 2k
onde k é um número ı́mpar. Logo não existe p ∈ ℵ tal que

x2 + y 2 = p2

Observe que p não precisa ser primo: vale para qualquer número natural.

Questão 3 - Resolva um (e apenas um) dos exercı́cios abaixo:


(a) Seja p um número primo. Mostre que um inteiro positivo a é o seu próprio
inverso módulo p (ou seja, a2 ≡ 1 (mod p)) se e somente se a ≡ 1 (mod p)
ou a ≡ −1 (mod p).
(b) Calcule 1235 (mod 23).
Resolução:

a) (=⇒) Suponhamos a2 ≡ 1 (mod p). Logo,

(a2 − 1) ≡ 0 (mod p) =⇒ p|(a + 1)(a − 1)

Pela propriedade fundamental dos primos, p|(a + 1) ou p|(a − 1). Logo,

a ≡ 1 (mod p) ou a ≡ −1 (mod p)

(⇐=) Trivial!

b) Observe que 35 = 25 + 2 + 1. Logo,


5
1235 ≡ 122 .122 .12
≡ 2.6.12
≡ 2.3
≡ 6 (mod 23)

23
8 Indução e Fermat

8.1 Indução finita

Seja P (n) uma proposição que afirma que uma determinada propriedade vale
para cada número natural n. Por exemplo:

• Se p é um número primo, então np − n é divisı́vel por p para todo natural


n.
n(n+1)
• A soma de 1 até n é 2

Para provar P (n), em geral usamos o princı́pio da indução finita :


Princı́pio da indução finita Para que uma proposição P (n) seja verdadeira
para todo n natural, basta que:

1. P (1) seja verdadeira.


2. Se P (k) for verdadeira para algum número natural k, então P (k + 1)
também é verdadeira.

8.2 Pequeno teorema de Fermat

Lema 10 Seja p um número primo e a, b inteiros. Então,


(a + b)p ≡ ap + bp (mod p)

Prova Veja livro texto, pag 94.

Teorema 11 (Teorema de Fermat) Seja p um número primo e a um número


inteiro. Então
ap ≡ a (mod p).

Prova

• Se n = 1, então 1p ≡ 1 (mod p) trivialmente.


• Suponhamos que np ≡ n (mod p) para algum n inteiro positivo. Usando
o lema anterior,
(n + 1)p ≡ np + 1p ≡ np + 1 (mod p)
Como pela hipótese de indução temos np ≡ n (mod p),
(n + 1)p ≡ np + 1 ≡ n + 1 (mod p)
Como querı́amos demonstrar.

24
Caso geral: veja pag 95 do livro texto.

Teorema 12 (Teorema de Fermat II) Seja p um número primo e a um in-


teiro que não é divisı́vel por p. Então,

ap−1 ≡ 1 (mod p).

Prova Como mdc(a, p) = 1, existe a′ tal que

aa′ ≡ 1 (mod p)

Multiplicando ambos os membros de ap ≡ a (mod p). por a′ , obtemos:

a′ .a.ap−1 ≡ a′ .a (mod p).

Logo,
ap−1 ≡ 1 (mod p).

Podemos simplificar algumas contas usando o Teorema de Fermat. De fato,


sejam p primo, a inteiro tal que mdc(a, p) = 1 e k um número inteiro tal que
k ≥ p − 1. Dividindo k por p − 1,

k = (p − 1).q + r 0 ≤ r < (p − 1)

Logo,
ak ≡ a(p−1).q+r ≡ (ap−1 )q .ar (mod p).
p−1
Mas (a ) ≡ 1 (mod p) e portanto

ak ≡ ar (mod p).

8.3 Exercı́cios propostos

1, 3, 46, 7, 8, 12

9 Pseudoprimos
Nesta seção, veremos com usar o pequeno teorema de Fermat para identificar
que um número é composto sem fatorá-lo .

25
9.1 Pseudoprimos

De acordo com o teorema de Fermat, se p é primo e a é um inteiro qualquer,


então ap ≡ a (mod p). Desta forma, é claro que, se n é um número composto,
então existe um inteiro b tal que bn \ ≡ b (mod n) (usaremos o sı́mbolo \ ≡ para
significar não equivalente). Observe que, na prática, só precisamos considerar
os inteiros b no intervalo 1 < b < n − 1 (por que?).
Desta forma, temos um método para determinar se um número é composto sem
termos que fatorá-lo:
Teste Se n, b são números inteiros, n > 0 e 1 < b < n − 1, tais que bn−1 \ ≡ 1
(mod n), então n é composto.
A pergunta que surge então é: o teste acima é um procedimento de decisão?
Isto é, o fato de não encontrarmos tal b significa que n é primo?
Resposta: Observe que, se n é composto, então existe p primo, 1 < p < n − 1
tal que p|n. Logo, mdc(p, n) = p 6= 1 e portanto p não é inversı́vel módulo n.
Desta forma, pn−1 \ ≡ 1 (mod n).
É claro que esse não é um método eficiente para testar primalidade uma vez que
é um método de exaustão.
Outra pergunta interessante que surge é a seguinte: será que, se um número
ı́mpar n que satisfaça:
bn−1 ≡ 1 (mod n)
para algum 1 < b < n−1 é primo? Infelizmente, a resposta é não. Por exemplo,
2340 ≡ 1 (mod 341) mas 341 = 11.31 não é primo! Esses “falsos primos” são
conhecidos como pseudoprimos. Ou seja, um pseudoprimo n para a base b
é um número inteiro positivo ı́mpar e composto tal que

bn−1 ≡ 1 (mod n)

Apesar de às vezes dar errado, esse teste (chamado de teste de Leibniz) é muito
útil. Tambeém é possı́vel melhorar o resultado do teste se testarmos para duas
bases.

Exemplo 6 Existem 50.847.534 primos entre 1 e 109 ; existem apenas 5597


pseudoprimos na base 2 e 1272 pseudoprimos para as bases 2 e 3.

9.2 Números de Carmichael

Como vimos anteriormente, não existem números que sejam pseudoprimos para
todas as bases. Entretanto, pode ocorrer que um número composto n seja
pseudoprimo para todas as bases b tais que mdc(b, n) = 1.
Dizemos que um número composto ı́mpar é um número de Carmichael se
bn ≡ b (mod n).

26
Os números de Carmichael possuem duas propriedades muito interessantes,
dadas pelo teorema baixo:

Teorema 13 (Teorema de Korselt:) Um inteiro positivo ı́mpar n é um número


de Carmichael se, e somente se, cada fator primo p de n satisfaz as seguintes
condições:

1. p2 não divide n;
2. p − 1 divide n − 1.

Prova (=⇒) Seja p um fator primo de n. Então,

bn ≡ b (mod p)

De fato, se b é divisı́vel por p então ambos os membros da equivalência são


congruentes a zero. Se não, pelo teorema de Fermat temos:

bp−1 ≡ 1 (mod p)

Pela condição (2) do teorema, n − 1 = (p − 1).q para algum q. Logo,

bn ≡ (bp−1 )q .b ≡ b (mod p)

Por (1), temos que n = p1 . . . pk com p1 < p2 < . . . < pk . Como os primos são
distintos, bn − b é divisı́vel pelo produto p1 .p2 . . . . .pk = n. Em outras palavras,

bn ≡ b (mod n)

e portanto n é um número de Carmichael.


(⇐=) Seja n um número de Carmichael e suponhamos que exista p primo tal
que p2 |n. Escolha b = p. Então:

pn − p = p(pn−1 − 1)

Mas p não divide pn−1 − 1, logo p2 não pode dividir pn − p. Portanto, n não
pode dividir pn − p. Em outras palavras, p ≡ p (mod n). Absurdo.
O restante da demonstração depende do teorema da raiz primitiva, que só será
vista no capı́tulo 10...
Observações:

• Para verificar que um número é de Carmichael usando o teorema acima


necessitamos fatorá-lo...
• Muitos números de Carmichael possuem fatores primos pequenos!
• Existem infinitos números de Carmichael.
• Entre 1 e 109 existem 50.847.534 primos e 646 números de Carmichael.

27
9.3 Teste de Miller

Teorema de Fermat: detecta números compostos com uma certa eficiência, mas
não é um bom teste de primalidade.
Teste de Miller: Calcula-se a sequência de potências módulo n:
k
bq , b2q , . . . , b2 q

onde n − 1 = 2k q.
O fato é que, se n é primo, então:
k
b2 q
≡ bn−1 ≡ 1 (mod n)
j
Digamos que j é o menor expoente tal que b2 q ≡ 1 (mod n). Se j ≥ 1
podemos escrever
j j−1 j−1
b2 q − 1 = (b2 q − 1)(b2 q + 1)
j j−1
Se n é primo e divide b2 q −1, então n deve dividir (b2 q
+1) pela minimalidade
de j. Logo,
j−1
b2 q − 1 ≡ −1 (mod n)
Ou seja, uma das potências
k
bq , b2q , . . . , b2 q

deve ser congruente a −1 módulo n. Se j = 0, então temos apenas que bq ≡ 1


(mod n). Se nada disso acontecer, então n deve ser composto.

Teste de Miller.

Etapa 1 Divida n − 1 por 2 até encontrar q ı́mpar e k tais que n − 1 = 2k q.


Etapa 2 Faça i = 0 e r = resto de bq por n.
Etapa 3 Se i = 0 e r = 1 ou i ≥ 0 e r = n − 1: teste inconclusivo.
Etapa 4 Faça i = i + 1 e r = r2 onde r2 é o resto da divisão de r2 por n.
Etapa 5 Se i < k volte à etapa 3; senão: n é composto.

Exemplo 7 Tome o número de Carmichael 561. Temos que 560 = 24 .35.


Calculando as sequências de restos módulo 561 das potências de 2:

expoentes 35 2.35 22 .35 23 .35


restos 263 166 67 1

28
Logo 561 tem que ser composto.

Se um número composto n tem resultado inconclusivo para o teste de Miller


com respeito a uma base b, dizemos que n é um pseudoprimo forte para a
base b. Observe que pseudoprimo forte −→ pseudoprimo.
Existem 1282 pseudoprimos fortes entre 1 e 109 .

9.4 Primalidade e computação algébrica

É importante ressaltar que o teste de Miller é muito usado na prática. O que


se faz para ter maior garantia do resultado é fazer o teste para diversas bases.
É assim com o Maple, ScratchPad - IBM, Axiom 1.1 - IBM.
Vale a observação: dado um número finito qualquer de bases, existem infinitos
números de Carmichael que são pseudoprimos fortes para todas essas bases.

9.5 Exercı́cios propostos

2, 5, 7, 8, 10

10 Teorema de Euler
O pequeno teorema de Fermat nos diz como trabalhar com certas congruências
envolvendo expoentes quando o módulo é primo. Nessa seção, veremos como
lidar com congruências módulo um número composto.

10.1 Função de Euler

Definição. Seja n um inteiro positivo. A função de Euler φ(n) é definida


como o número de inteiros positivos não excedendo n que são relativamente
primos com n.
A tabela abaixo apresenta os valores de φ(n) para 1 ≤ n ≤ 12.

n 1 2 3 4 5 6 7 8 9 10 11 12
φ(n) 1 1 2 2 4 2 6 4 6 4 10 4

Na seção de aritmética modular, estudamos o conjunto U(n), o conjunto dos


elementos de Zscrn que têm inverso. Vimos que

U(n) = {a ∈ Zn : mdc(a, n) = 1}

29
Desta forma, φ(n) nada mais é do que o número de elementos de U(n).
Vamos ver como calcular φ(n). Começamos com alguns casos especiais. Seja p
um número primo. Então todos os inteiros positivos menores que p são primos
com p. Logo
φ(p) = p − 1

Também é fácil calcular φ(pk ). Observe que mdc(a, pk ) = 1 se e somente se


p não divide a. Então basta contar os inteiros menores que pk que não são
divisı́veis por p. Se 0 ≤ a < pk é divisı́vel por p, então
a = p.b onde 0 ≤ b < pk − 1
Portanto há pk−1 inteiros positivos menores que pk que são divisı́veis por p.
Logo há pk − pk−1 que não são divisı́veis por p. Ou seja,
φ(pk ) = pk−1 (p − 1)

Para obtermos a fórmula geral, é necessário provar o seguinte resultado:

Teorema. Se m, n são inteiros positivos tais que mdc(m, n) = 1, então


φ(mn) = φ(m).φ(n)

A demonstração desse teorema é trabalhosa (mas não difı́cil) e portanto não


faremos aqui.

Exemplo 8 φ(100) = φ(22 ).φ(52 ) = (2.1).(5.4) = 40

Pelo teorema acima temos que, se n = pe11 . . . . .pekk , então,


φ(n) = pe11 −1 . . . . .pekk −1 (p1 − 1). . . . .(pk − 1)

10.2 Teorema de Euler

Vai ser necessário, para decodificação de mensagens, saber calcular a função


de Euler. Também vamos ter que aplicar o teorema de Euler. O teorema
de Euler é uma generalização do teorema de Fermat para o caso em que o
módulo não é primo:

Teorema de Euler. Se n é um inteiro positivo e a é um inteiro tal que


mdc(a, n) = 1, então
aφ(n) ≡ 1 (mod n)

Antes de provar esse teorema, vamos apresentar um exemplo.

30
Exemplo 9 Temos que U(8) = {1, 3, 5, 7} e portanto φ(8) = 4. Observe que,
se a, b, c ∈ U(8), então a.b ∈ U(8) e, se c 6= b, então

a.b\ ≡ a.c (por que?)

Para ver como isso funciona, tome a = 3. Então,

3.1 ≡ 3 (mod 8)
3.3 ≡ 1 (mod 8)
3.5 ≡ 7 (mod 8)
3.7 ≡ 5 (mod 8)

Logo,
(3.1).(3.3).(3.5).(3.7) ≡ 1.3.5.7 (mod 8)
e portanto,
34 .1.3.5.7 ≡ 1.3.5.7 (mod 8)
Como mdc(1.3.5.7, 8) = 1, podemos cortar o termo comum dos dois lados da
equivalência:
34 ≡ 1 (mod 8)

Teorema 14 (Teorema de Euler) Se n é um inteiro positivo e a um inteiro


tal que mdc(n, a) = 1, então

aφ(n) ≡ 1 (mod n)

Prova Escrevendo U(n) = {b1 , . . . , bφ(n) }, temos que:

(a.b1 ). . . . .(a.bφ(n) ) ≡ b1 . . . . .bφ(n) (mod n)

Logo,
aφ(n) .b1 . . . . .bφ(n) ≡ b1 . . . . .bφ(n) (mod n)
Como mdc(b1 . . . . .bφ(n) , n) = 1, podemos cortar o termo comum dos dois lados
e portanto,
aφ(n) ≡ 1 (mod n)

10.3 Exercı́cios propostos

Capı́tulo 8: 4, 6, 8, 9, 10, 18

31
10.4 Tabela Hashing

Uma universidade deseja estocar um arquivo para cada um de seus estudantes


no seu computador. O número identificador, ou chave para cada arquivo é o
número do CPF do estudante. O CPF é um inteiro de 11 dı́gitos, portanto
é praticamente impossı́vel reservar uma posição de memória para cada CPF
possı́vel. Deve-se encontrar um método sistemático para arranjar esses arquivos
na memória, usando um número razoável de posições de memória. De outra
forma, ficaria impossı́vel acessar os arquivos...
Um desses métodos é utilizando a tabela hashing , baseada em funções
hashing . Existem várias propostas para funções hashing. Vamos discutir
(brevemente) o tipo mais utilizado.
Seja k a chave do arquivo a ser estocado e seja n um inteiro positivo. Definimos
a função hashing h(k) por
h(k) ≡ k (mod n)
onde 0 ≤ h(k) < n. É claro que devemos escolher um n adequado de modo que
os arquivos fiquem distribuı́dos de uma maneira razoável entre as n posições
possı́veis de memória.
Por exemplo, n não deve ser uma potência de 10 (10r ) simplesmente porque o
valor da função h seria os r últimos dı́gitos da chave.
Outro exemplo de uma escolha ruim é quando n|10m ± a onde a e m são pe-
quenos. Por exemplo, se n = 111|(103 − 1) = 999 então 103 ≡ 1 (mod n) e
portanto os números:
64121284868 e 64184821268
vão para a mesma posição de memória.
Para evitar esses problemas, n deve ser um número primo próximo do número
de posições disponı́veis. Por exemplo, se existem 5000 posições de memória para
o armazenamento de 2000 arquivos de estudantes, podemos escolher n = 4969.
Claro que, mesmo assim, colisões podem ocorrer. Existem várias heurı́sticas
para tratamento de colisões. O método mais usado é o de escolher uma posição
livre. Existem várias maneiras de fazer isso e as mais complicadas são as mais
eficientes. Eu poderia passar o dia falando sobre elas, mas vou citar apenas
uma, a mais simples. Consiste em tomar:
hj (k) ≡ h(k) + j (mod n)
Desta forma, a chave k é alocada na posição mais próxima possı́vel de h(k).
A eficiência desse método é realmente baixa, pois tende a haver um engarrafa-
mento.
Na prática, o mais fácil é “atachar” uma lista a cada posição de memória. Dessa
forma, procede-se por busca sequencial.

32
11 Criptografia RSA

11.1 Pré-codificação

Em primeiro lugar, devemos converter a mensagem em uma sequência de números.


Essa primeira etapa é chamada de pré-codificação. Há várias maneiras de se
fazer isso. Aqui vamos supor que o texto não contém acentuação, pontuação,
números etc, apenas as letras A a Z (maiúsculas). Também vamos adicionar
espaços em branco entre palavras, que será substituı́do pelo número 99. A letra
A será convertida no número 10, B será 11 e assim por diante, até o Z corre-
spondendo ao número 35. Observe que cada letra corresponde a um número
com exatamente dois algarismos. Isso evita ambiguidades.
A chave pública é um número n = p.q, onde p e q são primos. Antes de começar
devemos, então escolher esses números. O último passo da pré-codificação é
quebrar a mensagem em blocos. Esses blocos devem ser números menores
que n. A maneira de escolher os blocos não é única, mas é importante evitar
duas situações:

• Nenhum bloco deve começar com o número 0 (problemas na decodi-


ficação).
• Os blocos não devem corresponder a nenhuma unidade linguı́stica (palavra,
letra, etc). Assim a decodificação por contagem de frequência fica im-
possı́vel.

11.2 Codificando e decodificando

Para codificar a mensagem precisamos de n = p.q e de um inteiro positivo e que


seja inversı́vel módulo φ(n). Em outras palavras,

mdc(e, φ(n)) = mdc(e, (p − 1).(q − 1)) = 1

Chamaremos o par (n, e) a chave de codificação do sistema RSA.


Codificaremos cada bloco de mensagem separadamente e a mensagem codificada
será a sequência de blocos codificados.
Importante: Os blocos já codificados não poderão ser reunidos de modo a formar
um longo número. Isso tornaria a decodificação impossı́vel!
Vamos agora mostrar como codificar cada bloco b. Chamaremos o bloco codifi-
cado de C(b). Em primeiro lugar, lembre-se que b é menor que n. Então:

C(b) ≡ be (mod n)

Onde 0 ≤ C(b) < n.

33
Exemplo 10 Considere a frase Paraty é linda . Convertendo em números,

2510271029349914992118231310

Agora devemos escolher n. Vamos começar com um número pequeno, por ex-
emplo
n = 11.13 = 143
Podemos então quebrar a mensagem acima em blocos, que devem ter valor
menor que 143:

25 − 102 − 7 − 102 − 93 − 49 − 91 − 49 − 92 − 118 − 23 − 13 − 10

Então temos que φ(143) = 10.12 = 120 e portanto e deve ser um número que
não divide 120. O menor valor possı́vel é 7. Logo,
2
C(25) ≡ 257 ≡ 252 .252 .25 (mod 143)
2
≡ 252 .53.25 (mod 143)
≡ 532 .53.25 (mod 143)
≡ 92.53.25 (mod 143)
≡ 14.25 (mod 143)
≡ 64 (mod 143)

Procedendo dessa maneira com todos os blocos, obtemos a seguinte mensagem


cifrada:

64 − 119 − 6 − 119 − 102 − 36 − 130 − 36 − 27 − 79 − 23 − 117 − 10

Vejamos agora como proceder para decodificar um bloco de mensagem codifi-


cada. A informação que precisamos para decodificar está contida no par (n, d),
onde d é o inverso de e módulo φ(n). Chamaremos (n, d) de chave de de-
codificação e de D(c) o resultado do processo de decodificação. D(c) é dado
por:
D(c) ≡ cd (mod n)
onde 0 ≤ D(c) < n.
Observe que é muito fácil calcular d, desde que φ(n) e e sejam conhecidos: basta
aplicar o algoritmo euclideano estendido. Entretanto, se não conhecemos p e q
é praticamente impossı́vel calcular d.
Voltando ao nosso exemplo, temos que n = 143 e e = 7. Para calcular d, usamos
o algoritmo euclideano estendido:

120 = 7.17 + 1 =⇒ 1 = 120 + (−17).7

Logo o inverso de 7 módulo 120 é −17. Como d deve ser usado como um
expoente, precisamos que d seja positivo. Logo tomamos d = 120 − 117 = 103.

34
11.3 Funciona?

A pergunta óbvia que surge agora é:

D(C(b)) = b?

Ou seja, decodificando um bloco de mensagem codificada, encontramos um bloco


da mensagem original? Porque senão todo nosso esforço foi sem sentido...
Vamos mostrar nessa seção que a resposta para a pergunta acima é sim .
Consideremos então n = p.q. Vamos provar que

DC(b) ≡ b (mod n)

E por que não a igualdade? Observe que DC(b) e b são menores que n − 1.
Por isso escolhemos b menor que n e mantivemos os blocos separados depois da
codificação!
Por definição, temos que

DC(b) ≡ (be )d ≡ be.d (mod n)

Mas d é o inverso de e módulo φ(n). Logo existe inteiro k tal que ed = 1+kφ(n).
Logo,
bed ≡ b1+kφ(n) ≡ (bφ(n) )k .b (mod n)
Se mdc(b, n) = 1, então podemos usar o teorema de Euler:

bed ≡ (bφ(n) )k .b ≡ b (mod n)

Se b e n não são primos entre si, obderve que n = p.q, p e q primos distintos.
Logo,
bed ≡ b1+kφ(n) ≡ (b(p−1) )k.(q−1) .b (mod p)
Se mdc(b, p) = 1, então podemos usar o teorema de Fermat (bp−1 ≡ 1 (mod p)).
Se não, temos que p|b e portanto

bed ≡ b ≡ 0 (mod p)

Logo,
bed ≡ b (mod p)
qualquer que seja b.
Fazemos o mesmo para o primo q, obtendo:

bed ≡ b (mod q)

Portanto,
bed ≡ b (mod p.q)
como querı́amos.

35
11.4 Porque o RSA é seguro

Como já vimos, o par de codificação (n, e) é conhecido e acessı́vel a qualquer


usuário. O RSA só é seguro se for difı́cil calcular d quando apenas esse par é
conhecido.
Observe que só sabemos calcular d se soubermos o valor de φ(n), cujo cálculo
depende da fatoração de n. A pergunta que surge então é: será que não existe
outro processo para calcular d e φ(n)? Por exemplo, o que aconteceria se alguém
inventasse um método para calcular φ(n) a partir de n e e? A resposta é que
terı́amos, então, um algoritmo rápido de fatoração. Observe que
φ(n) = (p − 1).(q − 1) = pq − (p + q) + 1 = n − (p + q) + 1
Logo, (p + q) = n − φ(n) + 1 é conhecido. Contudo,
(p + q)2 − 4n = (p2 + q 2 + 2pq) − 4pq = (p − q)2
Logo, p
p−q = (p + q)2 − 4n
que também é conhecido. Ou seja, conhecemos p+q e p−q. Portanto conhecemos
p e q e fatoramos n!
Deste modo, conhecer φ(n) sem fatorar n significa que, na verdade, sabemos
fatorar n!
Outro jeito de quebrar o RSA seria achar um algoritmo que calcule d diretamente
a partir de n e e. Como ed ≡ 1 (mod φ(n)), isto implica que conhecemos um
múltiplo de φ(n). Isso também é suficiente para fatorar n (prova complicada).
A última alternativa seria achar b a partir da forma reduzida de be módulo n
sem achar d. Bom, ninguém conseguiu fazer isso até agora... Acredita-se que
quebrar o RSA e fatorar n sejam problemas equivalentes, apesar disso não ter
sido demonstrado.

11.5 Escolhendo primos

Suponha que desejamos implementar o RSA de chave pública (n, e), de modo que
n seja um inteiro com aproximadamente r algarismos. Para construir n, escolha
r
4r 45r
um primo p entre 10 e 100 algarismos e, em seguida, escolha q próximo de 10p . O
tamanho da chave recomendado atualmente para uso pessoal é de 768 bits. Isso
significa que n terá aproximadamente 231 algarismos. Para construir tal número
precisamos de dois primos de, digamos, 104 e 127 algarismos respectivamente.
Outra coisa a ser observada é que os números p − 1, q − 1, p + 1, p − 1 não tenham
fatores primos pequenos, pois senão seria fácil fatorar n.
Para encontrar p e q, seguiremos a seguinte estratégia:

1. Tome um número s ı́mpar.

36
2. Verifique se n é divisı́vel por um primo menor que 5.000.

3. Aplique o teste de Miller a s usando como base os 10 primeiros primos.

Encontrar tais primos pode ser um processo trabalhoso. Por exemplo, se x é


um número da ordem de 101 27, no intervalo entre x e x + 104 existem aproxi-
madamente 34 primos dentre 560 números que passam a etapa (1) da estratégia
acima...

11.6 Assinaturas

Apenas codificar mensagens não basta, em geral, pois o sistema é de chave


pública. Ou seja, qualquer pessoa pode codificar uma mensagem usando uma
chave alheia. Por exemplo, um haker poderia facilmente mandar instruções ao
banco para que o seu saldo bancário fosse transferido para uma outra conta.
Por isso, o banco precisa de uma garantia de que a mensagem teve origem em
um usuário autorizado. Ou seja, a mensagem tem que ser assinada .
Vamos chamar de Cm e Dm as funções de codificação e decodificação do Mário
e de Ca e Da as funções de codificação e decodificação do Allan. Seja b um
bloco de mensagem que o Mário deseja mandar para o Allan. Para mandar
uma mensagem assinada, ao invés de Ca (b), o Mário envia

Ca (Dm (b))

Ou seja, primeiro ele “decodifica” a mensagem como só ele pode fazer, depois ele
codifica o resultado, como só o Allan pode ler. Para ler a mensagem, primeiro o
Allan aplica Da e depois Cm . Observe que Cm é público. Se a mensagem fizer
sentido, é certo que a origem foi mesmo o Mário!
Mas cuidado ! Esse sistema pode ser usado para quebrar o RSA, como em
1995 por um consultor em assuntos de segurança de computadores...

11.7 Exercı́cios propostos

Capı́tulo 11: 1, 2, 3, 4, 6.

12 1o trabalho prático
O trabalho tem como objetivo a criação de dois números primos grandes (entre
20 e 30 bits). Para isso:

• Gere dois números ı́mpares m e k da magnetude acima, de modo que não


sejam muito próximos um do outro.

37
• Verifique se m, k são divisı́veis por um primo menor que 5.000.

• Aplique o teste de Miller a m, k usando como base os 10 primeiros primos


(se você quiser ter uma certeza maior sobre o resultado, façø teste para
mais primos).

Depois calcule n = m.k e aplique os algoritmos da fatoração e de Fermat a n


para ver se sua chave pública é facilmente quebrada.
O trabalho deverá ser entregue no dia 06/08/2002 (sem falta!) e deverá
constar de:

• Parte escrita de no máximo duas páginas digitadas. Essa parte de-


verá conter os resultados do trabalho juntamente com a análise desses
resultados (em especial, se foi fácil quebrar a sua chave ou não).

• Código impresso comentado . Evitem C+ +, por favor!

• Disquete com o executável do programa. Este também pode ser enviado


por e-mail. Lembrem-se que eu posso rodar apenas programas em Delphi
(4.0) ou qualquer outra linguagem que rode nas estacoes do DCC. Então
evitem artifı́cios gráficos sofisticados...

13 Raı́zes primitivas

13.1 Teste de Lucas

Para determinar se n é primo, podemos verificar se φ(n) = n − 1. Ou seja, se


mdc(a, n) = 1 para todo a menor que n. Isso só é possı́vel se n é ı́mpar. Logo
precisamos encontrar um jeito de calcular φ(n) sem fatorar n. Mas já vimos
que isso é impossı́vel...

Teorema da raiz primitiva. Se p é um primo, existe b ∈ Zn tal que

bp−1 ≡ 1 (mod p)

mas
br \ ≡ 1 (mod p)
se r < p − 1.

Em geral, chamaremos de ordem do elemento b em Zn o número k tal que


bk ≡ 1 (mod n) e br \ ≡ 1 (mod n) se r < k. Observe que se n é primo e
1 < b < n, então a ordem de b é p − 1.

38
Teorema de Lagrange. A ordem de b tem que dividir a ordem de U(n), que
é igual a φ(n).

Logo, dado n ı́mpar, se existe b tal que bn−1 ≡ 1 (mod n) e bt \ ≡ 1 (mod n)


se t < n − 1 então n é primo pois terı́amos n − 1 ≤ φ(n) ≤ n − 1.
De acordo com o teorema da raiz primitiva, se n é primo, tal b sempre existe.
Encontrá-lo é uma questão de sorte...
Para aplicar isso à primalidade, precisamos encontrar uma maneira eficiente de
mostrar que a ordem de um elemento de U(n) é exatamente n − 1.

Teste de Lucas. Sejam n ´ impar e 1 ≤ b ≤ n − 1. Se

bn−1 ≡ 1 (mod n)

e n−1
b p \ ≡ 1 (mod n)
para cada fator primo de n − 1, então n é primo.
Demonstração: Veja o livro texto pag 168.

Continua... Aguardem!

14 Sistemas de congruências
O objetivo dessa seção é estudar a solução de sistemas de equações lineares. A
aplicação para criptografia é o desenvolvimento de um método para partilhar
senhas.

14.1 Equações lineares

Já estudamos o caso de uma equação linear

ax ≡ b (mod n)

Se a possui um inverso α em Zn , então multiplicando ambos os lados da equação


acima por α:
α(ax) ≡ αb (mod n)
x ≡ αb (mod n)
Em particular, se n é primo e a\ ≡ 0 (mod n), então a equação acima sempre
tem solução.

39
Se a não tem inverso em Zn , então mdc(a, n) = d 6= 1. Logo, a equação:
ax − ny = b
só tem solução quando b é divisı́vel por d.
Suponhamos então que d divide b. Escreveremos a = da′ , b = db′ e n = dn′ .
Cancelando os d’s, chegamos à seguinte equação:
a′ x − n′ y = b′
Ou seja,
a′ x ≡ b′ (mod n′ )
Observe que agora mdc(a′ , n′ ) = 1, e essa equação sempre tem solução.

Exemplo 11 Seja 6x ≡ 4 (mod 8). Dividindo pelo mdc(6, 8) = 2, obtemos


3x ≡ 2 (mod 4)
Logo a solução procurada é:
x ≡ 2 (mod 4)
Mas observe que o módulo mudou de 8 para 4... Para consertar isso, vamos
escrever a expressão acima em uma expressão de inteiros:
x = 2 + 4k
Duas possibilidades:

• k é par. Nesse caso, x ≡ 2 (mod 8) e 2 é uma solução.


• k é ı́mpar (k = 2m + 1). Nesse caso, x ≡ 6 (mod 8) e 6 é outra solução.

Ou seja, uma equação linear possui mais de uma solução.

14.2 Um exemplo astronômico

Três satélites passarão sobre o Rio essa noite. O primeiro à uma hora , o
segundo às 4 horas e o terceiro às 8 horas da manhã. O primeiro leva 13 horas
para completar uma volta em torno da terra, o segundo 15 horas e o terceiro 19
horas. Determine quantas horas decorrerão, à partir de meia noite, até que os
três satélites passem ao mesmo tempo sobre o Rio.
Montagem matemática: seja x é o número de horas, contadas a partir da meia
noite de hoje, quando os três satélites passarão juntos sobre o Rio. Então:
x ≡ 1 (mod 13)
x ≡ 4 (mod 15)
x ≡ 8 (mod 19)

40
Podemos re-escrever a primeira equação cmo x = 1 + 13t, Substituindo a
primeira equação na segunda, obtemos:

t ≡ 6 (mod 15)

Logo x = 79 + 195u. Substituindo essa equação na terceira:

u ≡ 1 (mod 19)

Logo,
x = 79 + 195u
= 274 + 3705v
Logo os satélites passarão juntos pela primeira vez 274 horas depois da meia
noite de hoje.

14.3 Algoritmo chinês do resto

Observe que, para resolver o problema dos satélites, resolvemos as duas primeiras
equações, obtendo x = 79 + 195u. Isso corresponde a uma nova equação, x ≡ 79
(mod 195). Em geral, a solução de um sistema de muitas equações é obtida
através da solução de vários sistemas de duas equações. Desta forma, vamos
analisar apenas o algoritmo correspondente á solução de um sistema de duas
equações.
Considere então o sistema
x ≡ a (mod m)
x ≡ b (mod n)

Podemos re-escrever a primeira equação na forma:

x = a + my

Substituindo x na segunda equação, obtemos:

my ≡ (b − a) (mod n)

Sabemos que essa equação tem solução se e somente se o mdc(n, m) divide b − a.


Vamos assumir que mdc(n, m) = 1. Seja então α o inverso de m módulo n.
Então:
y ≡ α(b − a) (mod n)
y = α(b − a) + nz
x = a + mα(b − a) + mnz
x = a(1 − mα) + mαb + mnz
x = aβn + mαb + mnz
Observe que essa solução é única. Temos então o seguinte teorema:

41
Teorema Chinês do resto. Sejam n1 , . . . , nk inteiros positivos, dois a dois
primos entre si. Então o sistema

x ≡ a1 (mod n1 )
..
.
x ≡ ak (mod nk )

sempre tem uma solução única em Zn1 ...nk .

14.4 Módulos não co-primos

Analisaremos esse caso através de um exemplo. Considere o sistema:

x ≡ 3 (mod 12)
x ≡ 19 (mod 8)

Da primeira equação, obtemos x = 3 + 12y. Substituindo isso na segunda


equação, temos 12y ≡ 16 (mod 8). Dividindo essa equação por 4, obtemos
3y ≡ 4 (mod 2). Logo,
x ≡ 3 (mod 24)
Observe que 24 é o mmc entre 8 e 12...

14.5 Partilha de senhas

Suponha que que desejemos partilhar uma senha s entre n pessoas, de modo
que a cada pessoa seja dado um elemento (uma parte) da senha. Esse elemento
é tal que é escolhido de um conjunto S de n pares de inteiros positivos de modo
que, para um inteiro positivo k ≤ n previamente escolhido temos:

1. qualquer subconjunto de S com k elementos permite determinar s facil-


mente;
2. é muito difı́cil determinar s conhecendo menos de k elementos de S.

Começamos escolhendo um conjunto L de n inteiros positivos, dois a dois primos


entre si. Seja N o produto dos k menores números de L e M o produto dos
k − 1 maiores números de L. Dizemos que esse conjunto tem limiar k se

N >s>M

Observe que essa condição implica que o produto de k ou mais elementos de L


é sempre maior que N e o produto de menos de k elementos é sempre menor
que M. O conjunto S será formado pelos pares da forma (m, sm ) onde m ∈ L e
sm é a forma reduzida de s módulo m. Observe que limiar k ≥ 1 implica s > m
para qualquer m ∈ L. Logo sm < s para qualquer m ∈ L.

42
Suponhamos que sejan conhecidos, em um dado momento, t elementos, ≥ k.
Denotaremos esses pares por (m1 , s1 ), . . . , (mt , st ). Vamos resolver o sistema de
congruências:
x ≡ s1 (mod m1 )
x ≡ s2 (mod m2 )
...
x ≡ st (mod mt )
obtendo x0 como solução. Pelo teorema chinês do resto,

x0 ≡ s (mod m1 . . . . .mt )

Por que? Sabemos que, como t ≥ k,

m1 . . . . .mt ≥ N > s

Pelo teorema chinês do resto, o sistema acima tem uma única solução menor
que m1 . . . . .mt . Mas s também é solução do sistema e s < m1 . . . . .mt . Logo
s = x0 .
Observações:

1. É possı́vel escolher os módulos de modo que fique praticamente impossı́vel


encontrar s através de uma busca.
2. É sempre possı́vel escolher um conjunto L que satisfaça todas as condições.

Exemplo 12 Digamos que em um banco há 5 funcionários e pelo menos 2 têm


que estar presentes para que o cofre seja aberto. Logo o conjunto L deve ter
5 elementos, e seu limiar deve ser 2. Uma escolha possı́vel escolhendo apenas
primos pequenos é
L = {11, 13, 17, 19, 23}
O valor de s pode ser escolhido como sendo qualquer inteiro no intervalo que
vai de 23 a 143. Digamos s = 30. Então:

S = {(11, 19), (13, 17), (17, 13), (19, 11), (23, 7)}

Se os funcionários que possuem as senhas (17, 13) e (23, 7) estão no banco, para
obter a senha é preciso resolver o sistema
x ≡ 13 (mod 17)
x ≡ 7 (mod 23)

A solução é x = 30 + 391k...

14.6 Exercı́cios propostos

1,2,4

43
15 Lógica e ciência da computação

15.1 Motivação

Lógica em ciência da computação:

• Primeira abordagem computação-como-modelo: computações são estru-


turas matemáticas contendo nodos, estados e transições e a lógica constrói
afirmativas sobre essas estruturas.

• Segunda abordagem computação-como-dedução: estados são descritos através


de um conjunto de proposições e mudanças nos estados são modelados por
mudanças nas proposições dentro de uma derivação (ou seja, por passos
na construção de uma prova)

A primeira abordagem tem sido amplamente estudada e faz uso de tópicos


da matemática como teoria de conjuntos, teoria das categorias, álgebras, etc.
para modelar computações. Em geral, as estruturas matemáticas utilizadas são
complexas porque devem lidar com o conceito de infinitude.
A segunda abordagem, apesar de lidar com estruturas mais simples (que rara-
mente fazem referência ao infinito) e de estar mais intimamente ligada à com-
putação, tem merecido pouca ou nenhuma atenção nos últimos tempos.
Apenas após recentes pesquisas na área de teoria de provas e programação lógica
observou-se um crescimento do estudo nessa área de pesquisa.
Lógicas expressivas como lógica linear (e Forum - linguagem de programação
baseada em lógica linear) passaram a ser utilizadas para modelar estados, transições
de estado e algumas primitivas de concorrência.

15.2 Lógica Clássica


• A verdade de uma afirmativa é absoluta e independe da quaisquer pensa-
mento, entendimento ou ação.

• Afirmativas são verdadeiras ou falsas, onde falso é a mesma coisa que não
verdadeiro.

• Isso é conhecido com princı́pio do meio excluı́do: p∨⌉p.

15.3 Lógica Intuicionista


• Em p∨⌉p nenhuma informação é dada sobre qual realmente vale:

44
Existem dois números irracionais x e y tais que xy é racional.
Existem sete 7s consecutivos na representação decimal do número
π.

• Afirmativas só são válidas perante a existência de uma prova ou construção


da afirmativa.
• Essa lógica é de especial interesse porque suas fórmulas estão em corre-
spondência 1 a 1 com tipos em λ-calculus, base das linguagens de pro-
gramação funcionais: Lisp, ML, Haskell.
• Ainda, lógica intuicionista é uma lógica de recursos infinitos (mas não de
conclusões infinitas).

15.4 Lógica linear


• Lógica linear é uma lógica de recursos conscientes.
• No caso de transição de estados:

maior tem valor 1 −◦ maior tem valor 2

• É claro que a proposição { maior tem valor 1} deve deixar de ser válida
no estado 2, enquanto que a proposição { maior tem valor 2}, que não
era válida no estado 1, passa a valer no estado 2.
• Esse tipo de comportamento não pode ser descrito em lógicas clássica ou
intuicionista, apenas em lógica linear.

15.5 Linguagens lógicas de programação - Prolog


• Uma definição comum das cláusulas de Horn é dada de acordo com a
seguinte gramática:
G ::= A|G ∧ G
D ::= A|G ⊃ A|∀xD
• Ou seja, fórmulas gol são conjunções de fórmulas atômicas e cláusulas de
programas são da forma:
∀x1 . . . ∀xm [A1 ∧ . . . ∧ An ⊃ A0 ]

• Observe que, como implicação e quantificação universal não estão pre-


sentes no gol, todas as hipóteses e termos necessários para completar a
prova devem estar presentes desde o inı́cio do programa: assinaturas e
programas são globais.
• Ou seja, nada de mecanismos para modularização ou construtores de da-
dos!

45
15.6 Linguagens lógicas de programação - λ-Prolog
• As fórmulas de primeira ordem de Harrop estendem as cláusulas de Horn,
uma vez que admitem implicações e quantificadores universais no gol:
G ::= A|G ∧ G|P ⊃ G|∀xG
D ::= A|G ⊃ A|∀xD
• Deste modo, o programa pode crescer ao longo da prova (modularização) e
novas constantes podem ser adicionadas ao programa (abstract datatypes)
• Desvantagem: recursos ilimitados para construção de provas.

15.7 Linguagens lógicas de programação - Forum


• Lógica linear não é uma linguagem abstrata de programação.
• Forum é uma linguagem lógica de programação baseada em lógica linear.
Σ: Ψ; ∆ −→ Γ; Υ possui uma prova em Forum se e somente se ! Ψ, ∆ ⊢
Γ, ? Υ.
• Além de modularização e abstração de dados também permite encap-
sulação de estado, concorrência e primitivas de comunicação e sincronização.
• Cláusulas em Forum possuem a forma:
∀ȳ(G1 ֒→ · · · ֒→ Gm ֒→ G0 ), (m ≥ 0)
onde G0 , . . . , Gm são fórmulas arbitrárias em Forum e ֒→ denota −◦ ou ⊃.

16 Álgebra e ciência da computação


A principal aplicação de matemática em ciência da computação é na definição
de semântica formal em linguagens de programação.
“Semântica” é geralmente definida como o estudo da relação entre palavras
e sentenças de uma linguagem (escrita ou falada) e os seus significados. É
uma área que tem recebido, através dos tempos, muita atenção em lingüı́stica
e filosofia, que estudam o significado de sentenças na linguagem natural. Uma
segunda área de estudo de semântica se concentra no significado de sentenças em
linguagens formais de lógica matemática, originalmente projetada para servir
como “fundação” da matemática. Esta seção visa discutir, brevemente, tópicos
de uma terceira área da semântica: aquela que tem por objetivo desenvolver
técnicas para expressar a semântica de linguagens utilizadas para programação
de computadores. Estaremos especialmente interessados no uso de estruturas
matemáticas tais como grupos, domı́nios e teoria de categorias na descrição de
semântica de linguagens imperativas (como o Pascal) e funcionais (como ML,
Haskell).

46
17 Semântica
Tradicionalmente, linguagens de computadores têm sido baseadas em uma seqüência
de comandos, determinados por sentenças imperativas. Em linguagem natural,
tais sentenças são aquelas que podem ser encontradas em um livro de receitas:

Bata a clara do ovo até ficar dura. (1)

Em contraste, sentenças de lógica matemática visam estabelecer verdades abso-


lutas:

Quando batida, a clara do ovo fica dura. (2)

Muitas pesquisas em métodos para analisar programas em uma certa linguagem


procuram formalizar a relação entre os dois exemplos citados acima. Afinal
de contas, a sentença lógica (2) garante que uma pessoa que execute o que
manda a sentença imperativa (1) vai ter sucesso em terminar a tarefa de mudar
a consistência da clara do ovo.
Desta forma, uma maneira de descrever comandos (que são sentenças impera-
tivas) de uma linguagem de programação é estabelecendo uma relação entre o
estado do computador antes e depois da execução do comando (como descrito
por sentenças lógicas). Essa interpretação relacional de fragmentos de programa
pode ser formalizada através da semântica denotacional.
Vejamos um exemplo da semântica do comando if. Escreveremos C[·] para de-
notação de um comando e E[·] para denotação de uma expressão. Então temos:
C[if E then C1 else C2 ] = E[E]λv.isBool v → (v → C[C1 ], C[C2 ])

Da mesma forma, podemos escrever a semântica do comando while como:


C[while E do C] = E[E]λv.isBool v → (v → C[C], C[while E do C])
ou, mais simplesmente, podemos escrever:
C[while E do C] = C[C]; C[while E do C])

Antes de falarmos um pouco sobre esse tipo de semântica, vamos responder


à uma pergunta fundamental: qual é o objetivo de se estudar semântica de
linguagens de programação? Bem, quando essa área surgiu, o objetivo era prover
uma descrição suficientemente precisa para tornar possı́vel aos implementadores
construir um compilador para a linguagem em questão. Hoje em dia, a ênfase
está em:

1. fornecer uma descrição precisa para os programadores, tornando possı́vel


que estes façam afirmativas rigorosas sobre o comportamento de progra-
mas por eles escritos;

47
2. fornecer ferramentas para os designers de linguagens de programação, para
que possam sugerir linguagens melhores, confiáveis e com descrições for-
mais simples.

Ou seja, a grande vantagem é que desenvolve-se um método matemático (e por-


tanto formal) que garante corretude tanto de programas quanto da linguagens
desenvolvidas.

18 Semântica Denotacional
É a semântica que mapeia construtores sintáticos de programas em valores ab-
stratos (números, funções, etc) que eles denotam. Esses “mapeamentos” são
usualmente definidos recursivamente (como no cado do while acima). É claro
que alguns cuidados devem ser tomados quando trabalhamos com funções re-
cursivas. Em especial, para “modelar” o espaço de todas as funções recursi-
vas precisarı́amos de um conjunto X que contivesse todo o espaço de funções
X −→ X. Por questões de cardinalidade, sabemos que isso é impossı́vel. Para
lidar com essa dificuldade, foi proposto, em 1969, um modelo para funções re-
cursivas X −→ X restritas a funções contı́nuas em X (de acordo com uma certa
topologia).
Esse modelo, chamado de teoria de domı́nio, é utilizado para descrever a semântica
denotacional do λ-calculus, base de linguagens de programação funcionais. E,
utilizando o λ-calculus, podemos facilmente descrever a semântica denotacional
de linguagens como o Algol60, base do Pascal.
Outro tipo de semântica que tem sido muito estudada é a semântica categórica.
As idéias básicas desse tópico (muito em moda atualmente) são elegantes e de
fácil entendimento para um aluno da graduação com alguma maturidade na
área de Álgebra.

19 Segundo trabalho prático


O segundo trabalho prático consiste em implementar o algoritmo RSA. Deve
ser apresentado o seguinte:

1. A chave pública (n) criada no TP1, juntamente com o número e tal que
mdc(e, φ(n)) = 1.

2. Algoritmo para encontrar d, o inverso de e módulo φ(n).

3. Algoritmos de codificação (incluindo o de partição da mensagem em blo-


cos) e decodificação.

48
4. Teste em um texto de, no mı́nimo, 20 linhas. O texto, os blocos e o texto
cifrado deverão estar contidos no trabalho.

Como sempre, é necessário um pequeno texto introdutório de no máximo duas


páginas. Dessa vez não vou cobrar os executáveis...

49

Você também pode gostar