Instituto Superior de Engenharia de Coimbra

Transcrição

Instituto Superior de Engenharia de Coimbra
Instituto Superior de Engenharia de Coimbra
Departamento de Informática e de Sistemas
2002 – 2003
Trabalho da cadeira de Análise Matemática II sobre:
Realizado Por:
• André Tenreiro de Almeida – 21120610
[email protected]
Índice
I . Abstract..................................................................................................3
1. Introdução ..............................................................................................3
1.1 Criptografia, Criptologia, CriptoAnálise, CriptoSistema ............3
2. Técnicas e Algoritmos de Criptologia e Criptoanálise ............................4
2.1 Criptografia Clássica ..................................................................4
2.1.1 Encriptação de César ...........................................................4
2.1.2 Algoritmo de Vigenére.........................................................6
2.2 Criptografia Moderna ou Convencional......................................8
3. Matemática e Criptologia .......................................................................9
3.1 Teorica dos Números................................................................10
3.1.1 Definições e grupos de interesse na Teoria dos Números ..........10
3.1.1.1 Números Amigáveis ...........................................10
3.1.1.2 Números Perfeitos..............................................10
3.1.1.3 Números Primos ................................................11
3.1.2 Aplicando os conceitos da Teoria dos Números na Criptografia ...........11
3.2 Análise Combinatória ...............................................................12
3.2.1 Aplicando a Teoria dos Grafos em Criptografia ......................12
3.2.2 Estatística na Criptografia ...................................................13
3.3 Geometria.................................................................................14
3.3.1 Aplicações de Curvas Elípticas em Criptografia ......................14
3.4 Fundamentos da Matemática ....................................................14
3.4.1 Complexidade de Algoritmos ..............................................15
4. Conclusões ...........................................................................................17
5. Bibliografia ..........................................................................................17
6. Contactos .............................................................................................17
7. Anexos .................................................................................................18
2
I. Abstract
Este trabalho pretende analisar algumas técnicas de Criptologia, como criar
algoritmos de encriptação e como quebrar a sua segurança usando Matemática.
1. Introdução
Hoje em dia com o crescimento exponencial dos meios de comunicação, como
telefones, telemóveis, faxes, Internet, cartas, satélites, etc. Permitem-nos comunicar
facilmente com alguém, mesmo a longa distancias. Contudo ao enviar informação
confidencial ou sensível, estamos sujeitos a que terceiros possam ler a nossa mensagem
que se destina apenas ao destinatário.
Por essas razões, informação confidencial deve ser tratada de modo diferente,
como por exemplo, encriptar a informação de modo que apenas o emissor e o receptor
possam tomar conhecimento do conteúdo mensagem enviada.
Ilustração 1 Esquema de comunicação
1.1
Criptologia, Criptografia, Criptoanálise, Criptosistema.
A arte e a ciência de manter a informação segura é a criptografia, e é praticada
por criptógrafos. Por sua vez a criptoanálise é a arte e a ciência de quebrar o código da
criptografia e é praticada por criptoanalistas. A ciência da matemática que acompanha a
criptografia e a criptoanálise é denominada de criptologia, e é praticada por criptólogos,
que tem um conhecimento profundo de matemática teórica. Um algoritmo de
encriptação e também de desencriptação é denominado de criptosistema.
3
2 Técnicas e Algoritmos de Criptologia e Criptoanálise
2.1
Criptografia Clássica
2.1.1 Encriptação de César
Rege na história actual que o famoso imperador de Roma, Júlio César, pretendia
enviar uma mensagem confidencial mas não confiava nos seus mensageiros. Então criou
uma forma de codificar a mensagem, substituído o carácter pretendido por 3 caracteres á
direita. Por exemplo, A é substituído por D, B por E, C por F, etc..
Encriptação de César
F G H I J K L M N O P Q R S
Alfabeto
A B C D E
Normal
Alfabeto
D E F G H I
Codificado
J
K L M N O P
Q R S T
T
U V W X Y Z
U V W X Y Z
Exemplo: Roma vai ser atacada
Codificado: URPD YDL VHU DWDFDGD
Este texto codificado (cifra) pode ser facilmente quebrado usando para tal efeito,
estatística matemática.
Recorrendo a conceitos matemáticos básicos:
Algoritmo:
Se atribuir-mos a cada letra o equivalente de um numero (a=1, b=2, c=3, etc..),
poderíamos criar um algoritmo em que p (Texto normal) substituída por C (cifra)
teríamos:
Encriptação:
Para o caso especifico da encriptação de César
C = E(P) = (p + 3) mod(26)
Para um caso geral do algoritmo de César:
C = E(p) = (p + k) mod(26) k ∈ N : 1 ≤ k ≤ 25, sendo o valor da permutação.
DesEncriptação:
p = D(C) = (C – k ) mod(26) k ∈ N : 1 ≤ k ≤ 25, sendo o valor da permutação.
4
A B C
Segurança do Algoritmo:
Este tipo de criptologia clássica, hoje em dia apenas servirá para um mero uso
amador e não para informação realmente confidencial. Aplicando o método de “Força
Bruta”, i.e, tentar todas as possibilidades até encontrar uma certa combinação que faça
sentido, teríamos 25 possibilidades para testar. Hoje em dia a capacidade dos
computador actuais com um programa informático destinado a esse fim, testar essas
possibilidades faria isso em fracções de segundo tornando o código ou algoritmo
trivialmente quebrável.
Quebrar o Algoritmo de César:
URPD
YDL
VHU
TQOC
SPNB
ROMA
QNLZ
PMKY
OLJX
NKIW
MJHV
LIGU
KHFT
J GES
IFDR
HECQ
GDBP
FCAO
EBZN
DAXM
CZYL
BYZK
AXWJ
ZWVI
YVUH
XUTG
WTSF
SSRE
XCK UGT
WBJ TFS
VAI SER
UZH RDQ
TYG QCP
SXF PBO
RWE OAN
QVD NZM
PUC MYL
OTB LXK
NSA KWJ
MZ
JVI
LRY IUH
KQX HTG
JPW GSF
IOV FRE
HNU EQD
GMT DPC
FLS
CO
EKR
BNA
DJQ
AMZ
CIPO ZLX
BHN YKY
AGM XJW
ZFL
WIV
DWDFDGD
Chave
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CVCECFC
BUBDBEB
ATACADA
ZSZBZCZ
YTYAYBY
XSXZXAX
WRWYWZW
VQVXVYV
UPUWUXU
TOTVTWT
SNSUSVS
RMRTRUR
QLQSQTQ
PKPRPSSP
OJOQORO
NINPNQN
MHMOPM
LGLNLOL
KFKMKNK
JEJLJMJ
IDIKINI
HCHJHLH
GBGIGKG
FAFGFJF
RZRFRIR
Como podemos constatar, a 3ª chave ou possibilidade faz sentido. O Algoritmo
de encriptação de César tem um tamanho de chave de cerca de 32 bits, que é facilmente
quebrável e inseguro. Contudo para quebrar a segurança deste algoritmo e permitir o
uso da criptoanálise através de “Força Bruta” precisamos de saber importantes
características:
• Ter conhecimento do algoritmo de encriptação e desencriptação
• Apenas temos de testar 25 chaves
• Conhecer a linguagem do texto descodificado
5
2.1.2 Algoritmo de Vigenére
Com apenas 25 possibilidades, o algoritmo de César está longe de ser um
criptosistema seguro. Com intuito de aumentar a fiabilidade do criptosistema, Vigenére
criou uma forma alternativa de codificação:
Exemplo: A = ERX ; B = 34 ; C=A; etc..
Aumentando o número de possibilidades usando a “Força Bruta” para atacar a cifra,
recorremos a uma maneira matemática de estudar a cifra e quebra-la. Eis um exemplo:
O centro de operações de criptologia Americano, National Security Agency (NSA),
destinado a espionagem electrónica intercepta uma mensagem codificada destinada a
um centro de operações Russo. A seguinte mensagem captada lia-se:
UZQSOVUOHXMOPVGPOZPEVSGZWSZOPFPESXUDBMETSXAIZ
VUEPHZHMDZSHZOWSFPAPPDTSVPQUZWYMXUZUHSX
EPYEPOPDZSZUFPOMBZWPFUPZHMDJUDTMOHMQ
Recorrendo a uma simples estatística matemática para contar a frequência dos
caracteres em texto codificado temos:
P
Z
S
U
O
M
13.33
11.67
8.33
8.33
7.50
6.67
H
D
E
V
X
Frequência dos caracteres na cifra (%)
5.83
F
3.33
B
1.67
5.00
W
3.33
G
1.67
5.00
Q
2.50
Y
1.67
4.17
T
2.50
I
0.83
4.17
A
1.67
J
0.83
C
K
L
N
R
0.00
0.00
0.00
0.00
0.00
Sabendo que o texto codificado está na língua inglesa, vamos analisar a frequência dos
caracteres da língua inglesa, sendo a língua mais standardizada, comparando-os com a
frequência dos caracteres da cifra.
6
Ling. Inglesa
Cifra
14
12
10
8
6
4
2
0
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
Ilustração 2 Frequência dos caracteres na língua inglesa e na nossa cifra
Recordando a cifra
UZQSOVUOHXMOPVGPOZPEVSGZWSZOPFPESXUDBMETSXAIZ
VUEPHZHMDZSHZOWSFPAPPDTSVPQUZWYMXUZUHSX
EPYEPOPDZSZUFPOMBZWPFUPZHMDJUDTMOHMQ
Recorrendo a Substituição dos caracteres mais frequentes da língua inglesa pelos
caracteres mais frequentes da cifra:
UZQSOVUOHXMOPVGPOZPEVSGZWSZOPFPESXUDBMETSXAIZ
t a
e e te
a that
e e a
a
VUEPHZHMDZSHZOWSFPAPPDTSVPQUZWYMXUZUHSX
e t
ta t há e ee
a e
th
t
a
EPYEPOPDZSZUFPOMBZWPFUPZHMDJUDTMOHMQ
e e e tat
e
the
t
Continuando o processo, como se fosse um “puzzle” ou uma sopa de letras
conseguimos chegar ao texto descodificado:
it will disclosed yesterday that several informal but
direct contacts have been made with political
representatives of the viet cong in moscow
7
Segurança do Algoritmo
Cifras monoalfabéticas são facilmente quebráveis porque refletem-se em estatísticas de
frequência dos caracteres do alfabeto em que foram escritas.
Mais segura do que o Algoritmo de César, embora também se considera esta cifra
meramente para uso amador e trivial.
2.2 Criptografia Moderna ou Convencional
A cada dia que passa são criados novos criptosistemas, descobrem-se novas
técnicas matemáticas e com o avanço da tecnologia, criam-se novos computadores
capazes de processar largas quantidades de informação em cada vez menos tempo.
Hoje em dia a criptografia clássica não oferece a segurança necessária para
corporações e pessoas que tenham de manter informação confidencial. A pensar nisso
NSA (National Security Agency) dos EUA, criou uma equipa de matemáticos
destinados a desenvolver novos algoritmos de encriptação “inquebráveis”, bem como
outras centrais de inteligência mundiais e universidades.
DES
O criptosistemas DES (Data Encryption System), desenvolvido na década de
1977 pelo NIST (National Institute of Standards and Technology) basea-se em trocas
sucessivas dos caracteres de forma a ser extremamente difícil seguir o rasto, ao
contrário da criptografia clássica.
Baseando-se numa chave de 56-bits, i.e, teríamos 256 possibilidades para testar
até quebrar o código! Se não parece ser muito, pense que no planeta terra existem cerca
de 2170 átomos! Isto num computador actual poderia demorar décadas ou mesmo
centenas de anos.
IDEA
O Algoritmo IDEA de encriptação, elaborado por Xuejia Lai e James Massey
em 1992. Baseado de fundamentos matemáticos bem sólidos e complexos, o algoritmo
IDEA , sendo o algoritmo também duas vezes mais rápido que o DES. Tendo 2128
possibilidades para um ataque de “força-bruta” até quebrar ó código, faz-nos crer que é
considerado um dos mais seguros, e um ataque de “força bruta” a uns anos atrás num
mero computador da época poderia demorar até 1013 anos, ao comprar com a idade do
universo, cerca de1010 anos, faz-nos crer que realmente é muito tempo!
8
RSA
Sem dúvida um dos algoritmos mais usados actual, tem a caracteristica de ser
de“Chave-Publica”, ou seja, temos uma chave publica e uma chave privada. A Chave
publica é conhecida e pode ser partilhada, mas a chave privada tem de ser mantida em
segredo. Este método aumenta bastante a segurança do algoritmo podendo este chegar a
ter uma chave de 1024-bits, i.e, 21024 possibilidades de desEncriptação, para ter uma
maior noção destas grandezas, o volume do universo é cerca de 2280 cm³!
Este algoritmo é cerca de 1000 vezes mais lento que o DES, mas sem dúvida
bem mais seguro. Para gerar uma chave publica, o algoritmo usa pura Matemática,
Teoria dos Números, como iremos abordar mais á frente, vejamos os passos para
criação de uma chave:
1. Gere dois números grandes de forma aleatória (e distintos) primos p e q, e os dois do
mesmo tamanho.
2. Gere n, tal que: n = pq e φ = (p - 1)(q - 1).
3. Gere um inteiro aleatório, E, 1 < E < φ, tal que MMC(E, φ) = 1
4. Usa-se o algoritmo Euclidiano para gerar um unico inteiro, d
1 < d < φ, tal que Ed = 1 (mod φ).
5. A chave publica é (n, E); e a Chave privada é d.
NOTA: Os Algoritmos utilizados encontram-se em Anexo.
3 Matemática e a Criptologia
A Matemática é a ciência que investiga as relações entre entidades definidas
abstrata e logicamente, ou ainda, o ciência que tem por objecto o estudo da grandeza
mensurável e calculável. Para que os estudos dessa ciência possam avançar, a ciência
Matemática é particionada em diversas divisões principais, a saber:
• Fundamentos da Matemática
• Álgebra
• Análise Combinatória
• Análise Matemática
• Geometria
• Teoria dos Números
• Topologia
Todas estas diferentes áreas de matemática tem o uso na criptografia, ajudando-a a
tornar-se cada vez mais complexa.
9
Ilustração 3 Areas de Matemática aplicadas em Criptografia
3.1 Teoria dos Números
Para o presente estudo, a Teoria Elementar dos Números contém diversos itens
de interesse, destacando-se a divisibilidade, primalidade, máximo divisor comum,
congruências e resíduos – associados às operações modulares. Esse conjunto de itens é
comumente conhecido como "teoria multiplicativa do anel Z de números inteiros".
3.1.1 Definições e grupos de interesse na Teoria dos Números
3.1.1.1 Números Amigáveis
Também encontrados na literatura como "números amigos", são pares de
Números onde cada um é igual à soma dos divisores do outro. Os árabes, em especial,
desenvolveram diversos algoritmos para a determinação de números amigáveis. O
quadro a seguir apresenta alguns desses números.
Números Amigos
220 e 284
Números
220
284
Factores
1,2,4,5,10,11,20,22,44,55,110
1,2,4,71,142
Ilustração 4 Exemplo de dois números amigos
Observa-se, no quadro acima, que a soma de todos os factores de 220 resulta em 284;
por sua vez, a soma dos factores de 284 resulta em 220. Não foram encontrados Muitos
números amigos: 1184 e 1210; 2620 e 2924; 5020 e 5564; e 6232 e 6368.
Recentemente, os matemáticos extenderam essa ideia para cadeia de números
amigáveis, sendo a soma dos factores do último da cadeia, o valor do primeiro.
3.1.1.2 Números Perfeitos
Os chamados números perfeitos são números cuja soma de seus factores resulta
no valor do próprio número. Por exemplo, seis é um número perfeito, visto que a soma
10
de seus factores - 1, 2 e 3 - resulta em 6. Euclides propôs - e pode-se expressar em um
formalismo dos dias actuais - que um número N da forma (2n - 1)* 2(n-1) é um número
perfeito, se o factor (2n - 1) 10 for um número primo. Assim, para n = 2, 3, 5 ou 7, a
expressão (2n - 1) assume os valores 3, 7, 31 ou 127 - os quais são também primos. Para
esses valores, podem-se obter o números perfeitos 6, 28, 496 e 8128. O estudo de
números perfeitos levou Fermat a estudos que possibilitaram base a seu teorema, e serve
de base para o estudo das fracções continuadas – uma das tendências Matemáticas para
Criptografia.
3.1.1.3 Números Primos
São números cujos factores são apenas um e o próprio número, ou seja, não têm
outros divisores. Tendo uma infinita possibilidade de números primos, sendo esse
factor, a restrita divisibilidade, e sua infinitude que detêm características que garantem
interessantes propriedades a determinados algoritmos aplicados a Criptografia.
Há apenas uma forma de determinar se um número é ou não primo: aplicando
um teste de primalidade. E, para isso, despende-se considerável tempo, mesmo
utilizando-se de grandes recursos computacionais. Baseado nessa dificuldade, repousa
a segurança da actual Criptografia.
Algoritmo de Verificação de um Numero Primo
Inicialização: Ler p
Primo := Verdadeiro
Iteração: r := (2 p/2- 1)/2*p
Para i := 1 até r faça
M(p) MOD Éprimo(r) = 0 então Primo := False
Término: Se Primo então imprimir "M(p) é Primo"
Senão imprimir "M(p) não é primo"
Saída: Mensagem de status: ou M(p) é primo, ou não é.
NOTA: A respectiva adaptação em Linguagem de programação C, encontra-se em
anexo.
3.1.2 Aplicando os conceitos da Teoria dos Números na Criptografia
Em 1977, foi apresentado um criptosistema de chave pública: o RSA, assim
chamado por ser a abreviatura dos sobrenomes de seus autores - Rivest, Shamir e
Adleman. Esse criptosistema é baseado no facto de que é muito mais fácil multiplicar
dois números primos grandes, do que a factoração do produto resultante desses primos
grandes, sendo baseado no teorema de Euler.
11
3.2 Análise Combinatória
A Análise Combinatória está subdividida em Teoria dos Grafos, Arranjos e
Configurações Combinatórias, Probabilidade, Estatística Matemática, Métodos de
Inferência, Matemática Computacional, Métodos Numéricos, Interpolação, Cibernética
Matemática, Teoria dos Sistemas de Controle, Teoria da Informação, Semiótica e
Pesquisa Operacional. A figura a seguir ilustra parte da contribuição de interesse para a
Criptografia.
Ilustração 5 Contribuições da Análise Combinatória para a Criptografia.
A subdivisão de interesse para a Criptografia é a Teoria dos Grafos – com a
contribuição significativa para a Criptografia de blocos -, conforme ver-se-á a seguir.
Contudo, a Estatística e a Probabilidade têm também aplicação, vista a importância dos
primeiros métodos de Criptoanálise.
3.2.1 Aplicando a Teoria dos Grafos em Criptografia
Sem a menor dúvida, a maior contribuição da Teoria dos Grafos para a
Criptografia foi o estudo dos circuitos, aplicando-se no Data Encryption Standard DES - adaptação do NIST para o algoritmo Lucifer da IBM, em 1977. Esse padrão é
orientado a blocos, ou seja, divide a mensagem ou o texto a ser criptografado em grupos
de 64 bits. Utilizando-se uma chave de 56 bits, de duas tabelas para transposição inicial e final – e uma técnica de cifragem – repetida 16 vezes, efetuavam a criptografia
de forma relativamente segura. A figura a seguir apresenta o esquema genérico do
funcionamento do DES, em blocos.
12
Ilustração 6 Esquema de funcionamento do DES.
3.2.2 Estatística na Criptografia
Como podemos ver no Capitulo 2, nas técnicas de Encriptação Clássica, através
das quais recorremos ás cifras mais frequentes para descobrir a respectiva combinação.
Ilustração 7 Frequência dos caracteres na língua Portuguesa.
NOTA: Em Anexo está um programa em C para contabilizar a frequência dos caracteres
num texto.
13
3.3 Geometria
As principais subdivisões da Geometria são a Geometria Geral, as Geometrias
Euclidiana e pseudo-Euclidiana, a Geometria Analítica, a Geometria projectiva, a
Trigonometria, os Conjuntos convexos, a Geometria Descritiva, a Geometria
Diferencial e a Geometria das Curvas Elípticas.
Ilustração 8 Contribuição da Geometria para o estudo da Criptografia.
Sucintamente, explicamos as aplicações das Curvas Elípticas, sendo essas as mais
importantes da área de Geometria na Criptografia.
3.3.1 Aplicações de Curvas Elípticas em Criptografia
•
•
Esquemas Troca de Chaves criptográficas
Algoritmo RSA
3.4 Fundamentos da Matemática
As principais subdivisões dos Fundamentos da Matemática são a Lógica
Matemática, Formalismo, o Positivismo, a Semântica, a Inferência, a Complexidade e
a Teoria dos Conjuntos . Para aplicações em Criptografia, é relevante a compreensão da
Complexidade.
14
Ilustração 9 Contribuição dos Fundamentos da Matemática para o estudo da Criptografia
3.4.1 Complexidade de Algoritmos
A complexidade computacional de técnicas ou algoritmos criptográficos pode
ser melhor analisado pela teoria da complexidade. Tipicamente, as afirmações da Teoria
dos Números garantem que todos os algoritmos criptográficos podem ser quebrados.
Assim, torna-se de interesse qualquer estudo que preveja o esforço necessário para
efectuar a quebra dos algoritmos que se enquadrem em algum tipo de problema - em
algum conjunto ou classe de problemas.
Para os estudos de classes de complexidade de problemas, normalmente empregam-se
os problemas de Decisão, visto a maior simplicidade entre os problemas associados.
Com relação à representação, emprega-se em geral o termo O. Dado um algoritmo e o
tamanho de sua entrada - n -, diz-se que a complexidade é:
• Linear - se o tempo para sua execução é O(n);
• Polinomial - se o tempo para a sua execução é O(nt), para algum t constante;
• Exponencial - se o tempo para a sua execução é O(th(n)), para alguma constante t, e um
polinómio h(n).
15
Como se poderia calcular a complexidade de determinado algoritmo? Através do
número de operações. Pode-se verificar o número de iterações de seus laços, por
exemplo; no caso das repetições condicionais, pode-se avaliar o pior caso - ou seja,
quando ocorre o maior número de repetições. Nos casos de decisões, assume-se o pior
caso. Há autores que buscam utilizar-se dos casos médios - ou seja, considerando-se a
média entre o número de ocorrências do pior caso, e do melhor caso.
Algoritmo Exemplo;
n, i, j: integer; x, Poli: real;
A, S: array [0..100] of real;
BEGIN
Read(x,n);
For i:= 0 to n do
Begin
S[i] := 1; Read (a[i);
For j := 1 to i do S[i] := x * S[i];
S[i] := A[i] * S[i];
End; {for}
Poli := 0;
For i := 0 to n do Poli := Poli + S[i];
Write ('O valor em ',x,' é: ', Poli);
END;
16
4. Considerações Finais
Sem dúvida que o papel da Matemática é fundamental para o desenvolvimento e
análise da Criptografia, como já vimos. Com o auxilio dos computadores, que cada dia
se tornam mais potentes, podemos criar e quebrar CriptoSistemas cada vez mais
complexos, e com o desenvolvimento rápido das novas tecnologias e o aumento da
preocupação do direito à privacidade, faz com que esta Área, a Criptologia nunca pare
de crescer.
5. Bibliografia
•
Applied Cryptography, Bruce Schneier.
o Cota Biblioteca ISEC: 1A 16 3
•
Cryptography and Network Security, WilliamStallings
o Cota Biblioteca ISEC: 1A 16 1
•
Um Estudo sobre a Matemática empregada em Criptografia, Vinicius Gadis
Ribeiro
6. Contacto
André Tenreiro de Almeida
Numero Interno: 21120610
Regime: Misto
Email: [email protected]
17
7. Anexo
Nesta secção encontram-se programas em C e Algoritmos Matemáticos usados para a
criação e análise Criptológica.
Progama em C para Calcular a Frequencia dos Caracteres num texto :
/* Instituto Superior de Engenharia de Coimbra
Departamento de Engeharia Informatica e de Sistemas
Analise Matematica II
Trabalho de Criptografia
Andre Mendonca Tenreiro de Almeida
NI: 21120610
01/06/03
*/
#include <stdio.h>
#include <stdlib.h>
struct data {
int total;
int A, B, C,
N, O, P,
int a, b, c,
n, o, p,
int numb;
int others;
D,
Q,
d,
q,
E,
R,
e,
r,
F,
S,
f,
s,
G,
T,
g,
t,
H,
U,
h,
u,
I,
V,
i,
v,
J,
W,
j,
w,
K,
X,
k,
x,
L,
Y,
l,
y,
M,
Z;
m,
z;
} var;
int main(int argc, char **argv) {
FILE *fp, *fp2;
char *filename, *filename2;
char chr;
float f_A, f_B, f_C, f_D,
f_N, f_O, f_P, f_Q,
f_a, f_b, f_c, f_d,
f_n, f_o, f_p, f_q,
f_numb, f_others;
f_E,
f_R,
f_e,
f_r,
f_F,
f_S,
f_f,
f_s,
f_G,
f_T,
f_g,
f_t,
f_H,
f_U,
f_h,
f_u,
f_I,
f_V,
f_i,
f_v,
f_J,
f_W,
f_j,
f_w,
f_K,
f_X,
f_k,
f_x,
f_L,
f_Y,
f_l,
f_y,
f_M,
f_Z,
f_m,
f_z,
if (argc != 3) {
printf("\n\n");
printf("++++++++++++++++++++++++++++++++++++++++\n");
printf("++
Analise Matematica II
++\n");
printf("++++++++++++++++++++++++++++++++++++++++\n");
printf("+ Contador para Criptografia Classica ++\n");
printf("++++++++++++++++++++++++++++++++++++++++\n\n");
printf("usagem: %s input.txt output.txt\n\n", argv[0]);
exit(1);
}
18
filename = argv[1];
filename2 = argv[2];
fp = fopen(filename, "r");
if (fp == NULL) {
printf("ERRO: Ficheiro inexistente \"%s\".\n", filename);
exit(1);
}
fp2 = fopen(filename2, "w");
if (fp2 == NULL) {
printf("ERRO: Ficheiro inexistente \"%s\".\n", filename2);
exit(1);
}
printf("Espere...");
while(fread(&chr, 1, 1, fp) != 0) {
if (chr == ' ') {
/* null, nao faz nada */
}
if (chr == 'a') {
var.total++;
var.a++;
}
if (chr == 'b') {
var.total++;
var.b++;
}
if (chr == 'c') {
var.total++;
var.c++;
}
if (chr == 'd') {
var.total++;
var.d++;
}
if (chr == 'e') {
var.total++;
var.e++;
}
if (chr == 'f') {
var.total++;
var.f++;
}
if (chr == 'g') {
var.total++;
var.g++;
}
if (chr == 'h') {
19
var.total++;
var.h++;
}
if (chr == 'i') {
var.total++;
var.i++;
}
if (chr == 'j') {
var.total++;
var.j++;
}
if (chr == 'k') {
var.total++;
var.k++;
}
if (chr == 'l') {
var.total++;
var.l++;
}
if (chr == 'm') {
var.total++;
var.m++;
}
if (chr == 'n') {
var.total++;
var.n++;
}
if (chr == 'o') {
var.total++;
var.o++;
}
if (chr == 'p') {
var.total++;
var.p++;
}
if (chr == 'q') {
var.total++;
var.q++;
}
if (chr == 'r') {
var.total++;
var.r++;
}
if (chr == 's') {
var.total++;
var.s++;
}
if (chr == 't') {
var.total++;
20
var.t++;
}
if (chr == 'u') {
var.total++;
var.u++;
}
if (chr == 'v') {
var.total++;
var.v++;
}
if (chr == 'w') {
var.total++;
var.w++;
}
if (chr == 'x') {
var.total++;
var.x++;
}
if (chr == 'y') {
var.total++;
var.y++;
}
if (chr == 'z') {
var.total++;
var.z++;
}
if (chr == 'A') {
var.total++;
var.A++;
}
if (chr == 'B') {
var.total++;
var.B++;
}
if (chr == 'C') {
var.total++;
var.C++;
}
if (chr == 'D') {
var.total++;
var.D++;
}
if (chr == 'E') {
var.total++;
var.E++;
}
if (chr == 'F') {
var.total++;
var.F++;
21
}
if (chr == 'G') {
var.total++;
var.G++;
}
if (chr == 'H') {
var.total++;
var.H++;
}
if (chr == 'I') {
var.total++;
var.I++;
}
if (chr == 'J') {
var.total++;
var.J++;
}
if (chr == 'K') {
var.total++;
var.K++;
}
if (chr == 'L') {
var.total++;
var.L++;
}
if (chr == 'M') {
var.total++;
var.M++;
}
if (chr == 'N') {
var.total++;
var.N++;
}
if (chr == 'O') {
var.total++;
var.O++;
}
if (chr == 'P') {
var.total++;
var.Q++;
}
if (chr == 'Q') {
var.total++;
var.Q++;
}
if (chr == 'R') {
var.total++;
var.R++;
}
22
if (chr == 'S') {
var.total++;
var.S++;
}
if (chr == 'T') {
var.total++;
var.T++;
}
if (chr == 'U') {
var.total++;
var.U++;
}
if (chr == 'V') {
var.total++;
var.V++;
}
if (chr == 'W') {
var.total++;
var.W++;
}
if (chr == 'X') {
var.total++;
var.X++;
}
if (chr == 'Y') {
var.total++;
var.Y++;
}
if (chr == 'Z') {
var.total++;
var.Z++;
}
/* teste de condicao de numeros*/
if (chr >= '0' || chr <= '9') {
var.total++;
var.numb++;
}
/* teste de condicoes nao alfanumericos */
else {
var.total++;
var.others++;
}
} /* end of while */
printf("done!\n\n");
f_a = (float)(var.a * 100) / var.total;
f_A = (float)(var.A * 100) / var.total;
f_b = (float)(var.b * 100) / var.total;
23
f_B = (float)(var.B * 100) / var.total;
f_c = (float)(var.c * 100) / var.total;
f_C = (float)(var.C * 100) / var.total;
f_d = (float)(var.d * 100) / var.total;
f_D = (float)(var.D * 100) / var.total;
f_e = (float)(var.e * 100) / var.total;
f_E = (float)(var.E * 100) / var.total;
f_f = (float)(var.g * 100) / var.total;
f_F = (float)(var.G * 100) / var.total;
f_g = (float)(var.g * 100) / var.total;
f_G = (float)(var.G * 100) / var.total;
f_h = (float)(var.h * 100) / var.total;
f_H = (float)(var.H * 100) / var.total;
f_i = (float)(var.i * 100) / var.total;
f_I = (float)(var.I * 100) / var.total;
f_j = (float)(var.j * 100) / var.total;
f_J = (float)(var.J * 100) / var.total;
f_k = (float)(var.k * 100) / var.total;
f_K = (float)(var.K * 100) / var.total;
f_l = (float)(var.l * 100) / var.total;
f_L = (float)(var.L * 100) / var.total;
f_m = (float)(var.m * 100) / var.total;
f_M = (float)(var.M * 100) / var.total;
f_n = (float)(var.n * 100) / var.total;
f_N = (float)(var.N * 100) / var.total;
f_o = (float)(var.o * 100) / var.total;
f_O = (float)(var.O * 100) / var.total;
f_p = (float)(var.p * 100) / var.total;
f_P = (float)(var.P * 100) / var.total;
f_q = (float)(var.q * 100) / var.total;
f_Q = (float)(var.Q * 100) / var.total;
f_r = (float)(var.r * 100) / var.total;
f_R = (float)(var.R * 100) / var.total;
f_s = (float)(var.s * 100) / var.total;
f_S = (float)(var.S * 100) / var.total;
f_t = (float)(var.t * 100) / var.total;
f_T = (float)(var.T * 100) / var.total;
f_u = (float)(var.u * 100) / var.total;
f_U = (float)(var.U * 100) / var.total;
f_v = (float)(var.v * 100) / var.total;
f_V = (float)(var.V * 100) / var.total;
f_w = (float)(var.w * 100) / var.total;
f_W = (float)(var.W * 100) / var.total;
f_x = (float)(var.x * 100) / var.total;
f_X = (float)(var.X * 100) / var.total;
f_y = (float)(var.y * 100) / var.total;
f_Y = (float)(var.Y * 100) / var.total;
f_z = (float)(var.z * 100) / var.total;
f_Z = (float)(var.Z * 100) / var.total;
f_numb = (float)(var.numb * 100) / var.total;
f_others = (float)(var.others * 100) / var.total;
fprintf(fp2, "++++++++++++++++++++++++++++++++++++++++++\n");
fprintf(fp2, "+
Analise Matematica II
++\n");
fprintf(fp2, "++++++++++++++++++++++++++++++++++++++++++\n");
fprintf(fp2, "+ Contador para criptografia classica ++\n");
fprintf(fp2, "++++++++++++++++++++++++++++++++++++++++++\n\n");
fprintf(fp2, "Input file: %s
data: %s
hora: %s\n", filename,
__DATE__, __TIME__);
fprintf(fp2, "\n\n");
24
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
fprintf(fp2,
"Caracts Totais: %d \n\n", var.total);
"Charcts Totais:
Percentagem\n\n");
"A:%8d %16.2f\n", var.A, f_A);
"a:%8d %16.2f\n", var.a, f_a);
"B:%8d %16.2f\n", var.B, f_b);
"b:%8d %16.2f\n", var.b, f_B);
"C:%8d %16.2f\n", var.C, f_C);
"c:%8d %16.2f\n", var.c, f_c);
"D:%8d %16.2f\n", var.D, f_D);
"d:%8d %16.2f\n", var.d, f_d);
"E:%8d %16.2f\n", var.E, f_E);
"e:%8d %16.2f\n", var.e, f_e);
"F:%8d %16.2f\n", var.F, f_F);
"f:%8d %16.2f\n", var.f, f_f);
"G:%8d %16.2f\n", var.G, f_G);
"g:%8d %16.2f\n", var.g, f_g);
"H:%8d %16.2f\n", var.H, f_H);
"h:%8d %16.2f\n", var.h, f_h);
"I:%8d %16.2f\n", var.I, f_I);
"i:%8d %16.2f\n", var.i, f_i);
"J:%8d %16.2f\n", var.J, f_J);
"j:%8d %16.2f\n", var.j, f_j);
"K:%8d %16.2f\n", var.K, f_K);
"k:%8d %16.2f\n", var.k, f_k);
"L:%8d %16.2f\n", var.L, f_L);
"l:%8d %16.2f\n", var.l, f_l);
"M:%8d %16.2f\n", var.M, f_M);
"m:%8d %16.2f\n", var.m, f_m);
"N:%8d %16.2f\n", var.N, f_N);
"n:%8d %16.2f\n", var.n, f_n);
"O:%8d %16.2f\n", var.O, f_O);
"o:%8d %16.2f\n", var.o, f_o);
"P:%8d %16.2f\n", var.P, f_P);
"p:%8d %16.2f\n", var.p, f_p);
"Q:%8d %16.2f\n", var.Q, f_Q);
"q:%8d %16.2f\n", var.q, f_q);
"R:%8d %16.2f\n", var.R, f_R);
"r:%8d %16.2f\n", var.r, f_r);
"S:%8d %16.2f\n", var.S, f_S);
"s:%8d %16.2f\n", var.s, f_s);
"T:%8d %16.2f\n", var.T, f_T);
"t:%8d %16.2f\n", var.t, f_t);
"U:%8d %16.2f\n", var.U, f_U);
"u:%8d %16.2f\n", var.u, f_u);
"V:%8d %16.2f\n", var.V, f_V);
"v:%8d %16.2f\n", var.v, f_v);
"W:%8d %16.2f\n", var.W, f_W);
"w:%8d %16.2f\n", var.w, f_w);
"X:%8d %16.2f\n", var.X, f_X);
"x:%8d %16.2f\n", var.x, f_x);
"Y:%8d %16.2f\n", var.Y, f_Y);
"y:%8d %16.2f\n", var.y, f_y);
"Z:%8d %16.2f\n", var.Z, f_Z);
"z:%8d %16.2f\n", var.z, f_z);
"Numeros:%8d %16.2f\n", var.numb, f_numb);
"Outros:%8d %16.2f\n", var.others, f_others);
"\n");
fclose(fp); fclose(fp2);
} /* end of main() function */
25
PseudoCódigo para Calcular MMC:
INICIO FUNCAO MMC
RECEBE (den1, den2)
SE den1 < den2
INICIO
Mmc <- den1 – 1
FIM
SENAO
INICIO
Mmc <- den2 -1
FIM SE
FAZER
INICIO
Mmc <- den1 + 1
Resto <- (mmc % den1) + (mmc % den2)
FIM
ENQUANTO resto > 0
INICIO “Fracções”
OBTEM (num1, den1)
OBTEM (num2, den2)
Mmc <- CHAMA mmc(den1, den2)
num <- num1 * (mmc / den1)
num <- num + num2 * (mmc / den2)
MOSTRA (num, mmc)
FIM “Fracções”
Calculo do MMC em C:
#include <stdio.h>
int MMC(en1, int den2) {
int mmc, resto;
if (den1 < den2) {
mmc = den1 - 1;
}
else {
mmc = den2 -1;
}
do {
mmc = mmc + 1
resto=(mmc%den1)+(mmc%den2);
}
while (resto > 0);
return mmc;
}
int main(void) {
int num1, den1
int num2, den2;
26
int mmc, resto;
scanf(“%d %d”, &num1, &den1);
scanf(“%d %d”, &num2, &den2);
mmc = MMC(den1, den2);
num = num1 * (mmc / den1);
num += num2 * (mmc / den2);
printf(“%d /%d”, num, mmc);
return 1;
}
Algoritmo Euclidiano
Inicialização: r := 0
Interação: aplica-se o algoritmo de divisão de a por b, obtendo-se o resto r1 ;
se r1 ψ 0, divide-se b por r1, obtendo-se o resto r2;
se r2 ψ 0, divide-se r3 por r2, obtendo-se o resto r3.
Término: quando terminar o algoritmo de divisão
O MDC será o último rn ψ 0.
Algoritmo dos Números Primos
Inicialização: Ler p
Primo := Verdadeiro
Iteração: r := (2 p/2- 1)/2*p
Para i := 1 até r faça
Se M(p) MOD Éprimo(r) = 0 então Primo := False
Término: Se Primo então imprimir "M(p) é Primo"
Senão imprimir "M(p) não é primo"
Saída: Mensagem de status: ou M(p) é primo, ou não é.
Algoritmo de Euler, Caminho Euleriano
Inicialização: total := 0
i := 1
Iteração: Enquanto (total χ 2) e (i χ n) faça
grau := 0
Para j := 1 to n faça
grau := grau + M[i,j]
se impar(grau) então
total := total + 1
i := i + 1
Término: Se total > 2 então imprimir “não existe caminho Euleriano”
Senão imprimir “existe caminho Euleriano”
27

Documentos relacionados