From 38346009e7d5e395fbdb3c25471b117865ccf634 Mon Sep 17 00:00:00 2001 From: Aurelien Rebourg Date: Thu, 19 Dec 2019 05:54:37 +0100 Subject: [PATCH] grosse avancee, fin de cipher --- .gitignore | 6 +- Makefile | 41 +++++++++++++ Source/builtin/basic_arithmetics.ml | 20 ++++++- Source/builtin/ciphers.ml | 50 ++++++++++++---- Source/builtin/generate_primes.ml | 89 ++++++++++++++++++++++++++--- Source/builtin/power.ml | 36 ++++++++++-- Source/builtin/test_primes.ml | 30 +++++++++- configure | 27 +++++++++ setup.ml | 39 +++++++++++++ 9 files changed, 308 insertions(+), 30 deletions(-) create mode 100644 Makefile create mode 100755 configure create mode 100644 setup.ml diff --git a/.gitignore b/.gitignore index 29f1024..15aff4c 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,8 @@ setup.log _opam/ # Local files -*~ \ No newline at end of file +*~ + +*.log +*.cache +*caml-toplevel* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3639f14 --- /dev/null +++ b/Makefile @@ -0,0 +1,41 @@ +# OASIS_START +# DO NOT EDIT (digest: a3c674b4239234cbbe53afe090018954) + +SETUP = ocaml setup.ml + +build: setup.data + $(SETUP) -build $(BUILDFLAGS) + +doc: setup.data build + $(SETUP) -doc $(DOCFLAGS) + +test: setup.data build + $(SETUP) -test $(TESTFLAGS) + +all: + $(SETUP) -all $(ALLFLAGS) + +install: setup.data + $(SETUP) -install $(INSTALLFLAGS) + +uninstall: setup.data + $(SETUP) -uninstall $(UNINSTALLFLAGS) + +reinstall: setup.data + $(SETUP) -reinstall $(REINSTALLFLAGS) + +clean: + $(SETUP) -clean $(CLEANFLAGS) + +distclean: + $(SETUP) -distclean $(DISTCLEANFLAGS) + +setup.data: + $(SETUP) -configure $(CONFIGUREFLAGS) + +configure: + $(SETUP) -configure $(CONFIGUREFLAGS) + +.PHONY: build doc test all install uninstall reinstall clean distclean configure + +# OASIS_STOP diff --git a/Source/builtin/basic_arithmetics.ml b/Source/builtin/basic_arithmetics.ml index ec0fd46..656e525 100644 --- a/Source/builtin/basic_arithmetics.ml +++ b/Source/builtin/basic_arithmetics.ml @@ -1,7 +1,8 @@ (** Basic arithmetics with built-in integers *) - +(**#use "builtin.ml";;**) open Builtin + (* Greater common divisor and smaller common multiple implemetations. *) @@ -10,7 +11,11 @@ open Builtin @param a non-zero integers @param b non-zero integer *) -let rec gcd a b = 0 +let rec gcd a b = + let r = modulo (sign a*a) (sign b*b) + in if r > 0 then + gcd (sign b *b) r + else b;; (* Extended Euclidean algorithm. Computing Bezout Coefficients. *) @@ -20,4 +25,13 @@ let rec gcd a b = 0 @param a non-zero integer @param b non-zero integer. *) -let bezout a b = (0, 0, 0) + +let rec bezout a b = + let rec bezout_rec u v r u1 v1 r1= + if r1 = 0 then + (u, v, a*u + b*v) + else + let q = r/r1 in + bezout_rec u1 v1 r1 (u-q*u1) (v-q*v1) (r-q*r1) + in bezout_rec 1 0 a 0 1 b;; + diff --git a/Source/builtin/ciphers.ml b/Source/builtin/ciphers.ml index 38d363b..b9f4aa1 100644 --- a/Source/builtin/ciphers.ml +++ b/Source/builtin/ciphers.ml @@ -13,14 +13,31 @@ open Power @param m word to cipher. @param b base ; for ASCII codes should be set to 255. *) -let encrypt_cesar k m b = [] +let encrypt_cesar k m b = + let rec encrypt_cesar_rec l = + match l with + [] -> [] + | e::l -> begin + let rot = modulo (e + k) b in + rot::encrypt_cesar_rec l + end + in encrypt_cesar_rec m;; + (** Cesar's cipher decryption @param k is an integer corresponding to key @param m encrypted word. @param b base ; for ASCII code should be set to 255. *) -let decrypt_cesar k m b = [] +let decrypt_cesar k m b = + let rec decrypt_cesar_rec l = + match l with + [] -> [] + | e::l -> begin + let rot = modulo (e - k) b in + rot::decrypt_cesar_rec l + end + in decrypt_cesar_rec m;; (********** RSA Cipher **********) @@ -30,21 +47,25 @@ let decrypt_cesar k m b = [] @param p prime number @param q prime number *) -let generate_keys_rsa p q = ((0,0), (0,0)) +let generate_keys_rsa p q = + let n = p * q in + let phi = (p-1) * (q-1) in + let e = phi - 1 in + let (d, _, _) = bezout e phi in + ((n, e), (n, d));; (** Encryption using RSA cryptosystem. @param m integer hash of message @param pub_key a tuple (n, e) composing public key of RSA cryptosystem. *) -let encrypt_rsa m (n, e) = 0 +let encrypt_rsa m (n, e) = mod_power m e n;; (** Decryption using RSA cryptosystem. @param m integer hash of encrypter message. @param pub_key a tuple (n, d) composing private key of RSA cryptosystem. *) -let decrypt_rsa m (n , d) = 0 -;; +let decrypt_rsa m (n , d) = mod_power m d n;; (********** ElGamal Cipher **********) @@ -52,23 +73,32 @@ let decrypt_rsa m (n , d) = 0 where p is prime and g having high enough order modulo p. @param p is prime having form 2*q + 1 for prime q. *) -let rec public_data_g p = (0, 0) +let rec public_data_g p = + let g = (p - 1)/2 in + (g, p);; (** Generate ElGamal public data. @param pub_data a tuple (g, p) of public data for ElGamal cryptosystem. *) -let generate_keys_g (g, p) = (0, 0) +let generate_keys_g (g, p) = + let r = modulo (787581985456192323) g in + let pub = mod_power g r p in (pub, r);; (** ElGamal encryption process. @param msg message to be encrypted. @param pub_data a tuple (g, p) of ElGamal public data. @param kA ElGamal public key. *) -let encrypt_g msg (g, p) kA = (0, 0) +let encrypt_g msg (g, p) kA = + let r = modulo (787581985456192323) g in + let c = mod_power g r p in + let d = msg * mod_power kA r p in + (c, d);; (** ElGamal decryption process. @param msg a tuple (msgA, msgB) forming an encrypted ElGamal message. @param a private key @param pub_data a tuple (g, p) of public data for ElGamal cryptosystem. *) -let decrypt_g (msgA, msgB) a (g, p) = 0 +let decrypt_g (msgA, msgB) a (g, p) = + msgB / (mod_power msgA a p);; diff --git a/Source/builtin/generate_primes.ml b/Source/builtin/generate_primes.ml index 2d3895f..b9a28f0 100644 --- a/Source/builtin/generate_primes.ml +++ b/Source/builtin/generate_primes.ml @@ -10,27 +10,61 @@ open Basic_arithmetics (** List composed of 2 and then odd integers starting at 3. @param n number of elements in the list of integers. *) -let init_eratosthenes n = [] +let init_eratosthenes n = + let rec init_eratosthenes_rec i = + match i with + i when i > n -> [] + | i when modulo i 2 = 1 -> i::init_eratosthenes_rec (i+2) + | i -> init_eratosthenes_rec (i+1) + in if n > 1 then + 2::init_eratosthenes_rec 3 + else [];; (* Eratosthenes sieve. *) (** Eratosthene sieve. @param n limit of list of primes, starting at 2. *) -let eratosthenes n = [] +let rec remove_multiples_from_list e l = + match l with + [] -> [] + | e1::l1 -> begin + match modulo e1 e with + 0 -> remove_multiples_from_list e l1 + | _ -> e1::remove_multiples_from_list e l1 + end;; + +let eratosthenes n = + let list = init_eratosthenes n in + let rec eratosthenes_rec l = + match l with + [] -> [] + | e::l1 -> begin + let l1 = remove_multiples_from_list e l1 in + e::eratosthenes_rec l1 + end + in eratosthenes_rec list (* Write and read into file functions for lists. *) (** Write a list into a file. Element seperator is newline. @param file path to write to. *) -let write_list li file = () +let write_list li file = + let oc = open_out file in + let rec write l = + match l with + [] -> close_out oc + | e::l1 -> Printf.fprintf oc "%d\n" e; write l1 + in write li;; (** Write a list of prime numbers up to limit into a txt file. @param n limit of prime numbers up to which to build up a list of primes. @param file path to write to. *) -let write_list_primes n file = () +let write_list_primes n file = + let list = eratosthenes n in + write_list list file;; (** Read file safely ; catch End_of_file exception. @param in_c input channel. @@ -42,12 +76,23 @@ let input_line_opt in_c = (** Create a list out of reading a line per line channel. @param in_c input channel. *) -let create_list in_c = () +let create_list in_c = + let rec read acc = + match input_line_opt in_c with + None -> acc + | Some l -> l::read acc + in read [];; (** Load list of primes into OCaml environment. @param file path to load from. *) -let read_list_primes file = [] +let read_list_primes file = + let list = create_list (open_in file) in + let rec put list = + match list with + [] -> [] + | e::l -> (int_of_string e)::put l + in put list;; (* Auxiliary functions to extract big prime numbers for testing purposes. @@ -80,11 +125,37 @@ let rec last_two l = match l with plus 1. @param limit positive integer bounding searched for primes. @param isprime function testing for (pseudo)primality. - *) -let double_primes limit isprime = [] +*) + + +let double_primes limit isprime = + let list = eratosthenes limit in + let rec double_primes_rec l = + match l with + [] -> [] + | e::l1 -> begin + let double = e * 2 + 1 in + if isprime double then + (e, double)::double_primes_rec l1 + else + double_primes_rec l1 + end + in double_primes_rec list;; (** Finding twin primes. @param limit positive integer bounding searched for primes. @param isprime function testing for (pseudo)primality. *) -let twin_primes limit isprime = [] +let twin_primes limit isprime = + let list = eratosthenes limit in + let rec double_primes_rec l = + match l with + [] -> [] + | e::l1 -> begin + let double = e + 2 in + if isprime double then + (e, double)::double_primes_rec l1 + else + double_primes_rec l1 + end + in double_primes_rec list;; diff --git a/Source/builtin/power.ml b/Source/builtin/power.ml index cbd3888..2062d5b 100644 --- a/Source/builtin/power.ml +++ b/Source/builtin/power.ml @@ -1,7 +1,7 @@ (** Power function implementations for built-in integers *) open Builtin -open Basic_arithmetics +open Basic_arithmetics;; (* Naive and fast exponentiation ; already implemented in-class. *) @@ -10,13 +10,25 @@ open Basic_arithmetics @param x base @param n exponent *) -let pow x n = 0 +let pow x n = + let rec pow_rec x1 n = + match n with + 0 -> x1 + | n -> pow_rec (x1*x) (n-1) + in pow_rec 1 n;; (** Fast integer exponentiation function. Logarithmic complexity. @param x base @param n exponent *) -let power x n = 0 +let power x n = + if n = 0 then 1 else + let rec power_rec x1 n = + match n with + 1 -> x1 + | n when modulo n 2 = 0 -> power_rec (x1 * x1) (n/2) + | n -> x1 * power_rec (x1 * x1) ((n-1)/2) + in power_rec x n;; (* Modular expnonentiation ; modulo a given natural number smaller max_int we never have integer-overflows if implemented properly. @@ -27,7 +39,17 @@ let power x n = 0 @param n exponent @param m modular base *) -let mod_power x n m = 0 +let mod_power x n m = + if n = 0 then + 1 + else + let rec mod_power_rec c e = + let c = modulo (x * c) m + in if e < n then + mod_power_rec c (e+1) + else + c + in mod_power_rec 1 1;; (* Making use of Fermat Little Theorem for very quick exponentation modulo prime number. @@ -39,4 +61,8 @@ let mod_power x n m = 0 @param n exponent @param p prime modular base *) -let prime_mod_power x n p = 0 +let prime_mod_power x n p = + if x = 0 then + 0 + else + mod_power x (modulo n (p - 1)) p;; diff --git a/Source/builtin/test_primes.ml b/Source/builtin/test_primes.ml index 9caa325..e1d074e 100644 --- a/Source/builtin/test_primes.ml +++ b/Source/builtin/test_primes.ml @@ -5,10 +5,36 @@ open Basic_arithmetics open Power (** Deterministic primality test *) -let is_prime n = true +let is_prime n = + if n = 2 || n = 3 then + true + else + if modulo n 2 = 0 || modulo n 3 = 0 then + false + else + let rec is_prime_rec k = + if (6*k-1) * (6*k-1) > n then + true + else + match (6*k-1, 6*k+1) with + (a, b) when modulo n a = 0 || modulo n b = 0 -> false + | _ -> is_prime_rec (k+1) + in is_prime_rec 1;; (** Pseudo-primality test based on Fermat's Little Theorem @param p tested integer @param testSeq sequence of integers againt which to test *) -let is_pseudo_prime p test_seq = true + +let is_pseudo_prime p test_seq = + let rec is_pseudo_prime_rec l = + match l with + [] -> true + | e::l1 when mod_power e (p-1) p <> 1 -> begin + if gcd e p = 1 then + false + else + is_pseudo_prime_rec l1 + end + | _::l1 -> is_pseudo_prime_rec l1 + in is_pseudo_prime_rec test_seq;; diff --git a/configure b/configure new file mode 100755 index 0000000..6acfaeb --- /dev/null +++ b/configure @@ -0,0 +1,27 @@ +#!/bin/sh + +# OASIS_START +# DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499) +set -e + +FST=true +for i in "$@"; do + if $FST; then + set -- + FST=false + fi + + case $i in + --*=*) + ARG=${i%%=*} + VAL=${i##*=} + set -- "$@" "$ARG" "$VAL" + ;; + *) + set -- "$@" "$i" + ;; + esac +done + +ocaml setup.ml -configure "$@" +# OASIS_STOP diff --git a/setup.ml b/setup.ml new file mode 100644 index 0000000..3b413ef --- /dev/null +++ b/setup.ml @@ -0,0 +1,39 @@ +(* setup.ml generated for the first time by OASIS v0.4.11 *) + +(* OASIS_START *) +(* DO NOT EDIT (digest: a426e2d026defb34183b787d31fbdcff) *) +(******************************************************************************) +(* OASIS: architecture for building OCaml libraries and applications *) +(* *) +(* Copyright (C) 2011-2016, Sylvain Le Gall *) +(* Copyright (C) 2008-2011, OCamlCore SARL *) +(* *) +(* This library is free software; you can redistribute it and/or modify it *) +(* under the terms of the GNU Lesser General Public License as published by *) +(* the Free Software Foundation; either version 2.1 of the License, or (at *) +(* your option) any later version, with the OCaml static compilation *) +(* exception. *) +(* *) +(* This library is distributed in the hope that it will be useful, but *) +(* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *) +(* or FITNESS FOR A PARTICULAR PURPOSE. See the file COPYING for more *) +(* details. *) +(* *) +(* You should have received a copy of the GNU Lesser General Public License *) +(* along with this library; if not, write to the Free Software Foundation, *) +(* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) +(******************************************************************************) + +let () = + try + Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH") + with Not_found -> () +;; +#use "topfind";; +#require "oasis.dynrun";; +open OASISDynRun;; + +let setup_t = BaseCompat.Compat_0_4.adapt_setup_t setup_t +open BaseCompat.Compat_0_4 +(* OASIS_STOP *) +let () = setup ();;