Προς το περιεχόμενο

Κρυπτογράφηση και κωδικοποίηση σε C++


Jaco

Προτεινόμενες αναρτήσεις

Δοθείσας της ευκαιρίας από ένα άλλο post περί κωδικοποίησης, άδραξα την ευκαιρία να ποστάρω ένα κείμενο περί κωδικοποίησης και συνεπώς κρυπτογραφίας που συνέταξα πριν λίγο καιρό για ένα παρόμοιου περιεχομένου site... Μου ήρθε ζαλάδα από το λεξιλόγιο που χρησιμοποίησα, δεν είμαι συνηθισμένος... Πάμε πάλι...

Η παρακάτω μακρουλή αηδία είναι μια μπαρούφα που έγραψα όταν δεν είχα κάτι καλύτερο να κάνω από το να βασανίζομαι με μ*λ*κίες και κρυπτογράφηση σε C...

Λοιπόν τιι κάνει νιάου-νιάου στα κεραμίδια; Αν βγαίναμε περίπατο στην γειτονιά και ρωτούσαμε τον κόσμο, τότε ένας τυχαίος θα μας έβριζε, άλλος θα έλεγε «μια γάτα φυσικά!», ένας σκύλος θα έλεγε «το απογευματινό μου βέβαια?», ένας κτηνίατρος «Ένα κοινό μικρό σαρκοφάγο ζώο της οικογένειας των αιλουροειδών.», ο μουγκός της γειτονιάς «?», ενώ μόνο ένας καχύποπτος και πονηρός σαν εσένα θα έλεγε «αποκλείεται να είναι γάτα, πρέπει να είναι ένα γάβγισμα κρυπτογραφημένο». Η αρρώστια της κρυπτογραφίας βλέπεις? Και όμως σήμερα δεν αποτελεί μόνο ένα σενάριο ή ένα πανηλίθιο παράδειγμα, αλλά σε πολλές περιπτώσεις, πραγματικά μπορούμε ένα μήνυμα να το κωδικοποιήσουμε με τέτοιο τρόπο, ώστε να το καμουφλάρουμε και να του δώσουμε μια μορφή λιγότερο «ύποπτη».

Αλλά ας μιλήσουμε με παραδείγματα. Ένας από τους πιο κλασσικούς τρόπους να καμουφλάρουμε ένα κείμενο, είναι να πάρουμε έναν hex file editor, το αρχείο σε μορφή κειμένου (*.txt, *.doc), έναν υπολογιστή και μια φωτογραφία σε ψηφιακή μορφή ( π.χ. jpeg). Τώρα δυο από εσάς αναρωτιούνται αν ακολουθεί συνταγή μαγειρικής, τέσσερις αν έχω λαλήσει, δυο έχουν κλείσει ήδη το post, ενώ ένας περιμένει ακόμα. Οπότε για τον ένα συνεχίζω να λέω, ότι αν με τον hex editor ανοίξουμε το *.txt αρχείο, τότε θα δούμε την ASCII μορφή των χαρακτήρων. Αυτοί δεν είναι τίποτα άλλο από ένα byte για κάθε χαρακτήρα. Μια ψηφιακή φωτογραφία από την άλλη, αποτελείται και αυτή από bytes, με την διαφορά ότι δεν συμβολίζουν χαρακτήρες, αλλά χρώματα, φωτεινότητα, θέση κ.τ.λ. Ας μείνουμε όμως στην θέση.

Μια φωτογραφία αποτελείται από οριζόντιες και κάθετες γραμμές και οι γραμμές αυτές από σημεία, τα οποία ανάλογα με το χρώμα τους τελικά σχηματίζουν την τελική εικόνα. Κάθε γραμμή, βέβαια τελειώνει κάπου!!! (πσσσς...). Τώρα αρχίζει το ωραίο... Τι θα γινόταν αν στο τέλος της κάθε γραμμής, αντικαθιστούσαμε το byte της φωτεινότητας της εικόνας με το byte του κειμένου; Τίποτα υπερβολικά φανερό, το πολύ ? πολύ να ήταν λίγο πιο έντονη η φωτεινότητα στο τέλος της φωτογραφίας, πράγμα που δεν μας νοιάζει, εκτός και είναι καμιά φωτογραφία της γκόμενας και μετά γκρινιάζει, επειδή την κάναμε έτσι, αρά καλό είναι να προσέχουμε... Ας δούμε τι έχουμε καταφέρει μέχρι τώρα...

Αυτή την στιγμή έχουμε μια φωτογραφία, η οποία μέσα της έχει ενσωματωμένο ένα κείμενο, πράγμα που σημαίνει ότι καταφέραμε να το καμουφλάρουμε χωρίς να έχουμε χάσει την πληροφορία. Εντυπωσιαστήκατε; ...Όχι;! Τι θα λέγατε αν σας έλεγα ότι μπορούμε να το κάνουμε και με ένα αρχείο ήχου; ?Ούτε πάλι;! Τέλος πάντων με τις γυναίκες «πιάνει»... Το μόνο πρόβλημα είναι ότι σε ένα αρχείο ήχου μπορεί να έχουμε κάποιες παραμορφώσεις, όπως αυξομείωση της έντασης του ήχου, αλλαγή της κυματομορφής, της συχνότητας και άλλα, στα σημεία που έχει γίνει η επέμβαση. Επειδή όμως το αυτί σε αυτήν τη περίπτωση, είναι πιο ευαίσθητο από το μάτι ή ακόμα και επειδή μπορεί να καταστρέψουμε το αρχείο, αν δεν ξέρουμε που ακριβώς κάνουμε την επέμβαση τότε καλύτερα να μην το κάνουμε, εκτός και είναι κανένα κομμάτι της Βανδής ή καμιάς ξενέρωτης σκυλού και το σιχαινόμαστε...

Για να ανακτήσουμε πάλι το αρχικό κείμενο από το καμουφλαρισμένο, τότε αρκεί να κάνουμε την αντίστροφη διαδικασία. Σημαντικός παράγοντας για την επιλογή του αρχείου εικόνας, είναι το μέγεθος του κειμένου. Παρόλο που συνήθως δεν υπάρχει πρόβλημα, καλό είναι να πούμε ότι η ανάλυση της εικόνας και το τελικό μέγεθός της είναι ανάλογα του μεγέθους του κειμένου και αυξάνονται με την αύξηση αυτού... Συνεχίζοντας στις λεπτομέρειες να πούμε, ότι είναι προτιμότερο να χρησιμοποιήσουμε μια φωτογραφία με μεγάλες διακυμάνσεις χρώματος και φωτεινότητας και όχι το αντίστροφο... Αυτό γιατί οι επεμβάσεις γίνονται πιο δυσδιάκριτες στην πρώτη των περιπτώσεων...

Με λίγη όρεξη μπορεί κανείς να σκεφτεί και άλλους τρόπους να καμουφλάρει κανείς τα αρχεία και τα κείμενά του... Μην μου πείτε αλλάζοντας την κατάληξη, γιατί είναι το πλέον παιδικό και ένας κρυπταναλυτής που θα πέσει στα χέρια του θα κάνει καιρό να συνέλθει από το γέλιο... Ένας τρόπος π.χ. να περάσει απαρατήρητο το αρχείο σας μέσα στο internet είναι να το ονομάσετε ʽterrorist.usaʼ. Δεν σας λέω τίποτα, την άλλη μέρα θα ξυπνήσετε δαρμένος και κρεμασμένος με αλυσίδες ανάποδα στην οροφή ενός σκοτεινού κλουβιού, κάπου σε ένα νησί, που στάζει νερό και ζέχνει και για τα υπόλοιπα 3 χρόνια θα σκέφτεστε ότι θα ήταν προτιμότερο να είχες δώσει ένα καλύτερο όνομα στο αρχείο σας... Αλλά παθαίνοντας μαθαίνει κανείς?

 

Λίγα για τα Πρωτόκολλα...

 

Στην κρυπτολογία υπάρχουν πολλά πρωτόκολλα, τα οποία αφενός καθορίζουν τους αλγόριθμους κρυπτογράφησης και αποκρυπτογράφησης και αφετέρου περιγράφουν την διαδικασία εφαρμογής τους και κάτω από ποιες συνθήκες... Έτσι υπάρχουν πρωτόκολλα τα οποία χωρίζονται σε κατηγορίες, ανάλογα με την χρήση τους και τις επιθυμητές συνθήκες... Για παράδειγμα σε ένα τηλεπικοινωνιακό κανάλι, το οποίο έχει μια συνεχή ροή δεδομένων, χρειαζόμαστε ένα πρωτόκολλο γρήγορο, έτσι ώστε να μην δημιουργείται καθυστέρηση των δεδομένων... Στο ίδιο παράδειγμα, ανάλογα με το είδος της πληροφορίας διαλέγουμε αν το πρωτόκολλο θέλουμε να παρέχει την μέγιστη ασφάλεια (π.χ. κλειδιά 512 ή 1024 bits) ή μικρότερη (50, 64 bits κ.τ.λ.)... Φυσικά όσο μεγαλώνει το κλειδί, αυξάνει και ο χρόνος κρυπτογράφησης/ αποκρυπτογράφησης των δεδομένων, άρα αυξάνει η καθυστέρηση... Από την άλλη παίζει ρόλο αν τα δεδομένα χρειάζεται να μείνουν κρυφά για πολύ χρόνο ή όχι, έτσι αν η αξία της πληροφορίας χάνεται μετά από μερικά λεπτά ή ώρες, τότε φυσικά δεν χρειαζόμαστε μεγάλα κλειδιά... Αν όλα αυτά δεν ισχύουν και η επικοινωνία είναι περιοδική, τότε προτιμούμε αυξημένη προστασία, καθώς δεν μας νοιάζει η ταχύτητα της διεργασίας... Τέτοιο παράδειγμα είναι π.χ. τα e-mail, όπου η σύνδεση δυο ατόμων δεν είναι συνεχής, αλλά σποραδική...

Το κύριο χαρακτηριστικό αυτών των πρωτοκόλλων είναι οι αλγόριθμοι κατασκευής κλειδιών και το εύρος τους... Έτσι υπάρχουν δυο βασικές κατηγορίες, οι συμμετρικοί και ασύμμετροι αλγόριθμοι... Παρακάτω ακολουθεί μια γρήγορη περιγραφή τους, αλλά θα εμμείνω περισσότερο στους ασύμμετρους...

 

--Συμμετρικοί αλγόριθμοι.

 

Συμμετρικοί αλγόριθμοι κρυπτογράφησης, είναι οι αλγόριθμοι οι οποίοι δημιουργούν ένα κλειδί συγκεκριμένου εύρους, το οποίο χρησιμοποιείται και για κρυπτογράφηση και αποκρυπτογράφηση... Τα θετικά του είναι ότι αυτοί οι αλγόριθμοι είναι μέχρι και 1000 φορές πιο γρήγοροι από τους ασύμμετρους, όταν η κρυπτογράφηση γίνεται μέσω hardware και 100 φορές όταν γίνεται μέσω software... Δηλαδή με όσα λέγαμε παραπάνω είναι ιδανικοί για τηλεπικοινωνιακά κανάλια, όπου η ταχύτητα παίζει μεγάλο ρόλο... Το προτέρημα αυτό, ισοσταθμίζεται όμως με την μειωμένη προστασία που προσφέρει... Μειωμένη, γιατί το ίδιο κλειδί πρέπει να έχουν όλοι όσοι συμμετέχουν σε μια επικοινωνία και αυτή πρέπει να γίνεται με το ίδιο κλειδί μέχρι να τελειώσει...

Αυτό είναι ελάττωμα και θα πούμε γιατί... Ας υποθέσουμε ότι κάποιος θέλει να επικοινωνήσει με κάποιον κολλητό του Σεφ και θα χρησιμοποιήσει ένα συμμετρικό αλγόριθμο... Η επικοινωνία γίνεται π.χ. γιατί θέλει να μάθει την μυστική συνταγή για τα φασόλια που δεν προκαλούν ακατάσχετο κλάσιμο και την ξέρει μόνο ο Σεφ και δεν θέλει να διαρρεύσει πουθενά γιατί από αυτήν κερδίζει πολλά λεφτά... Οπότε ο πρώτος δημιουργεί ένα κλειδί και τώρα πρέπει να το στείλει στον δεύτερο μέσω της γραμμής του καναλιού επικοινωνίας... Έλα όμως που ένας τρίτος έχει εισβάλει στην γραμμή και παίρνει και αυτός το κλειδί, οπότε μπορεί να ακούσει όλη την επικοινωνία... Εν τω μεταξύ δεν υπάρχει τρόπος να το καταλάβει κανένας από τους δυο πρώτους, καθώς δεν μπορεί να ξέρουν τι γίνεται ενδιάμεσα στην γραμμή... Αποτέλεσμα είναι τελικά ο υποκλοπέας να πουλήσει την συνταγή στην Βέφα και την επόμενη μέρα να την δουν όλοι στον πρωινό καφέ (ή όπου έχει πάει τέλος πάντων)... Βέβαια ο Σεφ σκοτώνει τον φίλο του και στην φυλακή που πάει ,όταν ακούει «φασόλια» σκοτώνει και από έναν...

 

--Ασύμμετροι αλγόριθμοι.

 

Ασύμμετροι αλγόριθμοι κρυπτογράφησης, είναι οι αλγόριθμοι οι οποίοι δημιουργούν δυο κλειδιά συγκεκριμένου εύρους, από τα οποία το πρώτο από αυτά χρησιμοποιείται για κρυπτογράφηση και το δεύτερο για αποκρυπτογράφηση... Τα δυο κλειδιά δεν έχουν καμία σχέση μεταξύ τους και από το ένα δεν μπορούμε να αντλήσουμε καμιά πληροφορία για το άλλο... Το κλειδί της κρυπτογράφησης το ονομάζουμε δημόσιο (public key), ενώ της αποκρυπτογράφησης ιδιωτικό (private key)... Οι ονομασίες αυτές έχουν νόημα γιατί το πρώτο κλειδί το δημοσιοποιούμε σε όλους όσους θέλουν να επικοινωνήσουν μαζί μας, ελεύθερα χωρίς να μας νοιάζει σε τι χέρια θα πέσει (βέβαια οι προφυλάξεις καλό είναι να υπάρχουν πάντα, δεν μιλάω για το sex)... Το δεύτερο κλειδί το κρατάμε για εμάς μόνο...!!

Το θετικό είναι ότι η επικοινωνία τώρα είναι πολύ πιο ασφαλής... Από την άλλη η ταχύτητα μειώνεται δραματικά, πράγμα που για ορισμένες εφαρμογές (π.χ. ζωντανή επικοινωνία), η χρήση του είναι αδύνατη (και για το στρατό άραγε;;;). Συνήθως όμως χρησιμοποιούμε μια υβριδική μέθοδο η οποία ακολουθεί παρακάτω...

 

--Υβριδική μέθοδος.

 

Αυτή η μέθοδος προσπαθεί να συνδυάσει τους ασύμμετρους με τους συμμετρικούς αλγόριθμους και να εκμεταλλευτεί τα προτερήματα τους... Δηλαδή για την κανονική επικοινωνία χρησιμοποιούμε ένα συμμετρικό αλγόριθμο του οποίου όμως το κλειδί έχουμε ανταλλάξει με ασύμμετρο τρόπο... Καλά, καλά μην φωνάζετε, ακολουθεί παράδειγμα? Η συνταγή να είναι με φασόλια ή μπάμιες..; Πάμε μπάμιες...

Οπότε ο καλός μας Σεφ κατά την διάρκεια της κράτησης του βρίσκει μια καταπληκτική συνταγή για μπάμιες τώρα, η οποία και αυτή έρχεται να σώσει αυτούς που τους προκαλούν συμπιεστική πορδοροή... Ταυτόχρονα όμως ένας άλλος κολλητός του Σεφ, του οποίου το οικογενειακό περιβάλλον υποφέρει από ασφυξία και πνιγμό κάθε φορά που έχουν μπάμιες, του ζητά να του δώσει την συνταγή... Διδαγμένος από τον μακάβριο θάνατο του άλλου του φίλου θα χρησιμοποιήσει ένα υβριδικό πρωτόκολλο και συγκεκριμένα δημιουργεί με έναν ασύμμετρο αλγόριθμο ένα ιδιωτικό και ένα δημόσιο κλειδί, εκ των οποίων το δημόσιο το στέλνει στον έγκλειστο Σεφ... Ψυλλιασμένη τώρα η Βέφα δεν κάθεται άπραγη, αλλά υποκλέπτει το κλειδί... Ο τύπος όμως λέει στον Σεφ να δημιουργήσει ένα συμμετρικό κλειδί με το οποίο θα γίνει η κυρίως επικοινωνία, να το κρυπτογραφήσει με το δημόσιο κλειδί και να του το στείλει... Και αυτό γίνεται... Η Βέφα υποκλέπτει και το κρυπτογραφημένο κλειδί... Αρχ*δια όμως... Με το δημόσιο κλειδί που έχει είναι αδύνατο φυσικά να αποκρυπτογραφήσει ένα μήνυμα που έχει κρυπτογραφηθεί με αυτό, μόνο το ιδιωτικό μπορεί... Έτσι ο τύπος παίρνει το κλειδί, το αποκρυπτογραφεί και τελικά συνεχίζεται και ολοκληρώνεται η επικοινωνία με αυτό... Έτσι η Βέφα δεν μαθαίνει την συνταγή, η οικογένεια του τύπου κάνει πάρτυ και ο Σεφ πνίγεται από μια μπάμια και πεθαίνει...

Επομένως το ηθικό δίδαγμα δεν είναι μόνο να μασάτε καλά πριν καταπιείτε, αλλά κυρίως ότι είναι προτιμότερη η χρήση υβριδικών μεθόδων, λόγο της αυξημένης ασφάλειας που προσφέρουν...

 

Ναι μεν... αλλά...

 

Καλά όλα αυτά, πλάκα έχουν, αλλά είναι καιρός να βουτήξουμε στα βαθιά και να μιλήσουμε λίγο για τους αριθμούς και τα μαθηματικά που κρύβονται πίσω από όλα αυτά τα πράγματα... Σκοπός είναι να μελετήσουμε και να αναλύσουμε μερικούς πολύ βασικούς αλγόριθμους κατασκευής κλειδιών... Στην συγκεκριμένη ανάλυση θα χρησιμοποιήσουμε τον γνωστό καλό, αλλά σχετικά παλιό ασύμμετρο αλγόριθμο RSA (από το 1979).

Γενικά αυτός ο αλγόριθμος φέρει τα αρχικά των δημιουργών του οι οποίοι είναι : Ron Rivest, Adi Shamir και Leonard Adleman (Μην μου πείτε ότι δεν τους ξέρετε...?!? τς... τς...). Αυτοί οι αξιότιμοι κύριοι λοιπόν, δημιούργησαν έναν αλγόριθμο με την βοήθεια του οποίου μπορούμε να φτιάξουμε κλειδιά των 100, 200 αλλά και παραπάνω bits... Η τιμή εξαρτάται από το διαθέσιμο hardware και όχι από το software, δηλαδή εξαρτάται από το εύρος του data bus και των καταχωρητών που αναλαμβάνουν τις πράξεις...

Αρχικά λοιπόν, ο αλγόριθμος δημιουργήθηκε για χρήση του μόνο σε hardware κωδικοποιητές / αποκωδικοποιητές και για στρατιωτική χρήση στα τηλεπικοινωνιακά συστήματα του αμερικάνικου στρατού... Για κάποιο λόγο όμως διέρρευσε και κάποιοι τρελαμένοι πήραν τον αλγόριθμο και του άλλαξαν τα φώτα, με αποτέλεσμα να γραφεί σε software και να χρησιμοποιηθεί κατά κόρον... Φυσικά ο στρατός είχε σταματήσει ήδη να τον χρησιμοποιεί και μάλλον ήταν και ο λόγος που διέρρευσε, αφενός γιατί ο στρατός είχε κατασκευάσει έναν καλύτερο και αφετέρου δίνοντας τον σε διάφορες κοινότητες (πανεπιστήμια κ.τ.λ.), δοκίμαζε την ποιότητα του, αλλά μπορούσε και να ελέγχει με έμμεσο τρόπο την κατεύθυνση αυτών των τρελαμένων αυτών κοινοτήτων... Γενικά όλοι οι συμμετέχοντες αρνήθηκαν ότι ο αλγόριθμος αυτός χρησιμοποιήθηκε από τον στρατό και τα σχετικά (ναι, εντάξει... Τι άλλα νέα...;). Αρκετά με την ιστορία, πάμε στην ουσία... (Ωραίο στιχάκι... :P )

Το σημαντικό με τον RSA είναι ότι μπορεί να δημιουργήσει κλειδιά μεγάλου μήκους, με αποτέλεσμα να είναι πρακτικά αδύνατο να τον σπάσει κανείς με απλές μεθόδους όπως το άμεσο σπάσιμο του κώδικα ή brutal attack, δηλαδή σα να έχει κάποιος ένα λουκέτο με τετραψήφιο κωδικό και να ξεκινάει από το 0000 και να γυρνάει τα κουμπιά με στόχο το 9999, μπας και πετύχει τον κωδικό.... Σκεφτείτε να το κάνετε αυτό και μετά από τρεις μέρες ξενύχτη, να καταλάβετε ότι το λουκέτο είναι χαλασμένο... πακέτο... Πόσο μάλλον όταν μιλάμε για συνδυασμούς των 512 bits, δηλαδή 2512 συνδυασμοί, ?ζαλίστηκα...

Ο RSA χρησιμοποιεί δυο κλειδιά ένα δημόσιο (public key) και ένα ιδιωτικό (private key)... Το πρώτο το δίνουμε σε κάποιον που θέλει να επικοινωνήσει μαζί μας, ώστε να κρυπτογραφήσει το μήνυμα του με αυτό, ενώ το δεύτερο το κρατάμε για την πάρτη μας, καθώς μόνο αυτό μπορεί να ξεκλειδώσει το κωδικοποιημένο μήνυμα... Βεβαίως ισχύει και το αντίστροφο... Η χρησιμότητα αυτή είναι μεγάλη, καθώς από το δημόσιο κλειδί δεν μπορούμε να αντλήσουμε καμιά πληροφορία για το ιδιωτικό, ούτε και το αντίθετο... Το μόνο που συνδέει αυτά τα δυο κλειδιά είναι ένα τρίτο που τα ελέγχει και τα δυο (κάτι σαν τα δαχτυλίδια στον άρχοντα των δαχτυλιδιών ένα πράγμα...) Αλλά πάλι έχοντας δυο από τα τρία, δεν μπορούμε να γνωρίζουμε το τρίτο. Μην μου πείτε ότι σας μπέρδεψα από τώρα, σε λίγο αρχίζουν τα καλά...

Ας υποθέσουμε ότι ένας παντρεμένος έχει μια γκόμενα... Αυτός μένει στους Θρακομακεδώνες με την γυναίκα του και αυτή στην Γλυφάδα, καμιά σχέση δηλαδή... Ο τύπος λοιπόν έχει κάνει καλή επιλογή, γιατί και οι δυο βρίσκονται μακριά και δεν γνωρίζουν η μια την άλλη... Όταν λοιπόν θέλει να συναντηθεί με την γκόμενα, τότε στην γυναίκα του λέει ένα ψέμα, π.χ. ότι πάει να παίξει μπάλα με τους φίλους του (πάντως γκολ σίγουρα βάζει...). Έτσι η γυναίκα του είναι το δημόσιο κλειδί, αποκρύβοντας την γκόμενα... Από την άλλη η γκόμενα είναι το ιδιωτικό κλειδί, αφού ξέρει το ψέμα (άρα το αποκρυπτογραφεί), αλλά δεν γνωρίζει την ίδια την γυναίκα του τύπου, δηλαδή το κλειδί... Ο τύπος είναι το τρίτο ενδιάμεσο κλειδί που ελέγχει τα αλλά δυο, τα οποία απορρέουν και από αυτόν, αφού είναι ο ενδιάμεσος κρίκος... Όργιο... Η γυναίκα του λοιπόν ξέρει το δημόσιο και ενδιάμεσο κλειδί, αλλά δεν μπορεί να αντλήσει καμία πληροφορία για την γκόμενα, δηλαδή το δημόσιο κλειδί... Από την άλλη η γκόμενα ξέρει το ιδιωτικό και ενδιάμεσο κλειδί, αλλά δεν μπορεί να ξέρει το δημόσιο... Αλλά ένας κανόνας στην κρυπτογραφία, λέει ότι για την μέγιστη ασφάλεια δεν πρέπει ποτέ να χρησιμοποιείς παραπάνω από μια φορά το ίδιο κλειδί, γιατί η πιθανότητα τότε να αποκρυπτογραφηθεί ένα μήνυμα αυξάνει... Έτσι αν ο τύπος συνεχίσει να λέει το ίδιο ψέμα, κάποια στιγμή θα φάει τηγανιά...

Βέβαια το κείμενο δεν λέγεται «ένα εκατομμύριο τρόποι να απατήσετε την γυναίκα σας», αλλά ούτε και σας συμβουλεύει να το κάνετε... (αληταράδες...) Από την άλλη όμως είναι καλός τρόπος να αντιληφθούμε τι γίνεται... Αυτό που μένει τελικά, είναι ότι ο RSA υπολογίζει μέσω ενός κεντρικού κλειδιού, ένα κλειδί για κρυπτογράφηση και ένα δεύτερο για αποκρυπτογράφηση...

Αρχικά διαλέγουμε δυο τυχαίους πρώτους αριθμούς p,q. (Πρώτοι αριθμοί, όπως όλοι θυμόμαστε, λέγονται όλοι οι αριθμοί, μεγαλύτεροι της μονάδας, οι οποίοι διαιρούνται τέλεια, μόνο με τον εαυτό τους και την μονάδα... Τέτοιοι είναι το 2, 3, 5, 7, 73 κ.τ.λ. οι οποίοι φυσικά είναι άπειροι...) Αυτούς τους δυο αριθμούς τους πολλαπλασιάζουμε και το γινόμενο τους το συγκρατούμε, κρατώντας μυστικούς πάντα τους δυο πολλαπλασιαστέους... Δηλαδή με άλλα λόγια..:

 

n = p*q

 

Έπειτα διαλέγουμε τυχαία ένα κλειδί για κωδικοποίηση (δημόσιο), με την προϋπόθεση όμως ότι είναι πρώτος αριθμός σε σχέση με το γινόμενο (p-1)*(q-1)... Το γινόμενο αυτό είναι το τρίτο κλειδί που ελέγχει τα άλλα δυο, αλλά δεν έχει καμία χρησιμότητα μετά από την δημιουργία των άλλων δυο κλειδιών... Βέβαια τα q, p τα κρατάμε, αλλά μυστικά... Επομένως..:

 

e = σχετικός πρώτος του (p-1)*(q-1)

 

Αμέσως μετά μπορούμε να υπολογίσουμε και το ιδιωτικό κλειδί (αποκωδικοποίησης) από την σχέση..:

 

d = e^-1 * mod[(p-1)*(q-1)]

 

Τώρα έχοντας κατασκευάσει τα δυο κλειδιά, βλέπουμε ότι όλα εξαρτώνται από τους παράγοντες p,q και e... Το μεν γινόμενο των δυο πρώτον το χρησιμοποιούμε και κατά την κρυπτογράφηση και κατά την αποκρυπτογράφηση... Ας δούμε ένα γρήγορο παράδειγμα..:

Έστω ότι έχουμε μια αριθμοσειρά, 1234567890987654321 την οποία και θέλουμε να κρυπτογραφήσουμε. Σύμφωνα με τα βήματα που προαναφέραμε αρχικά διαλέγουμε δυο πρώτους αριθμούς π.χ.

 

p = 73 και q = 23

 

Οπότε το γινόμενο τους είναι:

 

n = p*q = 1679

 

Στην συνέχεια υπολογίζουμε το γινόμενο:

 

 

(p-1)*(q-1) = 1584

 

Έπειτα διαλέγουμε ένα τυχαίο δημόσιο κλειδί για κρυπτογράφηση e, το οποίο όμως να είναι πρώτος αριθμός σε σχέση με το προηγούμενο γινόμενο, οπότε έστω ότι..:

 

e=113

 

Άρα το ιδιωτικό κλειδί είναι:

 

d = e^-1 * mod[(p-1)*(q-1)]=785

 

Όλοι οι υπολογισμοί γίνανε με το cryptculator, ένα προγραμματάκι που έχω γράψει σε Visual C++ και μόλις φτιάξω ένα briefcase θα το σηκώσω, αφού δόθηκαν οι δυο τιμές Prime Num #1 = 73 και Prime Num #2 = 23, δηλαδή τα p και q και πατώντας το calculate στο πεδίο ʽModular Calculationsʼ. Οπότε μετά από αυτά έχουμε δημιουργήσει το κλειδί κρυπτογράφησης e (δημόσιο) και αποκρυπτογράφησης d (ιδιωτικό).

Επόμενο βήμα είναι σπάσουμε το αρχικό μήνυμα σε μικρότερα, τα οποία πρέπει να είναι τριάδες και συγκεκριμένα:

 

123 456 789 098 765 432 001 <- Προσέξτε το τέλος!

 

Έπειτα ο αλγόριθμος κρυπτογράφησης είναι ο παρακάτω και ισχύει πάντα:

 

c = m^e * mod(n)

 

Όπου c: το προκύπτων κωδικοποιημένο μήνυμα

m: το αρχικό μήνυμα

e: το δημόσιο κλειδί για κρυπτογράφηση

n: το γινόμενο των μυστικών παραγόντων.

 

Οπότε για το μήνυμα μας έχουμε:

m1: 123, m2: 456, m3: 789, m4: 098, m5: 765, m6: 432, m7: 001, άρα:

 

 

c1 = m1^113 * mod(1679) = 123^113 * mod(1679) = 213

c2 = m2^113 * mod(1679) = 456^113 * mod(1679) = 1569

c3 = m3^113 * mod(1679) = 789^113 * mod(1679) = 1493

c4 = m4^113 * mod(1679) = 098^113 * mod(1679) = 561

c5 = m5^113 * mod(1679) = 765^113 * mod(1679) = 492

c6 = m6^113 * mod(1679) = 432^113 * mod(1679) = 473

c7 = m7^113 * mod(1679) = 001^113 * mod(1679) = 1

 

 

Δηλαδή 213 1569 1493 561 492 473 001...

 

Φυσικά αν πάει κάποιος να υπολογίσει με ένα calculator ή κανένα μαθηματικό πρόγραμμα καμιά δύναμη του τύπου 789^113, μάλλον θα απογοητευτεί, αφού είναι σίγουρο ότι αν δεν βγάλει καπνούς θα δείξει ένα ωραίο «?Ε-», δηλαδή σφάλμα... Για τον υπολογισμό αυτό χρησιμοποιούμε έναν δυσνόητο αλλά ταχύτατο αλγόριθμο, τον οποίο θα εξηγήσω στο μαθηματικό μέρος που ακολουθεί, βέβαια με το cryptculator μπορείτε να υπολογίσετε εύκολα τέτοιες συναρτήσεις...

 

Αντίστροφα τώρα πάμε να κάνουμε αποκρυπτογράφηση με την σχέση που ισχύει πάντοτε και είναι:

 

m = c^d * mod(n)

 

Όπου c: το προκύπτων κωδικοποιημένο μήνυμα

m: το αρχικό μήνυμα

d: το ιδιωτικό κλειδί για κρυπτογράφηση

n: το γινόμενο των μυστικών παραγόντων.

 

Οπότε έχουμε:

 

 

m1 = c1^785 * mod(1679) = 123^785 * mod(1679) = 123

m2 = c2^785 * mod(1679) = 1569^785 * mod(1679) = 456

m3 = c3^785 * mod(1679) = 1493^785 * mod(1679) = 789

m4 = c4^785 * mod(1679) = 561^785 * mod(1679) = 098

m5 = c5^785 * mod(1679) = 492^785 * mod(1679) = 765

m6 = c6^785 * mod(1679) = 473^785 * mod(1679) = 432

m7 = c7^785 * mod(1679) = 001^785 * mod(1679) = 001

 

Παρατηρείτε φυσικά ότι τα αποτελέσματα είναι τα αναμενόμενα, άρα καταφέραμε να κατασκευάσουμε δυο κλειδιά, ανεξάρτητα μεταξύ τους, αλλά και να κωδικοποιήσουμε και να αποκωδικοποιήσουμε μια αριθμοσειρά... Αν δοκιμάσετε να αποκρυπτογραφήσετε με το δημόσιο κλειδί, θα διαπιστώσετε ότι δεν θα βγαίνουν τα σωστά αποτελέσματα... Γενικά το ιδιωτικό κλειδί είναι το μοναδικό που μπορεί να αποκρυπτογραφήσει...

Στο m2 παρατηρείτε ότι υπάρχει μια δύναμη της τάξης του 1569^785... Όπως είπαμε μην πάτε να κάνετε τέτοιες πράξεις πουθενά, δεν γίνονται... Απλά στην modular algebra και με κάποιους πολύ γρήγορους αλγόριθμους μπορούμε να υπολογίσουμε αυτά τα αποτελέσματα με πολύ λίγους πολλαπλασιασμούς... Όποιος έχει κουράγιο να τους ρίξει μια ματιά παρακάτω, ας το κάνει. Αλλιώς, είπαμε το Cryptculator TM ? Ltd United ?kai ta resta!!!

 

 

Λίγη θεωρία αριθμών, δε βλάπτει...

 

Καλά όλα αυτά που μας λες ρε Λάκη, θα πείτε, αλλά εδώ υπάρχει ολόκληρη μαθηματική θεωρία για το πώς λύνονται αυτές οι εξισώσεις και αναλύονται στην Modular Algebra... Η mod είναι μια εξίσωση στροφής που χρησιμοποιείται απλά να περιστρέφει ένα κλειστό σύνολο τιμών γύρο από τον εαυτό του... Παρακάτω ακολουθεί η ανάλυση για τους ανήσυχους τύπους, η οποία είναι βασισμένη και στην δημιουργία ταχέων αλγορίθμων σε C++...

Ας τα πάρουμε όλα από την αρχή... Πρώτα ήταν οι δεινόσαυροι... Χμ, λάθος... Συνεχίζουμε... Θυμίζουμε ότι η συνάρτηση xmod(n), απλά λέει ότι αν έχουμε σύνολο n ακέραιων αριθμών, ο οποίος έχει μια κυκλική φορά, δηλαδή αν έχουμε το σύνολο {1,2,3,4,?.,n}, τότε ο αριθμός n+1 στην ουσία είναι πάλι η αρχή, δηλαδή 1, ο n+2 είναι το 2 κ.ο.κ. Με άλλα λόγια είναι το υπόλοιπο της ακέραιας διαίρεσης του n/x, χωρίς δηλαδή να συνεχίζουμε στον υπολογισμό των δεκαδικών ψηφίων... Είναι σαν την σημειολογία της ώρας, όπου το 13:00 είναι μία η ώρα, 14:00 είναι δύο η ώρα κ.τ.λ. Οπότε για την ώρα μπορούμε να πούμε ότι είναι μια συνάρτηση xmod(12)... Κάτι παρόμοιο γίνεται και με τον άνθρωπο, πρώτα πίνουμε νερό μετά κατουράμε, μετά τρώμε και χέζουμε, μετά ξαναπίνουμε νερό και ξανακατουράμε και η αηδία συνεχίζεται...

Στην modular algebra ισχύουν οι ιδιότητες της κανονικής άλγεβρας για τις πράξεις των αριθμών, δηλαδή η αντιμεταθετική ιδιότητα, η προσεταιριστική κ.τ.λ. Έτσι αν θεωρήσουμε δυο ακέραιους a,b,c σε ένα πεδίο n, τότε γιʼ αυτά ισχύει:

 

(a+B)*mod(n) = (a*mod(n) + b*mod(n))*mod(n)

(a-B)*mod(n) = (a*mod(n) - b*mod(n))*mod(n)

(a*B)*mod(n) = (a*mod(n) * b*mod(n))*mod(n)

 

Στην κρυπτογραφία χρησιμοποιούνται κατά κόρων οι υπολογισμοί mod, επειδή είναι δύσκολοι στην λύση τους, ιδιαίτερα όταν εμπλέκονται μεγάλες δυνάμεις και λογάριθμοι, αλλά και επειδή στους υπολογιστές μπορούμε να εκμεταλλευτούμε μια πολύ σημαντική ιδιότητα που παρουσιάζουν στον υπολογισμό των δυνάμεων... Γιʼ αυτά θα μιλήσουμε αμέσως τώρα...

 

Ας υποθέσουμε ότι έχουμε μια δύναμη a^x, την οποία θέλουμε να υπολογίσουμε σε ένα modular χώρο (n)... Τότε πρέπει να υπολογίσουμε την εξής συνάρτηση..:

 

a^x*mod(n)

 

Την συνάρτηση μπορούμε απλά να την δούμε σαν ένα συνδυασμό πολλαπλασιασμών και μιας διαίρεσης. Δηλαδή είναι σαν να έχουμε:

 

(a*a*a*...*a)*mod(n)

 

Δηλαδή x πολλαπλασιασμούς του a με τον εαυτό του. Βέβαια αν λύναμε έτσι αυτές τις εξισώσεις τότε για να υπολογίσουμε μια δύναμη όπως η 95783^78563, θα έπρεπε είτε να επικοινωνούμε με κανά εξωγήινο στην Ανδρομέδα (ή Γυναικομέδα...) είτε να κόβαμε τις φλέβες μας... Ευτυχώς για τους αγαπημένους σας, δεν χρειάζεται να φτάσουμε σε τέτοιο σημείο αφού υπάρχουν κάποιοι αλγόριθμοι που μας γλιτώνουν από την επίπονη διαδικασία...

Πριν συνεχίσουμε στον αλγόριθμο, πρέπει να δούμε κάποιες χονδρικές ενέργειες που μπορούν να μειώσουν τους πολλαπλασιασμούς... Ας υποθέσουμε ότι το x είναι 8, δηλαδή x=8. Τότε η σχέση γίνεται:

 

a^8*mod(n) = (a*a*a*a*a*a*a*a)*mod(n)

 

Ανταυτού μπορούμε να μειώσουμε τους υπολογισμούς σε τρεις, ως εξής:

 

{ [ (a^2*mod(n))^2 *mod(n)]^2 *mod(n)}

 

Πώς έγινε αυτό...; Αν κοιτάξετε την τρίτη ιδιότητα, θα δείτε πως το γινόμενο μπορούμε να το εκφράσουμε με γινόμενο mod, προσπαθήστε το λίγο... Θα δείτε ότι το γινόμενο των δυνάμεων θα μας δώσει το αρχικό που είναι 8... Έτσι βλέπουμε ότι χρησιμοποιώντας μια απλή ιδιότητα αμέσως μειώσαμε τους πολλαπλασιασμούς από 8 σε τρεις, δηλαδή βρήκαμε έναν αλγόριθμο συμπίεσης των πράξεων. Αυτό συμβαίνει με όλες τις δυνάμεις του 2... Ας δούμε όμως τι γίνεται με τις δυνάμεις που δεν είναι δυνάμεις του 2...

Η λύση της εξίσωσης τώρα γίνεται λίγο πιο δύσκολη, γιʼ αυτό χρησιμοποιούμε την δυαδική έκφραση της δύναμης. Δηλαδή εκφράζουμε την δύναμη ως εξής..:

Έστω ότι η δύναμη είναι 25... Στο δυαδικό το 25 γίνεται 11001... Αν θεωρήσουμε ότι από τα δεξιά προς τα αριστερά τα bits αντιστοιχούν σε παράγοντες 2^x, όπου x=0,1,2..n, οι θέσεις δηλαδή των bits, με LSB το 0 και MSB το n, τότε για το 25 (11001), μπορούμε να κάνουμε την αντιστοίχιση του πίνακα που ακολουθεί..:

 

1 -> 1*2^4

1 -> 1*2^3

0 -> 0*2^2

0 -> 0*2^1

1 -> 1*2^0

 

Δηλαδή πολλαπλασιάζουμε το bit με την αύξουσα δύναμη του 2... Προσπαθήστε να διαβάσετε τον πίνακα από πάνω προς τα κάτω, για να πιάσετε το κόλπο... Οπότε τώρα την δύναμη του 25 μπορούμε να την γράψουμε..:

 

25 = 1*2^4 + 1*2^3 + 0*2^2 + 0*2^1 + 1*2^0

 

Το οποίο τελικά μας κάνει:

 

2^4 + 2^3 + 2^0 = 16 + 8 + 1 = 25

 

Άρα ισχύει... :P

Οπότε επειδή x=25, τότε θα έχουμε:

 

a^25*mod(n) = (a^2^4 * a^2^3 * a^2^0)*mod(n) = (a^16 * a^8 * a)*mod(n)

 

Άρα και...:

 

(a*a^8*a^16)mod(n) = [ a* (((a^2)^2)^2) * ((((a^2)^2)^2)^2)]mod(n)

 

Και τελικά:

 

(((((((a*2*mod(n)) * a) *mod(n))^2 *mod(n))^2 *mod(n))^2 *mod(n)) *a) *mod(n)

 

Απλά πράγματα δηλαδή... παιχνιδάκι... Φυσικά κανένας «στόκος» δεν κάνει αυτές τις πράξεις πια στο χέρι...

 

Η τελευταία σχέση λέγεται αλυσίδα και η λύση της από 25 πολλαπλασιασμούς που θα γινόταν υπολογίζοντας την δύναμη απευθείας, μειώνεται στους έξι.... Άρα έχουμε ένα γρήγορο αλγόριθμο υπολογισμού δυνάμεων... :P

Για να το καταφέρουμε αυτό στην C++ χρησιμοποιούμε τον παρακάτω αλγόριθμο..:

 

unsigned long alisida(unsigned long a, unsigned long x, unsigned long n)

{

unsigned long s, t, u;

s=1; t=x; u=y;

while(u)

{

if (u&1) s=(s*t)%n;

u>>=1;

t=(t*t)%n;

}

return (s);

}

 

Ο παραπάνω αλγόριθμος είναι ταχύτατος, αλλά και επίσης δυσνόητος, καθώς χρησιμοποιεί κάποιες ιδιότητες των δυαδικών δυνάμεων, με σκοπό να μειώσει τους πολλαπλασιασμούς στο ελάχιστο... Θα προσπαθήσω να σας εξηγήσω αναλυτικά τον τρόπο λειτουργίας του, πράγμα που το επιχειρώ έτσι ώστε να κατανοηθεί πως δημιουργείται ένας αλγόριθμος και πόσο δύσκολο είναι να καταφέρει κάποιος να δημιουργήσει έναν αξιόπιστο, γρήγορο και ταυτόχρονα απλό τρόπο εφαρμογής του... Μετά από αυτόν θα ακολουθήσει ένας πραγματικά δύσκολος αλγόριθμος, όμως δεν θα μπω στην διαδικασία ανάλυσης του, γιατί θέλει πολύ χώρο, χρόνο και ίσως η εξήγηση που δοθεί, στο τέλος ίσως να μην έχει αποτέλεσμα στο να τον καταλάβει κάποιος...

Την προσέγγιση του αλγορίθμου θα την κάνω και μαθηματικά, αλλά και προγραμματιστικά, γιʼ αυτό χρειάζεται λίγη υπομονή και καθαρό μυαλό... Καπνίστε ένα τσιγάρο δηλαδή και συνεχίζουμε...

 

Στην πρώτη σειρά είναι η δήλωση της συνάρτησης με εξωτερικές μεταβλητές που δέχεται... Τα γνωστά... Οπότε το a είναι η βάση, το x η δύναμη και το n ο παράγοντας της mod(n)... Αυτές οι μεταβλητές να δίδονται από το κυρίως πρόγραμμα το οποίο καλεί την συνάρτηση αυτή... Έπειτα δημιουργούμε άλλες τρεις μεταβλητές οι οποίες είναι και αυτές unsigned long... Επιλέγουμε τέτοιο εύρος μεταβλητών για τον λόγο ότι τα γινόμενα μπορεί να είναι μεγαλύτερα από 2 πόσο μάλλον 1 byte... Η μεταβλητή s θα περιέχει το αποτέλεσμα και τίθεται ίση με ένα λόγω του ότι η αρχική του τιμή δεν μπορεί να είναι μηδέν και ακόμα ο άσσος δεν επηρεάζει τον πρώτο πολλαπλασιασμό μας... Οι μεταβλητές t, u παίρνουν τις τιμές των a, x αντίστοιχα...

Η δήλωση while(u) στην σειρά 6, υποχρεώνει την επανάληψη των περιεχομένων εντολών των αγκυλών ώσπου η δύναμη u μηδενιστεί... Όλο το παιχνίδι γίνεται στις σειρές 8,9 και 10... Ας τις δούμε ξεχωριστά και μετά όλες μαζί...

Στην σειρά 8 υπάρχει η δήλωση ʽif (u&1) s=(s*t)%n;ʼ. Το if βάζει μια προυπόθεση, η οποία απαιτεί η λογική πράξη AND της δύναμης u με τον άσσο (1) να επιστρέφουν μια τιμή διάφορη του μηδενός... Βαθύτερα ακόμα δεν μας νοιάζει αυτό κάθε αυτό το αποτέλεσμα, αλλά αν η δύναμη που εξετάζεται είναι άρτια ή περιττή... Οπότε αν είναι περιττή τότε και μόνο στο αποτέλεσμα, δηλαδή στον s καταχωρείται το υπόλοιπο του γινομένου (s*t) προς το n...

Στην σειρά 9 υπάρχει η εντολή ʽu>>=1;ʼ. Με την εντολή αυτή το δυαδικό περιεχόμενο της μεταβλητής ολισθαίνει προς τα δεξιά μία θέση... Καλό είναι να σκέφτεστε τις μεταβλητές όπως τους καταχωρητές μιας CPU, οπότε η παραπάνω δήλωση είναι σαν την εκτέλεση της assembly εντολής SHR (Shift Logical Right)... Δηλαδή αν πρώτα ήταν 100110101, μετά την εκτέλεση της εντολής γίνεται 010011010...

Στην επόμενη σειρά και συγκεκριμένα στην 10, το μόνο που γίνεται είναι ότι στην μεταβλητή t καταχωρείται το υπόλοιπο του τετραγώνου του εαυτού της με το n... Ο κύκλος επαναλαμβάνεται μέχρι η δύναμη να μηδενιστεί...

 

-Ωραία καλά μας τα πες, αλλά δεν καταλάβαμε μία. Αν αυτό συνέβη, τότε μάλλον πρέπει να διαβάσετε και το μαθηματικό παρασκήνιο της φάσης... Λοιπόν όπως είπαμε μπορούμε να εκφράσουμε μια δύναμη με δυαδικό τρόπο, όπως το 25 σε 11001 που λέγαμε... Όποια δύναμη και να πάρουμε μπορούμε να την εκφράσουμε με αυτόν τον τρόπο... Τώρα υπάρχει μια μπακάλικη διαδικασία της οποίας η απόδειξη δεν μας αφορά, αλλά μπορούμε να υπολογίσουμε το αποτέλεσμα οποιασδήποτε δύναμης με την μέθοδο υπολογισμού και κράτησης... Πάμε λοιπόν?

Ξεχνάμε για την ώρα και για ευκολία τη mod ή τον τελεστή % στο πρόγραμμα... Δηλαδή ας υποθέσουμε ότι το πρόγραμμα γίνεται ως εξής..:

 

unsigned long alisida(unsigned long a, unsigned long x, unsigned long n)

{

unsigned long s, t, u;

s=1; t=x; u=y;

while(u)

{

if (u&1) s=(s*t);

u>>=1;

t=(t*t);

}

return (s);

}

 

Απλά αφαιρέθηκε το (%n)... Τώρα το πρόγραμμα υπολογίζει απλά δυνάμεις... Έστω ότι η δύναμη είναι η 225, άρα s=1, t=2, u=25... Eπειδή είπαμε ότι 25 εστί 11001 στο δυαδικό σύμφωνα με μια μέθοδο που αναφέραμε λίγο πιο πάνω, διαβάζουμε τα bits από το λιγότερο σημαντικό προς το περισσότερο σημαντικό, δηλαδή από τα δεξιά προς τα αριστερά... Ο μπακάλης της γειτονιάς όμως μας λέει ότι όπου βρίσκουμε 1, θα πολλαπλασιάζουμε το μέχρι τότε αποτέλεσμα s με το μέχρι τότε t και το t με τον εαυτό του, όπου βρίσκουμε 0, απλά θα πολλαπλασιάζουμε το t με τον εαυτό του... Σε κάθε περίπτωση η νέα τιμή του t αποθηκεύεται στην θέση της παλιάς... Η εξέταση bit προς bit, είναι η προς τα δεξιά ολίσθηση της δύναμης κατά ένα κάθε φορά...

Το πρώτο bit είναι 1 [1100(1)], οπότε επειδή ο μπακάλης μας το είπε, πολλαπλασιάζουμε το s με το t... Άρα έχουμε s=(s*t)=(1*2)=2 και το t με τον εαυτό του, άρα t=(t*t)=(2*2)=4... Μέχρι στιγμής δυο πολλαπλασιασμοί... Στην συνέχεια κάνουμε μια δεξιά ολίσθηση ή απλά σβήνουμε το bit που εξετάσαμε και η δύναμη γίνεται από 11001 -> 01100... Οπότε τώρα το εξεταζόμενο bit είναι το μηδέν [0110(0)]... Σύμφωνα πάντα με τον μπακάλη απλά πολλαπλασιάζουμε το t με τον εαυτό του, δηλαδή (t*t)=(4*4)=16... Μην λησμονείτε καλοί μου ότι το t έχει αλλάξει σε σχέση με την αρχή... Οπότε μέχρι στιγμής τρεις πολλαπλασιασμοί... Ίδια διαδικασία, επόμενο bit πάλι 0, καθώς 01100 -> 00110 και [0011(0)]... Οπότε έχουμε (t*t)=(16*16)=256... Τέσσερις πολλαπλασιασμοί... Στην συνέχεια είναι 00110 - > 00011 και [0001(1)]... Οπότε λόγο του άσσου έχουμε s=(s*t)=(2*256)=512 και t=(t*t)=(256*256)=65536... Έξι πολλαπλασιασμοί... Το επόμενο και τελευταίο bit είναι πάλι άσσος γιατί 00011 -> 00001 και [0000(1)]... Οπότε έχουμε s=(s*t)= (512*65536)= 33554432, ο τελευταίος πολλαπλασιασμός δεν χρειάζεται...

Ιδού και το αποτέλεσμα μόνο με εφτά πολλαπλασιασμούς... Αλλιώς το 2^25 θα έπρεπε να το υπολογίσουμε πολλαπλασιάζοντας το a στον εαυτό του 25 φορές! Οπότε γλιτώσαμε 18 πολλαπλασιασμούς... Αν ξαναβάλουμε πάλι στην θέση του τον modulus operator %, τότε θα υπολογίζει ακριβώς αυτό του θέλουμε, αφού κάθε φορά θα κάνει και την πράξη mod, άρα θα υπολογίζει τελικά το:

 

a^x*mod(n)

 

Αυτά τα λίγα για να εξηγήσουμε τον αλγόριθμο αυτόν... Όπως καταλαβαίνετε λόγο της επίπονης διαδικασίας θα αποφύγω να εξηγήσω και τον κυρίως αλγόριθμο που χρησιμοποιεί ο RSA για τον υπολογισμό του αντίστροφου modulus για την εύρεση του ιδιωτικού κλειδιού, δηλαδή του..:

 

d = e^-1 *mod[(p-1)*(q-1)]

ή γενικά

 

a = x^-1 *mod(n)

 

Ο παραπάνω τύπος είναι αρκετά δύσκολος να υπολογιστεί, καθώς στην modulus algebra οι αντίστροφοι αριθμοί είναι πραγματικά αγγούρια... Ωστόσο μπορούμε να πούμε ότι με δεδομένο το a το γενικό πρόβλημα είναι να βρούμε ένα x τέτοιο ώστε να ισχύει..:

 

1 = (a*x)*mod(n)

 

Αν μπορείτε να το κάνετε με το μάτι, κανένα πρόβλημα (γίνεται για απλές περιπτώσεις...). Αν από την άλλη όχι πάρτε τον εκτεταμένο Ευκλείδειο αλγόριθμο που ακολουθεί..:

 

#define isEven(x) ((x & 0x01)==0)

#define isOdd(x) (x & 0x01)

#define swap(x,y) (x^=y, y^=x, x^=y)

 

void ExtBinEuclid (int *u, int *v, int *u1, int *u2, int *u3)

{

int k, t1, t2, t3;

 

if (*u < *v) swap(*u,*v);

for (k=0; isEven(*u) && isEven(*v); ++k)

{

*u>>=1; *v>>=1;

}

*u1=1; *u2=0; *u3=*u; t1=*v; t2=*u-1; t3=*v;

do{

do{

if (isEven(*u3))

{

if (isOdd(*u1) || isOdd(*u2))

{

*u1+=*v; *u2+=*u;

}

*u1>>=1; *u2>>=1; *u3>>=1;

}

if (isEven(t3) || *u3<t3)

{

swap(*u1,t1); swap(*u2,t2); swap(*u3,t3);

}

}

while (isEven(*u3));

while (*u1<t1 || *u2<t2)

{

*u1+=*v; *u2+=*u;

}

*u1-=t1; *u2-=t2; *u3-=t3;

}

while (t3>0);

while (*u1>=*v && *u2>=*u)

{

*u1-=*v; *u2-=*u;

}

*u1<<=k; *u2<<=k; *u3<<=k;

}

 

 

 

DWORD ExtEuclideanAlgorithm(int u, int v)

{

int a,b,gcd;

 

ExtBinEuclid(&u, &v, &a, &b, &gcd);

if (gcd==1)

return(u-B);

 

return 0;

}

 

 

Αυτά τα λίγα και εύκολα... Σε γενικές γραμμές ο αλγόριθμος είναι το ίδιο εύκολος με τον προηγούμενο, απλά χρειάζεται λίγη προσοχή στην διαχείριση περιττών και ζυγών... Μπορεί να δυσκολευτείτε λίγο, αλλά καλό είναι όποιος ξέρει λίγο C να τον παλέψει...

 

Εν κατακλείδι?

 

Για τέλος θέλω τονίσω μια πολύ σημαντική πατάτα... Ότι αλγόριθμο και πρωτόκολλο δημιουργήσουμε δεν υπάρχει καμία περίπτωση να είναι εντελώς ασφαλές, είναι ΑΔΥΝΑΤΟ... Αυτό πρέπει να το συνειδητοποιήσουμε καλά πριν ασχοληθούμε σοβαρά με το αντικείμενο... Στόχος μας τελικά, είναι να δυσκολέψουμε όσο περισσότερο γίνεται κάποιον που επιχειρεί να σπάσει τον αλγόριθμο ή το κλειδί μας... Σε αυτό το σημείο στηρίζεται όλη η έρευνα και θα συνεχίσει να στηρίζεται, εξάλλου η τεχνογνωσία σε ολόκληρο τον κόσμο είναι κοινή, το μόνο που κάνει την διαφορά είναι τα άτομα που βρίσκονται πίσω απʼ αυτήν και τελικά την χρησιμοποιούν... Η χρήση τελικά της κρυπτογραφίας, σηκώνει πολύ κουβέντα για το πώς, γιατί και με ποιο σκοπό γίνεται... Εμάς αυτό που μας ενδιαφέρει είναι να διασφαλίζουμε την ακεραιότητα και ασφάλεια των προσωπικών μας δεδομένων, η οποία στην εποχή που διανύουμε έχει καταστεί έρμαιο των διαφόρων υπηρεσιών στο όνομα της παγκοσμιοποίησης και της δημοκρατίας, αν είναι ποτέ δυνατόν... Τον π*ύλο...

 

Ελπίζω να μην ξενερώσατε θανάσιμα... :cry:

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 εβδομάδες αργότερα...
  • Απαντ. 125
  • Δημ.
  • Τελ. απάντηση

Καταρχήν, ευχαριστώ όλους για την θετική απόκριση που είχατε, και επειδή αποδειχτήκατε περισσότερο μαζόχες από εμένα αφού διαβάζετε τις ασυναρτησίες που γράφω, παραθέτω καινούργιο τερατούργημα... ;) Αν και το παρών κείμενο θα έπρεπε να έλθει πρώτο σε σειρά από το προηγούμενο, ωστόσο προτίμησα να κάνω το αντίθετο καθότι το επίπεδο γενικά του forum είναι ανεβασμένο... Ωστόσο, σίγουρα υπάρχουν και κάποιοι παρανοϊκοί οι οποίοι διάβασαν το πρώτο και γούσταραν... Λυπάμαι αλλά για εσάς δεν υπάρχει θεραπεία και η επιστροφή αδύνατη... Αυτό που έλειπε από το πρώτο μέρος είναι μια πραγματική εισαγωγή στην κρυπτογραφία και μια προσέγγιση της από την ηλίθια πλευρά της... Ηλίθια, γιατί πραγματικά είναι πολύ απλή, έξυπνη όμως και διαχρονική γιατί επιβίωσε από την αρχαιότητα μέχρι σήμερα... Όποτε, μπορούμε να πούμε ότι παίρνουμε κάποια πράγματα από την αρχή και για όσα ειπώθηκαν στο προηγούμενο μέρος το παίζουμε «πάπιες»...

Άρα, τι είναι κρυπτογραφία...; Εάν ρωτήσεις διάφορους ανθρώπους μπορεί να πάρεις διάφορες απαντήσεις... Έτσι για έναν φιλόλογο είναι «μια σύνθετη λέξη αποτελούμενη από δυο συστατικές με ρίζα το κρύπτο- και κατάληξη ?γραφία»... Για έναν αστυνομικό είναι ύποπτη, για έναν άσχετο μπορεί να είναι κανένα περίεργο εξωτικό φαγητό, ενώ για μια κυβέρνηση ή πολυεθνική ένας μπελάς... Τελικά μπορούμε απλά να πούμε ότι δεν είναι τίποτα από όλες αυτές τις ανοησίες που μου έρχονται, αλλά μια μορφή επικοινωνίας...

ΝΑΙ?! Η κρυπτογραφία είναι επικοινωνία, για τον λόγο ότι, για να υφίσταται χρειάζεται να υπάρχει ένας πομπός και τουλάχιστον ένας δέκτης... Χωρίς τον δέκτη φυσικά δεν μπορεί να υπάρξει επικοινωνία, εκτός και αν την βρίσκει κανείς να μιλά μόνος του στον τοίχο... Ο λόγος τώρα της ύπαρξης της κρυπτογραφίας είναι να κάνει το περιεχόμενο ενός μηνύματος γνωστό μόνο σε αυτούς για τους οποίους απευθύνεται και σε κανέναν άλλον... Αυτό μπορεί να γίνει εφικτό εάν καταφέρουμε να κωδικοποιήσουμε το περιεχόμενό του... Τι πάει να πει να «κωδικοποιήσουμε», θα αναρωτηθεί κανείς... Βασικά για να μην μπερδευτούμε με έννοιες θεωρούμε ότι κωδικοποίηση και κρυπτογράφηση είναι έννοιες όμοιες, αν και στην πραγματικότητα αυτό δεν ισχύει... Είναι κάτι σαν τον κουραμπιέ και το μελομακάρονο, και τα δυο είναι χριστουγεννιάτικα γλυκά, αλλά έχουν διαφορετική γεύση... Εγώ, πάντως προτιμώ τους κουραμπιέδες...

Οπότε, κωδικοποίηση (ή κρυπτογράφηση, δεν κάνουμε διάκριση από εδώ και πέρα) είναι η διαδικασία κατά την οποία αλλάζουμε την μορφή ή το νόημα ενός κατανοητού μηνύματος από όλους, σε ένα μήνυμα κατανοητό μόνο σε αυτόν που ξέρει πως έγινε η αλλαγή... Ένα απλό παράδειγμα είναι π.χ. τα χρώματα των αντιστάσεων στα ηλεκτρικά κυκλώματα που κάθε χρώμα αντιστοιχεί σε έναν αριθμό και ο συνδυασμός των χρωμάτων σε μια τιμή αντίστασης... Παραδείγματα κρυπτογράφησης στην καθημερινή ζωή είναι πολλά και συχνά την χρησιμοποιούμε χωρίς να το σκεφτόμαστε... Όπως παράδειγμα όταν θέλαμε να βρίσουμε έναν καθηγητή μας στο σχολείο, ποτέ δεν τον βρίζαμε με το όνομα του, αλλά είχαμε συνεννοηθεί όλοι οι μαθητές να τον βρίζουμε με ένα παρατσούκλι... Και αυτό είναι ένα είδος κρυπτογράφησης, καθώς κρύβουμε το νόημα από τους πολλούς και το φανερώνουμε σε αυτούς που ξέρουν ότι το παρατσούκλι απευθύνεται στον καθηγητή...

Αντίστοιχα με την κωδικοποίηση όμως, υπάρχει και η αποκωδικοποίηση... Αποκωδικοποίηση είναι να καταλάβει ο καθηγητής ότι βρίζουμε αυτόν... Οπότε και οι συνέπειες θα είναι ανάλογες... Όπως καταλαβαίνουμε η αποκωδικοποίηση έχει να κάνει με το σπάσιμο της κωδικοποίησης και την αποκατάσταση του αρχικού μηνύματος... Ένας από τους πιο εξελισσόμενους και αναπτυσσόμενους τομείς, είναι ο τομέας του σπασίματος κωδικοποιημένων μηνυμάτων και υπολογίζεται ότι κάθε χρόνο μεγάλο μέρος του εθνικού προϋπολογισμού ισχυρών κρατών δαπανάται για τον εξοπλισμό και επάνδρωση τέτοιων υπηρεσιών... Οπότε αν ψάχνει κανείς για επαγγελματική αποκατάσταση καλύτερα να συνεχίσει να διαβάζει και παρακάτω...

 

Ωραία όλα αυτά, αλλά ας περάσουμε σε λίγο πιο εξειδικευμένα πραγματάκια... Αρχικά πρέπει να πούμε ότι όλα αυτά που συζητάμε βράζουν όλα σε ένα καζάνι που λέγεται κρυπτολογία... Η κρυπτολογία έχει όπως φαίνεται από τα παραπάνω δυο όψεις, μία είναι η κρυπτογράφηση και η άλλη είναι η αποκρυπτογράφηση (ή κωδικοποίηση και αποκωδικοποίηση). Αυτός που κάνει την κρυπτογράφηση λέγεται κρυπτογράφος και αντίθετα αυτός που την σπάει λέγεται κρυπταναλυτής (τα τσογλάνια της υπόθεσης)... Αντίστοιχα τα ίδια κόλπα ισχύουν και για το μήνυμα, και στην αγγλική ορολογία το αρχικό μήνυμα λέγεται plaintext (plat), ενώ όταν το κωδικοποιήσουμε λέγεται ciphertext (cipt)... Γενικά λόγο συντομίας καλύτερα να χρησιμοποιούμε αυτές τις αντιπαθητικές αγγλικές έννοιες...

Γενικά θα ασχοληθούμε περισσότερο με την κρυπτογράφηση παρά με την αποκρυπτογράφηση, καθώς για την δεύτερη απαιτούνται ιδιαίτερες γνώσεις μαθηματικών και στοχαστικών ανελίξεων για να περιγραφεί σωστά... Ωστόσο εάν ζητηθεί μπορεί να γίνει εν καιρώ... Η κρυπτογραφία δεν έχει κανόνες για την υλοποίηση της, αλλά έχει όμως σίγουρα πολλά παραδείγματα προς αποφυγήν, τα οποία πρέπει να εκμεταλλευόμαστε και να αποφεύγουμε... Για μια ομαλή προσέγγιση ωστόσο θα μιλήσουμε για δυο είδη τα οποία τα συναντάμε ακόμα και τα οποία είναι ίδια από την αρχαιότητα... Αυτά είναι ?στροφή? και η ?μετάθεση?...

 

Στροφή ή Ολίσθηση.

 

Για όσους έχουν αντέξει μέχρι αυτό σημείο πρέπει να πούμε ότι η κωδικοποίηση στροφής βασίζεται σε ένα πολύ απλό κανόνα... Παίρνουμε τους χαρακτήρες με αλφαβητική σειρά σε μια ευθεία και στο μυαλό μας σκεφτόμαστε ότι παίρνουμε τα δυο άκρα της ευθείας και τα λυγίζουμε κυκλικά έτσι ώστε να τα ενώσουμε μεταξύ τους... Έτσι μπορούμε να πούμε ότι έχουμε φτιάξει έναν δακτύλιο ο οποίος έχει όλους τους χαρακτήρες σε αλφαβητική διάταξη και το τέλος βρίσκει ξανά την αρχή, οπότε υπάρχει μια συνέχεια... Αυτό το κάνουμε μόνο για να καταλάβουμε το νόημα της συνέχειας των γραμμάτων... Ωραία και τώρα τι...; Ας υποθέσουμε ότι τον γνωστό καθηγητή για τον οποίο λέγαμε και παραπάνω τον λένε Γ. ΠΡΙΧΤΗΣ, εάν θέλουμε να κωδικοποιήσουμε το επίθετό του μπορούμε να κάνουμε το εξής...

Ας θεωρήσουμε ότι το πρώτο γράμμα του δακτυλίου είναι το Α, τότε εάν η αύξουσα ροπή του δίσκου είναι η δεξιά, τότε το 2 είναι το Β, το 3 το Γ κ.ο.κ. Οπότε προκύπτει ο παρακάτω πίνακας..:

 

 

 

1=Α, 2=Β, 3=Γ, 4=Δ, 5=Ε, 6=Ζ, 7=Η, 8=Θ, 9=Ι, 10=Κ, 11=Λ, 12=Μ, 13=Ν, 14=Ξ, 15=Ο

16=Π, 17=Ρ, 18=Σ, 19=Τ, 20=Υ, 21=Φ, 22=Χ, 23=Ψ, 24=Ω.

 

Έτσι το Π είναι το 16, το Ρ το 17, το Ι το 9, το Ξ το 14, το Α το 1 και το Σ το 18. Οπότε αν βάλουμε σε ένα πίνακα τους αριθμούς των γραμμάτων, το ΠΡΙΧΤΗΣ θα είναι..:

 

16, 17, 9, 14, 1, 18

 

Αν τώρα αλλάξουμε την παραπάνω υπόθεση και πούμε ότι αντί να θεωρήσουμε ότι το πρώτο γράμμα είναι το Α, θεωρούμε ότι είναι το Κ, τότε είναι σα να έχουμε στρέψει την αρχή του δακτυλίου κατά 9 θέσεις... Την ενέργεια αυτή συμβολικά την γράφουμε mod(x) ή mod(9) (θυμάστε έτσι...;), που σημαίνει περιστροφή κατά 9 θέσεις και είναι ένας απλός συμμετρικός αλγόριθμος... Οπότε mod(x) σημαίνει περιστροφή κατά x θέσεις... Όπως πρέπει να γίνει αντιληπτό η μέγιστη στροφή είναι η mod(23) (δηλαδή το Ω), καθώς μετά από αυτήν όλα επαναλαμβάνονται από την αρχή... Δηλαδή, για mod(0) = mod(24) = mod(n*24) και n: ακέραιο είναι αρχή το Α, δηλαδή το κανονικό αλφάβητο... Αν μπερδευτήκατε, δεν πρέπει να συγχέεται τον αριθμό των περιστροφών με τον αριθμό των γραμμάτων... Δηλαδή, με μηδέν περιστροφές το Α είναι ίσο με 1, ενώ με 9 περιστροφές το Κ είναι ίσο με 1 (ας ήταν Κ=10) και το Α γίνεται

(24-9)mod(23) = (15)mod(23) = 15... Άρα το Α είναι στην δέκατη-πέμπτη θέση για την οποία ο αριθμός που αντιστοιχεί είναι n+1 = 16, οπότε Α = 16... Αν κάποιοι αναρωτιούνται τι παίχτηκε ποιο πάνω και χάθηκαν, ορκίζομαι ότι δεν έκανα ΚΑΜΙΆ μ*λακία, έτσι βγαίνει... Δοκιμάστε να το κάνετε σε ένα χαρτί και θα το δείτε... Συνεχίζουμε...

Επειδή όπως είπαμε θα θεωρήσουμε για αρχή το Κ, δηλαδή mod(9), μπορούμε να ξαναγράψουμε για ευκολία την καινούργια μορφή του πίνακα:

 

1=Κ, 2=Λ, 3=Μ, 4=Ν, 5=Ξ, 6=Ο, 7=Π, 8=Ρ, 9=Σ, 10=Τ, 11=Υ, 12=Φ, 13=Χ, 14=Ψ, 15=Ω

16=Α, 17=Β, 18=Γ, 19=Δ, 20=Ε, 21=Ζ, 22=Η, 23=Θ, 24=Ι.

 

Οπότε σύμφωνα με το πίνακα του ονόματος και αν αντικαταστήσουμε τους αριθμούς με τα καινούργια γράμματα που προέκυψαν, τελικά ο καθηγητής ΠΡΙΧΤΗΣ θα λέγεται ΑΒΣΨΚΓ, τέλος πάντων θα μπορούσε να είχε προκύψει ένα πιο αναγνώσιμό όνομα, αλλά σημασία έχει αν πέσει στα χέρια του χαρτί με τις βρισιές και το σκίτσο με το γουρούνι που το λένε ΑΒΣΨΚΓ, δεν θα καταλάβει ότι είναι για αυτόν... Βέβαια όλα αυτά δεν γίνονται για να βρείτε κάποιον τρόπο να βρίζεται τον καθηγητή σας, αλλά ούτε επειδή έχω ένα παιδικό τραύμα με τον δικό μου... Σκοπός είναι η κατανόηση της διαδικασία, έτσι ώστε να μπορούμε να την εφαρμόσουμε για άλλα πιο σοβαρά πράγματα και την επαφή μας με το ζωικό βασίλειο μέσω της κρυπτογραφίας...

Η κωδικοποίηση έχει νόημα όταν πρόκειται για ασφάλεια κάποιον σημαντικών εγγράφων είτε αυτά είναι για τα σχέδια μιας εταιρίας, είτε ένα e-mail που δεν θέλουμε εκτός από αυτόν που το στέλνουμε να το διαβάσουν και άλλες 10 υπηρεσίες μυστικές και φανερές... Γιατί όσο δεν παρακολουθούνται τα μηνύματα σε ένα δίκτυο και ιδιαίτερα στο internet , άλλο τόσο δεν θα σε τιμωρήσει ο καθηγητής όταν μάθει ότι ο ΑΒΣΨΚΓ είναι αυτός..! Αν από την άλλη κάποιον δεν τον ενδιαφέρει αν παρακολουθούν τα μηνύματα του, τότε μπορεί να ζήσει άνετα και κάνα τρίμηνο στο σπίτι του Big Brothel? εεε συγνώμη Big Brother ήθελα να πω... Η ασφάλεια των προσωπικών δεδομένων είναι δικαίωμα του καθενός και μπορούμε να το υπερασπιζόμαστε, η κρυπτογραφία είναι ένας τρόπος...

Α... άσχετο... αλλά για μορφωτικούς λόγους να αναφέρουμε ότι στην αρχαιότητα, ο Καίσαρας τα μηνύματα που είχαν σοβαρό περιεχόμενο π.χ. στρατηγικές για μάχες, ραντεβού για ξέσκισμα με την Κλεοπάτρα και δέκα αυλικούς κ.λ.π., χρησιμοποιούσε τον παραπάνω τρόπο κρυπτογράφησης, έτσι ώστε στην περίπτωση που ο αγγελιοφόρος πάθαινε κανένα «ατυχηματάκι» στον δρόμο (ενέδρα, θάνατο από διάρροια κ.ά) , ο εχθρός να μην μπορούσε να διαβάσει το περιεχόμενο... Αν βέβαια ζούσε και το έκανε αυτό σήμερα, το πιο πιθανό είναι ότι κανείς δεν θα είχε ακούσει ποτέ για κάποιον Καίσαρα που κέρδιζε μάχες και τέτοια, γιατί για έναν κρυπταναλυτή τώρα το σπάσιμο ενός τέτοιου κώδικά είναι μισό τσιγάρο υπόθεση, στην χειρότερη περίπτωση, άρα θα τα ήξερε όλα...

Θυμίζω ότι σκοπός της λογοδιάρροιας μου δεν είναι να κάνει κάποιον που διαβάζει αυτά κορυφαίο κρυπτογράφο, απλά είναι μια εισαγωγή σε βασικές έννοιες και αρχές της εφαρμοσμένης κρυπτογραφίας... Στο κάτω ? κάτω είπαμε ότι ο βασικός στόχος του κρυπτογράφου είναι και να αποφεύγει τα λάθη των άλλων, έτσι εάν θέλουμε να κάνουμε ένα cipt (τι..; δεν θυμάστε τι σημαίνει..; -Κωδικοποιημένο κείμενο...), το οποίο δύσκολα να μπορεί να σπάσει, τότε σίγουρα δεν χρησιμοποιούμε τον παραπάνω τρόπο, αλλά έναν ασύμμετρο αλγόριθμο όπως ο RSA που λέγαμε...

Ας δούμε όμως λίγο πιο βαθιά τι μπορούμε να επιτύχουμε με τα παραπάνω... Δεν είναι αναγκαίο ότι όλο το κείμενο το κωδικοποιούμε με τον ίδιο αλγόριθμο, αυτό εξαρτάται από εμάς και μπορούμε πολύ εύκολα να αυτοσχεδιάσουμε... Έτσι αν το κείμενο έχει πολλές σειρές μπορούμε να κωδικοποιούμε κάθε σειρά με διαφορετικό αλγόριθμο, π.χ. την πρώτη σειρά με mod(7), την δεύτερη με mod(21), την τρίτη με mod(Μήτσος) κ.λ.π. Έτσι με ένα απλό αλγόριθμο επιτυγχάνουμε μια πιο σύνθετη κωδικοποίηση, που είναι και πιο δύσκολο να σπάσει...

Επίσης μπορούμε να το κάνουμε ακόμα πιο πολύπλοκο, δηλαδή αν το κείμενο έχει πολλές σειρές και σε κάθε σειρά συγκεκριμένο αριθμό χαρακτήρων, τότε μπορούμε τους μονούς χαρακτήρες (1, 3, 5, 7?, ν+1, ν: άρτιος), της πρώτης σειράς να τους κωδικοποιούμε με έναν αλγόριθμο, τους ζυγούς (2, 4, 6?,ν) με έναν άλλο και σε κάθε σειρά μετά να αλλάζουμε και πάλι τους αλγόριθμους... Σαφώς οι συνδυασμοί είναι άπειροι και μοναδικό όριο είναι η φαντασία του κρυπτογράφου...

Η φαντασία έχει πολύ μεγάλο ρόλο στην κρυπτογράφηση και μάλιστα υπερέχει της τεχνικής κατάρτισης και των μαθηματικών, χωρίς όμως να μπορεί να καταφέρει και πολλά χωρίς αυτά... Επομένως πίσω από όλα αυτά υπάρχει μεγάλο μαθηματικό και θεωρητικό υπόβαθρο, το οποίο είναι απαραίτητο για την δημιουργία αλγόριθμων κωδικοποίησης, τέτοιων ώστε να μην μπορούν να αποκρυπτογραφηθούν σε χρόνο μισού τσιγάρου (από ένα πακέτο και πάνω αρχίζει ο κώδικάς να είναι καλός, και στην περίπτωση που ο κρυπταναλυτής πεθάνει από καρκίνο στους πνεύμονες στην προσπάθεια του να σπάσει τον κωδικό, τότε σημαίνει ότι ήταν πολύ καλός!)...

Στην δημιουργία ενός κώδικα κρυπτογραφίας πρέπει να λάβουμε πολλές παραμέτρους υπόψη, όπως η σοβαρότητα του εγγράφου, ο χρόνος που πρέπει να καταφέρει να μείνει κωδικοποιημένο, το μέσο που διαδίδεται, το άτομο στο οποίο προορίζεται, η γλώσσα στην οποία είναι γραμμένο, ο χώρος που γίνεται η δοσοληψία, το μέγεθος του, αν θα ακολουθήσει επικοινωνία ή είναι το μοναδικό, πόσα λιπαρά έχει το ζαμπόν και άλλα πολλά... Οπότε βλέπουμε ότι στην πραγματικότητα αυτά που πρέπει να πληροί ένας κώδικάς είναι πολλά και μην ξεχνάμε ότι πολλοί κώδικες τα πληρούσαν και τελικά έσπασαν, γιʼ αυτό είπαμε ότι μαθαίνουμε από τα λάθη των άλλων... Παρόλα αυτά δεν απογοητευόμαστε και συνεχίζουμε παρακάτω...

 

Μετάθεση.

 

Στην μετάθεση όπως μπορεί να καταλάβει κανείς έχουμε πάλι το γνωστό αλφάβητο και θέλουμε και πάλι να βρίσουμε τον γνωστό καθηγητή χωρίς να το καταλάβει... Αντίθετα με πριν αυτό που κάνουμε τώρα είναι να αντιστοιχίσουμε ένα γράμμα του αλφαβήτου με ένα άλλο τυχαίο ή συγκεκριμένο χωρίς κατά λάθος να αντιστοιχίσουμε δυο διαφορετικά γράμματα με το ίδιο... Οπότε τώρα φτιάχνουμε έναν πίνακα που στην πάνω σειρά θα έχει το αλφάβητο και κάτω από κάθε γράμμα αυτό το οποίο του έχουμε αντιστοιχίσει... Άρα προκύπτει..:

 

Α=Ξ, Β=Ε, Γ=Β, Δ=Ζ, Ε=Χ, Ζ=Δ, Η=Ν, Θ=Τ, Ι=Π, Κ=Ψ, Λ=Ρ, Μ=Γ, Ν=Ω, Ξ=Θ,

Ο=Η, Π=Σ, Ρ=Α, Σ=Ι, Τ=Υ, Υ=Μ, Φ=Κ, Χ=Ο, Ψ=Φ, Ω=Λ.

 

Οπότε αυτό που έχουμε καταφέρει τώρα είναι να έχουμε αντιστοιχίσει τα γράμματα του αλφαβήτου με κάποια άλλα σχεδόν τυχαία (το σχεδόν θα το αναλύσουμε αργότερα)... Έτσι τώρα ο κύριος ΠΡΙΧΤΗΣ σύμφωνα με τον πίνακα θα λέγεται ΣΑΠΟΥΝΙ... Οπότε τι και αν βρει ο καθηγητής ένα χαρτάκι να γυρνά στην τάξη και να γράφει «Το ΣΑΠΟΥΝΙ σήμερα είναι γλοιώδες, όλο μας κολλάει, άσε που βρομάει...» και τέτοια, το πολύ ? πολύ να πει «παιδιά μου, μην ανησυχείτε θα το πω στην καθαρίστρια να το αλλάξει...» και έτσι όλα μέλι γάλα?. Αν βέβαια πει «Χμμ... Αυτό είναι κρυπτογράφηση μετάθεσης και σύμφωνα με την εμπειρία μου ΣΑΠΟΥΝΙ σημαίνει....», τότε καλό είναι να μάθετε και την μέθοδο της γρήγορης διαφυγής, καθώς ο καθηγητής είναι προφανές τι κάνει στον ελεύθερο χρόνο του στο σπίτι... Διαβάζει insomnia...!

Είναι προφανές ότι ο κώδικας αυτός είναι πιο δύσκολο να σπάσει μιας και δεν έχει τον χαρακτήρα συνέχειας, όπως η κωδικοποίηση στροφής, αλλά είναι ασυνεχείς και τυχαίος... Αυτό βέβαια δεν τον κάνει πιο ασφαλή, αφού μπορεί να σπαστεί με την χρήση απλών μαθηματικών και πιθανοτήτων... Πως γίνεται αυτό..; Κάθε γλώσσα έχει για κάθε γράμμα της αλφαβήτου μια πιθανότητα εμφάνισης του χαρακτήρα σε ένα κείμενο, με άλλα λόγια σε ένα κείμενο κάθε γράμμα έχει ένα ποσοστό επί της % εμφάνισης... Για να καταλάβουμε πως γίνεται αυτό, ας υποθέσουμε ότι παίρνουμε αυτό άρθρο και μετράμε όλους τους χαρακτήρες μέχρι αυτήν την τελεία < . > Είναι 14908 μαζί με τους χαρακτήρες κενού, αν δεν το πιστεύετε μετρήστε τους... Εγώ πάντως το έκανα και ελπίζω να μην ξέχασα κανέναν... Τι..; Τους μετράει και το word..; A... καλά...

Λοιπόν από αυτούς τους χαρακτήρες εάν εξαιρέσουμε τους αριθμούς, τότε μένουν τα γράμματα, οπότε αν μετρήσουμε πόσες φορές εμφανίζεται το κάθε γράμμα τότε βγάζουμε ένα ποσοστό... Π.χ. αν ο χαρακτήρας «α», εμφανίζεται 450 φορές στο κείμενο, τότε η πιθανότητα εμφάνισης του χαρακτήρα «α» θα είναι ίση με:

 

P(α) = n(α) / Ν = 450 / 14908 = 0.0301851

 

Όπου,

n(a) = Αριθμός εμφάνισης του χαρακτήρα «α»

Ν= Συνολικό άθροισμα χαρακτήρων.

Ρ(α)= Πιθανότητα εμφάνισης του «α»

 

Εάν θέλουμε να δούμε την παραπάνω πιθανότητα, στατιστικά σε ποσοστιαίες μονάδες τότε ο παραπάνω τύπος γίνεται:

 

Q(α) = n(α)/N * 100% = 3,01851 %

 

Αυτός ο τύπος τώρα μας δίνει το ποσοστό % εμφάνισης του χαρακτήρα «α»... Αν κάνουμε τα παραπάνω για όλα τα γράμματα θα βρούμε συνολικά 24 ποσοστά των οποίων το άθροισμα θα είναι 100 ή 24 ποσότητες πιθανότητας με άθροισμα 1... Έτσι έχουμε χαρτογραφήσει κατά κάποιο τρόπο το κείμενο... Παράλληλα όμως, κάποιοι κύριοι φρόντισαν πριν από εμάς να το κάνουν αυτό πιο εντατικά και με περισσότερο αξιόπιστα αποτελέσματα, έτσι υπάρχουν για κάθε γλώσσα κάποιοι πίνακες που έχουν όλα αυτά τα ποσοστά... Για παράδειγμα το Α έχει την μεγαλύτερη πιθανότητα εμφάνισης...

Τι χρησιμεύουν όλα αυτά..; Απλά συγκρίνουμε τα ποσοστά αυτά που βρήκαμε με αυτούς τους πίνακες και υποθέτουμε ότι τα ποσοστά που συγγενεύουν αναφέρονται στον ίδιο χαρακτήρα... Εάν για παράδειγμα, για τα ελληνικά το μεγαλύτερο ποσοστό εμφάνισης το έχει ο χαρακτήρας «α» με 3% και εμείς έχουμε βρει 3,01851%, τότε είναι φυσικό να υποθέσουμε ότι είναι αυτός... Αναφερόμενοι τώρα στο παράδειγμα, εάν έχουμε ένα κείμενο κωδικοποιημένο με την αντιστοίχηση που προηγήθηκε, τότε το πιθανότερο είναι να βρούμε ότι το ποσοστό επανάληψης του χαρακτήρα «Ξ» θα είναι ίσο με του πραγματικού «Α», του «Ε» με του πραγματικού «Β» κ.ο.κ... Άρα, σπάσαμε την κρυπτογράφηση...

Σχεδόν, όλοι οι κώδικές αυτού του τύπου μπορούν να σπάσουν με αυτόν τον τρόπο με επιτυχία... Μπορούμε βέβαια να δυσκολέψουμε τα πράγματα για έναν κρυπταναλυτή, εάν χρησιμοποιούμε μηνύματα με λίγες λέξεις, αλλά κατάλληλα επιλεγμένες ώστε το ποσοστό επανάληψης των χαρακτήρων να μην είναι το αναμενόμενο... Δράση ? αντίδραση...

Το πιο γνωστό παράδειγμα κωδικοποίησης μετάθεσης είναι η πασίγνωστη γραφομηχανή Enigma, η οποία κατασκευάστηκε και χρησιμοποιήθηκε από τους γερμαναράδες κατά την διάρκεια του δευτέρου παγκοσμίου πολέμου... Αυτή η γραφομηχανή αποτελούταν από πέντε μοτέρ και η λειτουργία τους ήταν η εξής..: Κάθε πλήκτρο ήταν συνδεμένο με το πρώτο μοτέρ περιστροφής και ανάλογα με το πιο πλήκτρο πατιόταν αυτό περιστρεφόταν ανάλογα και τύπωνε τον χαρακτήρα. Π.χ. το Α ήταν μια στροφή, το Β δυο κ.λ.π. Όμως ο πρώτος κινητήρας δεν συνδεόταν απευθείας με το σύστημα τύπωσης του χαρακτήρα, αλλά πέρναγε μέσω δυο ακόμα μοτέρ που άλλαζαν ανάλογα με την συνδεσμολογία των καλωδίων τις τελικές στροφές του... Έτσι το Α μπορεί να τελικά να αντιστοιχούσε σε ένα οποιοδήποτε άλλο γράμμα τυχαίο... Το ίδιο συνέβαινε και με τα υπόλοιπα πλήκτρα...

Για να διαβάσει τώρα κάποιος το κείμενο έπρεπε να κάνει ακριβώς την αντίστροφη συνδεσμολογία και να πληκτρολογεί το κωδικοποιημένο κείμενο, έτσι στην έξοδο έβλεπε τυπωμένο το πραγματικό... Για την ιστορία αναφέρουμε ότι τελικά οι Βρετανοί κατάφεραν να αποσπάσουν μια Enigma και τελικά να την «σπάσουν» και λέγεται ότι ήταν και από τους βασικούς λόγους που χάθηκε ο πόλεμος από τους Γερμανούς... Η αλήθεια είναι ο Βʼ.Π.Π. είναι και ο πρώτος πόλεμος των τηλεπικοινωνιών, αφού η κωδικοποίηση και η κατασκευή φίλτρων πήγαν σύννεφο... Δηλαδή, με άλλα λόγια μας λένε ότι τσάμπα σκοτώθηκε τόσος κοσμάκης για να παίζουν αυτοί με τις τεχνολογικές παπ*ριές της εποχής τους... Κάτι δεν σας θυμίζει..;

 

 

Παράδειγμα για C++.

 

Τι θα λέγατε αν όλα αυτά τα κάναμε και λίγο πραγματικότητα..; Αυτό που χρειαζόμαστε είναι πολύ υπομονή, δόσεις καφεΐνης, και μπόλικη δόση φαντασίας... Α και ένα compiler για C++, που στην συγκεκριμένη περίπτωση ο κώδικας που ακολουθεί έχει δοκιμαστεί στο Visual Studio 6... Ας τα πάρουμε όμως από την αρχή...

Η C++ είναι πολύ δυνατό εργαλείο και είναι ότι πρέπει για την δημιουργία από απλών μέχρι πολύ σύνθετων προγραμμάτων κωδικοποίησης... Θα αρκεστούμε σε ένα απλό... Βεβαίως οι τρόποι που μπορούμε να το κάνουμε αυτό είναι πολλοί, αλλά θα προσπαθήσουμε μια απλή προσέγγιση στροφής, χωρίς αντικειμενοστρέφειες και διάφορα άλλα... Σκοπός είναι να δοθεί μια ιδέα και στόχος να συνεχίσει κανείς μόνος του στη γραφή πιο σύνθετων και αποτελεσματικότερων προγραμμάτων... Αν κάποιος δεν έχει ιδέα τι είναι η C/C++ υπάρχουν αρκετοί οδηγοί και tutorials στο internet για αρχάριους και μη... Αλλά συνεχίσουμε με προϋπόθεση ότι υπάρχουν κάποιες βασικές γνώσεις...

 

Αρχικά όμως, ΞΕΚΑΘΑΡΙΖΩ, ότι δεν είμαι προγραμματιστής αλλά ηλεκτρονικός, οπότε ο κώδικας μου δεν είναι τέλειος ή πρωτοποριακός, αλλά ότι μου βγαίνει από τα αυτοδίδακτα βράδια που πέρασα αγκαλιά με τον υπολογιστή μου και τον οδηγό για C/C++... Οπότε μπορείτε να με διορθώσετε με επιείκεια...

Η ιδέα του προγράμματος είναι να ανοίγει ένα αρχείο txt, να διαβάζει το περιεχόμενο και στην συνέχεια αφού του δώσουμε τον αλγόριθμο mod(x), να το κωδικοποιεί... Ομοίως ύστερα μπορούμε να κάνουμε την αποκωδικοποίηση αφού δώσουμε πάλι τον ΙΔΙΟ αλγόριθμο με τον οποίο κωδικοποιήσαμε το αρχείο... Για να μειωθεί ο όγκος του προγράμματος προτίμησα να μην χρησιμοποιήσω πολλά flags με αποτέλεσμα να υπάρχουν κάποια μικρά bugs τα οποία είναι ασήμαντα...

Για ευκολία σε αυτόν που το χρησιμοποιεί, για να πάρει μια γεύση από κωδικοποίηση, προτίμησα να κωδικοποιεί μόνο τους κεφαλαίους και τους πεζούς χαρακτήρες και να μην επηρεάζει τους χαρακτήρες κενού και τα σημεία στίξης... Σαν άσκηση κάποιος όμως μπορεί να το δοκιμάσει και αυτό...

Η λειτουργία του είναι απλή... Καταρχήν αφού τρέξουμε το πρόγραμμα, πρέπει να επιλέξουμε εάν θέλουμε να κρυπτογραφήσουμε ή να αποκρυπτογραφήσουμε ένα txt αρχείο... Αφού επιλέξουμε, τότε πρέπει να δώσουμε το πλήρες όνομα του αρχείου μαζί με την κατάληξη... Αν θέλουμε να το κωδικοποιήσουμε ΠΡΕΠΕΙ να προϋπάρχει στον ίδιο φάκελο με το πρόγραμμα, και πρέπει να είναι μόνο με αγγλικούς χαρακτήρες, για λόγους που δεν υπάρχει τώρα λόγος να αναλύσουμε... Π.χ. μπορεί να είναι ένα αρχείο του wordpad, οπότε για να το ανοίξουμε γράφουμε <name>.txt... Αφού τα κάνουμε αυτά το επόμενο βήμα είναι να διαλέξουμε τον αλγόριθμο κωδικοποίησης mod(x), η επιλογή είναι φυσικά από 1-25 (αγγλικοί χαρακτήρες) και ο λόγος αναφέρεται στο παράρτημα της κωδικοποίησης στροφής... Αμέσως μετά το πρόγραμμα κωδικοποιεί το κείμενο και το γράφει σε ένα καινούργιο txt αρχείο προσθέτοντας στην αρχή του ονόματός του το πρόθεμα ʽFixed-ʽ. Αν προσπαθήσετε να το διαβάσετε προφανώς δεν θα μπορέσετε... Για ευκολία έχουν προστεθεί στην επικεφαλίδα του αρχείου πληροφορίες για την κρυπτογράφηση, έτσι ώστε αν το αρχείο ξεχαστεί μετά από καιρό να θυμάστε τον αλγόριθμο κωδικοποίησης... Βέβαια, αυτό θα ήταν βλακεία να γίνει σε μια κανονική εφαρμογή με αυτόν τον τρόπο, γιατί θα μας έπαιρναν πρέφα και οι αχιβάδες...

Η αποκρυπτογράφηση έχει ακριβώς τα ίδια βήματα με την διαφορά, ότι τώρα δίδουμε το όνομα του αρχείου που είναι κρυπτογραφημένο... Από τις πληροφορίες που υπάρχουν στην επικεφαλίδα του δίνουμε τον αλγόριθμο αποκωδικοποίησης και? ταρατατζούμ... Βέβαια αν δοκιμάσετε να αποκωδικοποιήσετε ένα οποιοδήποτε αρχείο, τότε το πρόγραμμα θα κολλήσει γιατί δεν θα βρίσκει την επικεφαλίδα που δημιουργεί το πρόγραμμα κατά την κωδικοποίηση.

«Μα τι λέει ο καλλιτέχνης...; Που είναι ο κώδικάς...;»... Θα είπατε... Ορίστε, ακολουθεί παρακάτω...

 

/**********************************************************************************

* *

* Encrypt Tool *

*-------------------------------------------------------------------------------------------------------------------------*

* *

* By ]@co *

* *

* Αυτό το πρόγραμμα είναι φτιαγμένο για την κρυπτογράφηση και αποκρυπτογράφηση *

* αρχείων με κείμενο, με σκοπό την κατανόηση της εφαρμογής του προγραμματισμού *

* σε αυτήν. Για πλάκα μπορείτε να το χρησιμοποιήσετε για την κρυπτογράφηση των *

* e-mail που ανταλλάσσεται με ένα φίλο, χρησιμοποιώντας το ίδιο πρόγραμμα. *

* Βέβαια δεν είναι τίποτα το ιδιαίτερο γι' αυτό, αν θέλει κάποιος μπορεί να το *

* επεκτείνει και να το τροποποιήσει έτσι ώστε να κάνει μια πιο σύνθετη κωδικοποί- *

* ηση. Απλά χρειάζεται λίγη όρεξη και δουλειά. *

* *

* Το πρόγραμμα είναι ένα εκτελέσιμο αρχείο win32 και έχει γραφεί στη Visual *

* C++ v.6. Μπορείτε βέβαια με οποιονδήποτε compiler για C++, που έχει τα αρχεία *

* includes, να το κάνετε compile. *

* *

***********************************************************************************/

 

/****************************

Δήλωση μεταβλητών και headers

****************************/

 

//Headers

 

#include "iostream.h"

#include "fstream.h"

#include "string.h"

 

//Δήλωση Συναρτήσεων

 

int DecryptFile();

int EncryptFile();

int Menu();

 

//Δήλωση Global μεταβλητών

 

int counter=0; //Μετρητής

char file[20], decFile[20]; //Για την ονομασία των αρχείων

unsigned char ch; //Για ASCII μεγαλύτερους από 127

int x,selection;

 

 

 

int main()

{

for( ;; )

{

int selection=Menu(); //Καλεί την συνάρτηση Menu

switch (selection)

{

case 1:

EncryptFile(); //Αν η Menu(), επιστρέφει 1, καλεί την EncryptFile()

break;

case 2:

DecryptFile(); //Αν η Menu(), επιστρέφει 2, καλεί την DecryptFile()

break;

case 3:

return 0; //Αν η Menu(), επιστρέφει 3, βγαίνει

}

}

return 0;

}

 

 

/********************************

Συνάρτηση Εμφάνισης αρχικού μενού

********************************/

 

int Menu()

{

int selection;

cout <<"En/Decrypt Tool v.1 by: ]@co\n";

cout <<"------------------------------------------------------------------------------\n\n\n\n";

 

cout <<"This is an enc/decryption, tool using rotation encoding by Jaco for ";

cout <<"exercise purposes only. Just make a choise bellow and follow the orders.";

cout <<"The executable file must be in the same folder with the document you ";

cout <<"want to encrypt. Me alla logia balte to *.txt sto idio fakelo!";

cout <<"\n\n\tChoose:";

cout <<"\n\t\t(1): To Encrypt A Document \n\t\t(2): To Dencrypt A Document";

cout <<"\n\t\t(3): Quit\n\n\t\t=>";

cin >>selection;

 

return selection; //Επιστρέφει την επιλογή

}

 

 

/******************************

Συνάρτηση Κωδικοποίησης αρχείων

******************************/

 

int EncryptFile()

{

 

cout <<"\nType the name of the file you want to encrypt with the extension. (i.e. Doc.txt)\nEntry: ";

cin >>file;

 

ifstream doc; //Δημιουργεί ένα αντικείμενο αρχείου για διάβασμα

doc.open(file,ios::nocreate|ios::binary); //Ανοίγει το αρχείο

 

if (!doc) //Ελέγχει αν υπάρχει το αρχείο

{

 

cout <<"\n\n\\n\n\t\t\tFile not found!\n\n\n\n";

return 0;

}

 

 

 

cout <<"Select algorithm mod(x), (1-25)= "; //Επιλογή Αλγόριθμού

cin >>x;

 

while (x<1 || x>25) //Έλεγχος για σφάλμα

{

cout <<"\nx must be 1-25: ";

cin >>x;

}

 

strcpy(decFile, "Fixed-"); //Δημιουργία του ονόματος του αρχείου

strcat(decFile, file);

 

ofstream decrdoc; //Δημιουργεί ένα αντικείμενο αρχείου για γράψιμο

decrdoc.open(decFile); //Άνοιγμα αρχείου

 

 

//Πρόσθεση επικεφαλίδας στο κωδικοποιημένο αρχείο

 

decrdoc <<"********************************************************\n";

decrdoc <<"* This file has been encrypted with mod(" <<x <<") *\n";

decrdoc <<"* with *\n";

decrdoc <<"* Encrypt Tool v.1 by ]@co *\n";

decrdoc <<"********************************************************\n";

 

 

while (doc.get(ch)) //Διαβάζει το προτότυπο αρχείο

{

if (ch>=0x41 && ch<=0x5a) //Ελέγχει τους κεφαλαίους χαρακτήρες

{

ch=ch+x;

if (ch>0x5a)

ch=ch-0x5b+0x41;

}

 

if (ch>=0x61 && ch<=0x7a) //Ελέγχει τους πεζούς χαρακτήρες

{

ch=ch+x;

 

if (ch>=0x7b)

{

ch=0x61-0x7b+ch;

}

}

decrdoc <<ch;

}

 

decrdoc.close(); //Αφού τελείωσει η διαδικασία κλείνει το αρχείο

doc.close();

 

return 0;

}

 

 

 

/*********************************

Συνάρτηση Αποκωδικοποίησης αρχείων

*********************************/

 

int DecryptFile()

{

cout <<"\nType the name of the file you want to decrypt with the extension. (i.e. Doc.txt)\nEntry: ";

cin >>file;

 

ifstream doc;

doc.open(file,ios::nocreate|ios::binary);

 

if (!doc)

{

 

cout <<"\n\n\\n\n\t\t\tFile not found!\n\n\n\n";

return 0;

}

 

 

 

cout <<"Select algorithm mod(x), that the file has been encrypted, (1-25)= ";

cin >>x;

 

while (x<1 || x>25)

{

cout <<"\nx must be 1-25: ";

cin >>x;

}

 

strcpy(decFile, "Fixed-");

strcat(decFile, file);

 

ofstream decrdoc;

decrdoc.open(decFile);

 

x=26-x; //Αντιστρέφει τον αλγόριθμο ώστε να αποκωδικοποιήσει το αρχείο

 

decrdoc <<"****This file has been decrypted with mod(" <<26-x <<")****.\n";

 

counter = 0;

while (doc.get(ch))

{

if (ch=='*') //Έλεγχος επικεφαλίδας αρχείου και σβήσιμο

{ //της αν υπάρχει, από το αρχείο στόχο.

counter++; //Σε περίπτωση που αυτή δεν υπάρχει το

} //αρχείο δεν είναι έγκυρο και δεν τρέχει.

 

if (counter>=118)

{

if (ch>=0x41 && ch<=0x5a)

{

ch=ch+x;

if (ch>0x5a)

ch=ch-0x5b+0x41;

}

 

if (ch>=0x61 && ch<=0x7a)

{

ch=ch+x;

 

if (ch>=0x7b)

{

ch=0x61-0x7b+ch;

}

}

decrdoc <<ch;

}

}

 

 

decrdoc.close();

doc.close();

 

return 0;

}

 

Μπορεί ίσως να τρομάζει στην όψη αλλά είναι πολύ εύκολο και απλό να το καταλάβει κανείς... Αν βαριέστε να το γράψετε, κλασσικά copy-paste στον compiler... Αν για κάποιο λόγο δεν λειτουργήσει πυροβολήστε τον πιανίστα ποτέ όμως τον μπασίστα...

Εμένα πάντως μου δουλεύει κανονικά... Για παράδειγμα ετοιμάζω ένα αρχείο test.txt στον ίδιο φάκελο με το .exe αρχείο και γράφω...:

JACO MAS ESPASES TA @RXIDIA?

 

Μετά, τρέχω το πρόγραμμα και πατάω (1) και Enter για να κάνω κρυπτογράφηση, μετά το όνομα του αρχικού αρχείου «test.txt» και Enter και ύστερα επιλέγω για mod(x) το x = 13 και Enter... Έτσι μου φτιάχνει ένα καινούργιο αρχείο με την ονομασία ?fixed-test.txt?, το οποίο και όταν ανοίγω το περιεχόμενο του είναι το παρακάτω..:

 

********************************************************

* This file has been encrypted with mod(13) *

* with *

* Encrypt Tool v.1 by ]@co *

********************************************************

WNPB ZNF RFCNFRF GN @EKVQVN...

 

Είπαμε, ότι κρυπτογραφεί μόνο αλφαβητικούς χαρακτήρες και όχι σύμβολα, αριθμούς ή σημεία στίξης... Αυτό μπορείτε να το κάνετε μόνοι σας... Στην συνέχεια για να το αποκρυπτογραφήσουμε γυρνάμε πάλι στο πρόγραμμα και πατάμε (2) για αποκρυπτογράφηση, το όνομα του αρχείου ?fixed-test.txt? και τον αλγόριθμο mod(x) που λέει το κρυπτογραφημένο κείμενο, δηλαδή 13 και παίρνουμε το καινούργιο μήνυμα ?fixed-fixed-test.txt? (έρε Jaco bug-ιες που κάνεις, ούτε ο μπακάλης τέτοιες μπακαλιές?)? Το οποίο και περιέχει τα εξής..:

 

****This file has been decrypted with mod(13)****.

*

JACO MAS ESPASES TA @RXIDIA...

 

Χε, χε πλάκα δεν έχει..; Μόλις φτιάξατε το πρώτο δικό σας πρόγραμμα κρυπτογράφησης και από κρυπτογράφησης... Επομένως, συνεχίζουμε με την κατασκευή ενός πυραύλου... Πριν ξεκινήσουμε όμως να πούμε ότι το πρόγραμμα μπορούμε να το κάνουμε όπως θέλουμε, δηλαδή να κρυπτογραφεί αριθμούς, σημεία στίξης, χαρακτήρες Unicode, να κάνει περισσότερους κύκλους κρυπτογράφησης αυξάνοντας τον βαθμό της κρυπτογράφησης, να ψήνει καφέ κ.τ.λ... Ένα update για να ψήνει έναν ελληνικό με ολίγην θα ποστάρω σύντομα... Βασικά, οι δυνατότητες είναι απεριόριστες γιατί ο καθένας μπορεί να κάνει ότι θέλει... Είχα δοκιμάσει με ένα παλικάρι το οποίο μου έστελνε e-mail κρυπτογραφημένα με αυτόν τον τρόπο, δηλαδή μετάθεση και στροφή και σπάζανε για πλάκα με απλές πιθανότητες, οπότε επαναλαμβάνω δεν θεωρείται ασφαλή μέθοδο... Πιο ασφαλές είναι να κυκλοφορείς στο Σύνταγμα το βράδυ ένα μάτσο ευρώ να ξεχειλίζουν από όλες τις τσέπες και μια δίμετρη ξανθιά που να κρατάει μια πινακίδα που να λέει «πλακώστε τον και πάρτε με?».

 

Τελειώνοντας, θα μπορούσε κάποιος ή κάποιοι υπερ-μαζόχες να συντονιστούμε ώστε να φτιάξουμε ένα υποτυπώδες εργαλείο κρυπτογράφησης το οποίο να μοιραστούμε μεταξύ μας... Ένα πρόγραμμα παρτούζα κατά κάποιο τρόπο... Εγώ προσωπικά δεν έχω τον ατελείωτο ελεύθερο χρόνο (δεν πιάνει το trainer +1/time μου), αλλά δεν χαλιέμαι να δώσω κάποιες λιγοστές γνώσεις στο θέμα που έχω σε κάποιον που έχει πολύ περισσότερες γνώσεις πάνω στον καθαρό προγραμματισμό, ώστε να γίνει η δουλειά... Περιμένω ιδέες... Καλώ και τους φίλους Java-τζήδες, παρόλο που αρνήθηκαν το όνομα που τους είχα προτείνει... ;) Καλύτερα πρόγραμμα κρυπτογράφησης σε java παρά σε «ελεγχόμενη» C++ μου φαίνεται, ε..;

 

 

]@co.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 1 χρόνο αργότερα...

Να προτείνω κάτι που ίσως να με κάνει να φανώ άσχετος; Τι θα έλεγες να προσθέσεις και κωδικοποιήση για όλα τα στοιχεία του Ascii και μετά κρυπτογράφηση με Xnor βασισμένο σε κλειδί διαβασμένο από το χρήστη;

 

:)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

sugoruyo, αυτό που λες μπορεί να γίνει όπως και πολλά άλλα... δηλαδή να βρεις δικούς σου αλγόριθμους ακόμα και να κάνεις επικάλυψη αλγορίθμων ή και κρυπτογράφηση στον ίδιο τον αλγόριθμο κρυπτογράφησης, κρυπτόγραφηση junk και ένα σωρό άλλα... κοινώς σταματάει εκεί που σταματά η φαντασία...

απλά αυτό είναι μια εισαγωγή και τίποτα παραπάνω...

μπορείς να βρεις πολλές πληροφορίες στο internet κάνοντας search για symetric και asymetric algorithms, kryptography, encryption, decryption, steganography και άλλα που προκύπτουν ψάχνοντας αυτά...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Συγχαρητήρια για την δουλεία που έχεις κάνει!Είναι φοβερή. Είχα διαβάσει και το πρώτο μέρος και περίμενα πως & πως μήπως βγάλεις και άλλο. Και τελικά να το.Τώρα περιμένουμε το τρίτο!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ευχαριστώ τους mod για το sticky...

 

Γι' αυτό και εγώ έχω σχεδόν έτοιμο και το τρίτο μέρος (90+%)... πολύ πιο ενδιαφέρων από τα άλλα δυο μέρη, το κρατάω έκπληξη για το περιεχόμενο αλλά θα συνδυάζει ένα είδος κρυπτολογίας με δεδομένα τα οποία χρησιμοποιούμε συχνά στο pc... Το διάλεξα επειδή δεν έχει σχεδόν καθόλου μαθηματικά και θα δώσω τον πλήρη κώδικα σε Standard C++...

Υπομονή, γιατί κάνω debug στον κώδικα και παίρνει γενικά περισσότερο χρόνο να εξηγώ την φιλοσοφία και την ροή του παρά όλα τα υπόλοιπα...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Γεια σας και πάλι... καιρός ήταν να φτάσω και στο τρίτο μέρος αφού τα άλλα δυο είχαν τρομερή απήχηση στο ευρύτερο κοινό και δεν θα μπορούσα να κάνω και αλλιώς ύστερα από τα χιλιάδες e-mail που μου στέλνατε για αυτή την συνέχεια... και ύστερα ξύπνησα...

Τελικά αποφάσισα το τρίτο μέρος να μην έχει να κάνει καθαυτό με την κρυπτογράφηση, γιατί ξαναδιαβάζοντας τα προηγούμενα άρθρα είδα ότι έχει γίνει ήδη αναφορά στους συμμετρικούς αλλά και στους ασύμμετρους αλγόριθμους κρυπτογράφησης... Οπότε δεν νομίζω ότι υπάρχει λόγος να το αναλύσω σε περισσότερο βάθος, τουλάχιστον για την ώρα, γιατί θα μπλέξουμε σε μαθηματικά περίεργα και αρκετά δυσνόητα έτσι ώστε να καταφέρω απλά να σας πονοκεφαλιάσω και να μην διαβάσετε ούτε τα μισά... Αντίθετα σκέφτηκα ότι είναι καλύτερα να κάνουμε κάτι σαν παιχνίδι με πράγματα τα οποία όλοι έχουμε έρθει πάνω-κάτω σε επαφή και δεν ξέρουμε πως μπορούμε να τα εκμεταλλευτούμε...

 

ΣΤΕΓΑΝΟΓΡΑΦΙΑ

-------------------------

 

Το καινούργιο μας παιχνίδι λοιπόν λέγεται στεγανογραφία και θα δείξω πως είναι πολύ απλό να γίνει, αλλά και ότι μπορούμε να το εκμεταλλευτούμε έτσι ώστε να το χρησιμοποιήσουμε σαν ένα μέσο κρυπτογράφησης. Για την ιστορία στεγανογραφία σημαίνει να κρύβεις κάτι μέσα σε κάτι στην μορφή του δεύτερου κάτι έτσι ώστε να σημαίνει κάτι σαν το δεύτερο κάτι αλλά να κρύβει μέσα του το πρώτο κάτι...! Σας μπέρδεψε κάτι...? Αυτός ήταν ο σκοπός... χε, χε... Με πιο απλά λόγια σημαίνει πως μπορεί κανείς να κρύψει τον ελέφαντα πίσω από την παπαρούνα... Για παράδειγμα στεγανογραφία είναι να κρύψεις ένα κείμενο μέσα σε ένα άλλο με τέτοιο προκαθορισμένο τρόπο ώστε ενώ κάποιος διαβάζει το κείμενο να βγάζει ένα νόημα, αλλά κάποιος άλλος που ξέρει πως μπορεί να το αποκρυπτογραφήσει να βρίσκει το κρυφό κείμενο ή νόημα μέσα στο κείμενο...

Π.χ.

 

-- Κυκλοφόρησαν τα νέα τεύχη περιοδικών ΒΑΒΕΛ του Ιουνίου. Στα περίπτερα μπορείτε σήμερα πρωί να πάρετε. --

 

Τι νόημα βγάζετε απʼαυτό...? Τίποτα...? Αν σας έδινα ή ξέρατε και αυτό το στοιχείο...?

 

-- 821123271633123 --

 

ή

 

-- 8, 2, 1, 1, 2, 3, 2, 7, 1, 6, 3, 3, 1, 2, 3 --

 

Τώρα...?

 

Για όσους δεν το κατάλαβαν οι αριθμοί είναι το γράμμα της κάθε λέξης που έχει σημασία... Δηλαδή παίρνοντας την αριθμοσειρά και βάζαμε σε παρένθεση το γράμμα που δείχνει ο κέθε αριθμός θα προέκυπτε το εξής...

 

-- Κυκλοφό(ρ)ησαν τ(α) (ν)έα (τ)εύχη π(ε)ριοδικών ΒΑ(Β)ΕΛ τ(ο)υ Ιουνίο(υ). (Σ)τα περίπ(τ)ερα μπ(ο)ρείτε σή(μ)ερα (π)ρωί ν(α) πά(ρ)ετε. --

 

Ή αν μαζέψουμε αυτά τα γράμματα στην σειρά βγάζουν το εξής νόημα...

 

-- Ραντεβού στο Μπαρ --

 

Καλό...?

Εάν θέλατε θα μπορούσατε στο ίδιο μήνυμα αν το συνεχίζατε να παραγγέλνατε και μια μπύρα με το ίδιο τρόπο...

Το παράδειγμα ήταν του λεπτού, οπότε μπορείτε με περισσότερη προσπάθεια να βγάλετε ένα κείμενο με καλύτερο νόημα το οποίο να κρύβει πάλι το ίδιο νόημα... στο συγκεκριμένο παράδειγμα από το νόημα που βγάζει κάποιος που δεν ξέρει τι γίνεται, μάλλον υποθέτει πως αυτός που το έγραψε έχει ήδη πιει την μπύρα στο μπαρ...

 

Στην στεγανογραφία δεν είναι απαραίτητο να βγαίνουν κάποια γράμματα από το κείμενο ή να υπάρχουν κάποιοι αριθμοί κτλ... μπορεί να έχει υπάρχει ένα προκαθορισμένο συνθηματικό μοντέλο το οποίο να λειτουργεί στο υπόβαθρο, έτσι ώστε να είναι ένα απλό κείμενο που απλά συνθηματικά να υποδηλώνει κάτι άλλο... Για παράδειγμα λέγοντας

-- Τον προηγούμενο μήνα οι επιστήμονες ανακάλυψαν από πού κλάνει το μπαρμπούνι και θα ακολουθήσει περαιτέρω έρευνα με την υποστήριξη της Ευρωπαϊκής ένωσης και του συλλόγου “Λευτεριά στο μπαρμπούνι” της κοινότητας Άνω, Κάτω και Πέρα Μπαρμουνοχωρίου... --

 

να εννοεί κάποιος

-- φέρε μου και ένα πακέτο τσιγάρα καθώς έρχεσαι στο ραντεβού στο προκαθορισμένο μπαρ... --

 

Ή άλλο παράδειγμα

 

-- Ζητείται 30άχρονη, για συντροφιά κλπ περιοχή Καλλιθέας, τηλ 693x240221 --

 

Το οποίο θα μπορούσε να σημαίνει ότι στις 24/02 στις 21:30 έχουμε ραντεβού στο γνωστό μέρος της Καλλιθέας...

 

Είναι όλα θέμα του αλγορίθμου που χρησιμοποιούμε και θέμα φαντασίας μέχρι το που μπορεί να φτάσει μια τέτοιου είδους επικοινωνία με στεγανογραφία...

 

Ωραία όλα αυτά, νόστιμο και υγιεινό το μπαρμπούνι, αλλά πως μπορούμε να τα χρησιμοποιήσουμε εμείς οι pc-άδες σε συνδυασμό με προγραμματισμό και κυρίως για ποιο λόγο...

Τον λόγο θα το αφήσω σε εσάς καθώς ο καθένας μπορεί να το χρησιμοποιήσει για όποιο λόγο θέλει, αλλά σαν βάση το χρησιμοποιούμε να κρύψουμε κάτι από κάποιους...

Τώρα το πώς έχει πρακτικό ενδιαφέρων... Ξέρουμε όλοι τι είναι το wav και το bmp...? Είναι και τα δυο πρωτόκολλα δεδομένων, το ένα για ήχο και το άλλο για εικόνα... είναι κοινώς δεδομένα (data) τοποθετημένα σε σειρά με τέτοιο τρόπο έτσι ώστε να περιέχουν μια πληροφορία που να αναγνωρίζεται από όλες τις εφαρμογές που τα υποστηρίζουν...

Πως θα σας φαινόταν λοιπόν αν μπορούσατε να κρύψετε μια εικόνα bmp σε ένα αρχείο ήχου wav ή ένα κείμενο μέσα σε ένα αρχείο ήχου ή εικόνας... Ακολουθώντας κάποιους τυπικούς κανόνες που συμφωνούν με τα παραπάνω πρωτόκολλα είναι δυνατόν και εύκολο...

Στο παρόν άρθρο θα ασχοληθούμε με το πώς να κρύψουμε ένα κείμενο μέσα σε ένα wav αρχείο και πως μπορούμε να το ανακτήσουμε πάλι για να πάρουμε την πληροφορία...

Για να γίνει αυτό πρέπει καταρχήν να δούμε και να αναλύσουμε το πρωτόκολλο WAVE PCM FORMAT (WAV), πάμε λοιπόν...?

 

 

WAVE PCM FORMAT (WAV)

----------------------------------------

 

Το WAV format είναι ένα πρωτόκολλο αποθήκευσης ήχου... Αυτό το πρωτόκολλο αποτελείται από τρία βασικά μέρη, τα οποία περιέχουν άλλα υπο-μέρη... Το κανονικοποιημένο πρωτόκολλο WAVE φαίνεται παρακάτω μαζί με την θέση των υπο-μερών μέσα στην μνήμη (ή το αρχείο)...:

 

1. RIFF

1.1. ChunkID (00h-03h)

1.2. ChunkSize (04h-07h)

1.3. Format (08h-0Βh)

 

2. FMT

2.1 SubChunk1ID (0Ch-0Fh)

2.2 SubChunk1Size (10h-13h)

2.3 AudioFormat (14h-15h)

2.4 NumChannels (16h-17h)

2.5 SampleRate (18h-1Bh)

2.6 ByteRate (1Ch-1Fh)

2.7 BlockAlign (20h-21h)

2.8 BitsPerSample (22h-23h)

 

3. DATA

3.1 SubChunk2ID (24h-27h)

3.2 SubChunk2Size (28h-2Bh)

3.3 Data (2Ch-τέλος αρχείου)

 

Αυτό που μας ενδιαφέρει κάτω από ορισμένες συνθήκες είναι το (3.3) και οι συνθήκες αυτές είναι στην ουσία η προϋπόθεση ότι δεν θα αλλάξουμε το μέγεθος του αρχείου προσθέτοντας περισσότερα data, αλλά θα αντικαταστήσουμε κάποια από αυτά με κάποια άλλα... Για περισσότερες πληροφορίες όσων αφορά την πλήρη ανάλυση του πρωτοκόλλου μπορείτε να ψάξετε στο internet... Ωστόσο θα πω κάποια βασικά πράγματα για το πρωτόκολλο έτσι ώστε να έχουμε μια ιδέα περί τίνος πρόκειται...

Το πρώτο πράγμα που χρειαζόμαστε είναι ένας HEX-Editor σαν το UltraEdit-32 (UE) το οποίο χρησιμοποιώ για τα παραδείγματα... Ξεκινάμε ανοίγοντας ένα wav αρχείο με το UE, αυτό που μας εμφανίζει είναι το παρακάτω...:

 

00h: 52 49 46 46 FC C6 FD 02 57 41 56 45 66 6D 74 20

10h: 10 00 00 00 01 00 02 00 44 AC 00 00 10 B1 02 00

20h: 04 00 10 00 64 61 74 61 0C E5 E6 02 FF FF 01 00

30h: FF FF 00 00 03 00 05 00 09 00 08 00 09 00 07 00

40h: 09 00 09 00 0D 00 0C 00 0C 00 0C 00 0B 00 0C 00

 

Panic...? Όχι τόσο...

Από 00h-03h είναι το ASCII των χαρακτήρων -RIFF- (52 49 46 46) που απλά υποδηλώνει την έναρξη του header του RIFF Specification Descriptor του αρχείου... μην σας απασχολεί αυτό είναι τυπικό όπως και τα περισσότερα και δεν χρειάζεται να παρέμβουμε σε αυτό...

 

Από 08h-0Bh είναι το ASCII των χαρακτήρων -WAVE- (57 41 56 45) που δηλώνει ότι το format του αρχείου είναι wav... το προσπερνάμε και αυτό σφυρίζοντας αδιάφορα...

 

Από 0Ch-0Fh είναι το ASCII των χαρακτήρων -FMT - (66 6D 74 20) μαζί με τον χαρακτήρα κενού (20h) στο τέλος... Το FMT είναι το header της περιγραφής του αρχείου wav και συγκεκριμένα...:

10h: 10 ; σε ΗΕΧ που στο δεκαδικό είναι το 16 και υποδηλώνει ότι το αρχείο είναι 16-PCM

 

14h: 01 ; σε ΗΕΧ που σημαίνει ότι το αρχείο έχει υποστεί γραμμικό κβαντισμό (linear quantization), με άλλα λόγια είναι ένα ασυμπίεστο wav, ότιδήποτε άλλο σημαίνει ότι το αρχείο έχει υποστεί μια μορφή συμπίεσης...

 

16h: 02 ; σε ΗΕΧ που σημαίνει ότι το αρχείο είναι stereo (01 για mono)...

 

18h-19h: 44 AC ; σε HEX AC44h που στο δεκαδικό είναι 44100 που σημαίνει ότι το sampling rate του αρχείου έγινε στα 44,1KHz...

 

22h: 10 ; σε ΗΕΧ που στο δεκαδικό είναι 16 και υποδηλώνει το Bits Per Sample, δηλαδή την κωδικοποίηση των bits ανά δείγμα...

 

Από 26h-29h είναι το ASCII των χαρακτήρων -data- το οποίο είναι το header που υποδηλώνει μετά από αυτό αρχίζουν τα δεδομένα του ήχου...

 

Όπως παρατηρείτε υπάρχουν κάποιες θέσεις τις οποίες παρέλειψα, αλλά το έκανα επίτηδες γιατί έχουν νόημα μόνο για τον decoder που θα παίξει το αρχείο και αποτελούν μαθηματικές πράξεις για διάφορα μεγέθη του αρχείου...

Οπότε όπως είδαμε δεν ήταν κάτι το τραγικό και γενικά το wav πρωτόκολλο είναι πολύ απλό, γιʼ αυτό και παράγει τόσο μεγάλα αρχεία... Με τον ίδιο τρόπο περίπου αναλύεται και το πρωτόκολλο bmp το οποίο και αυτό περιέχει τα απαραίτητα headers και τα δεδομένα θέσης, χρώματος κλπ...

 

Το wav στο χώρο που αποτελείται από τα data δεν είναι τίποτε άλλο παρά οι πληροφορίες του ήχου για το κάθε κανάλι... Από την θέση 30h και μετά δηλαδή είναι οι πληροφορίες του σήματος για το κάθε κανάλι αν είναι stereo ή μόνο για το ένα κανάλι αν είναι mono... Για να είμαστε πιο συγκεκριμένοι, το κάθε δείγμα (sample) αποτελείται από 4 bytes, από τα οποία τα δυο πρώτα είναι η πληροφορία του αριστερού καναλιού και τα δυο τελευταία του δεξιού. Οπότε κάθε δείγμα έχει πληροφορία 2 bytes ή 16-bit, το οποίο επαληθεύει αυτό που είπαμε και πριν και απορρέει από τη HEX μορφή του wav στην θέση 2Ch, ότι δηλαδή η πληροφορία είναι κωδικοποιημένη με 16-bit/sample...

Επομένως, για το αρχείο το οποίο έχω ανοίξει εγώ μετά την θέση 2Ch τα δεδομένα είναι:

 

2Ch: FF FF 01 00

30h: FF FF 00 00 03 00 05 00 09 00 08 00 09 00 07 00

40h: 09 00 09 00 0D 00 0C 00 0D 00 0D 00 0B 00 0C 00

.

.

2E6E550h: 04 00 04 00 09 00 02 43

 

Βλέπουμε ότι το αρχείο τελειώνει στην θέση 2E6E557h, πράγμα το οποίο φαίνεται και από το πεδίο Subchunk2Size, το οποίο στο δεκαδικό είναι 48.686.423 bytes ή 48ΜΒ περίπου, τα οποία αν το διαιρέσουμε με το δυο μας δίνουν τα δείγματα και για τα δυο κανάλια ή με το τέσσερα για να βρούμε τα συνολικά δείγματα... οπότε 48686423/4=12171605,75 δηλαδή περίπου 12.171.605 (το δεκαδικό βγήκε γιατί έχω υπολογίσει μέσα και τα header τα οποία επειδή είναι πολύ μικρά δεν τα αφαίρεσα)... άρα αφού η δειγματοληψία μου είναι 44.1KHz σημαίνει ότι έχω 44.100 δείγματα ανά δευτερόλεπτο, άρα η διάρκεια του wav αρχείου είναι 12.171.605/44,100= 276 δευτερόλεπτα ή 4,6 λεπτά... Οπότε είδαμε πως μπορούμε να υπολογίσουμε βλέποντας μόνο το HEX κώδικα του αρχείου να βγάλουμε συμπεράσματα για αυτό... Με τον ίδιο τρόπο μπορείτε να υπολογίσετε ποιος είναι ο συνθέτης του κομματιού, ποιος παίζει μπάσο στο κομμάτι, πόσων χρονών είναι ο τραγουδιστής και αν έχει ζάχαρο, όπως επίσης μπορείτε και να υπολογίσετε τι ναρκωτικά έπαιρναν την ώρα που έγραφαν στο studio το κομμάτι και άλλα πολλά...

 

Λοιπόν ξαναγυρνάμε στα data τα οποία έχουν την μορφή που είπαμε παραπάνω, λόγο λογοδιάρροιας που με έπιασε πριν τα ξαναγράφω...:

 

2Ch: FF FF 01 00

30h: FF FF 00 00 03 00 05 00 09 00 08 00 09 00 07 00

40h: 09 00 09 00 0D 00 0C 00 0D 00 0D 00 0B 00 0C 00

.

.

2E6E550h: 04 00 04 00 09 00 02 43

 

Στην πρώτη γραμμή τα τέσσερα bytes είναι πληροφορία του πρώτου δείγματος, τα δύο πρώτα το αριστερό κανάλι (L, Left Channel) και τα άλλα δυο το δεξί κανάλι (R, Right Channel)... Οπότε το L1 είναι FFFFh=65535 που σημαίνει ότι κάνει peak (κάτι σαν το τσικ-τσακ του πικ-απ) και R1 είναι 0000h=0 δηλαδή απόλυτη ησυχία, πράγμα φυσιολογικό αφού μόλις αρχίζει το τραγούδι...

Με τον ίδιο τρόπο προκύπτει:

 

L2 = FFFFh = 65535

R2 = 0000h = 0

L3 = 0030h = 48

R3 = 0005h = 5

bla, bla, bla...

 

Να υπενθυμίσω ότι σε ένα HEX αρχείο τα bytes το διαβάζουμε από αριστερά προς τα δεξιά δηλαδή αν ένας αριθμός αποτελείται από 2 ή τρία bytes και πάνω τα διαβάζουμε ως εξής...:

 

5F 34 03 = 03345Fh = 210.015 (dec)

και όχι

5F 34 03 = 5F3403h = 6.239.235 (dec)

 

Έτσι...? Καμία σχέση δηλαδή, άλλο βούρτσα άλλο π...

 

Για να μιλήσουμε και λίγο για τα δείγματα... Στην ουσία ο αριθμός είτε δεκαεξαδικός είτε δεκαδικός που περιέχει το κάθε δείγμα σε κάθε κανάλι υποδηλώνει την ένταση της καμπύλης εξόδου... Οπότε αν είχαμε ένα κανονικοποιημένο (normalized) wave σήμα τότε στο σημείο που η κυματομορφή έπαιρνε την μέγιστη τιμή της, το δείγμα αυτό θα είχε τιμή FFFFh, ενώ αντίστοιχα η ελάχιστη τιμή θα ήταν 0000h, στην περίπτωση που το wav είναι PCM 16-bit, δηλαδή 16-bit/sample... αν ήταν για παράδειγμα PCM 24-bit θα είχε 24-bit... Συνεπώς, ανάμεσα στις δυο άκρες παίρνουν τιμές τα υπόλοιπα δείγματα... η συχνότητα του διαμορφωμένου προκύπτει από την μεταβολή του πλάτος των διπλανών δειγμάτων στο χρόνο... Ένα παράδειγμα πως μοιάζουν τα σήματα αυτά είναι το παρακάτω

 

-

--

---

-----

-------

--------

-----

---

-

-

---

-----

-------

--

-

---

 

Αν στρέψετε το κεφάλι σας 90 μοίρες δεξιά (μέχρι να ακουστεί ένα κρακ) θα δείτε τι περίπου εννοώ... αυτό θα μπορούσε να είναι τα δείγματα ενός καναλιού, ενός αρχείου wav...

 

 

 

ΠΡΩΤΟΚΟΛΛΟ ΣΤΕΓΑΝΟΓΡΑΦΙΑΣ

 

-------------------------------------------------

 

Πως μπορεί να γίνει τώρα η στεγανογραφία...? Πολύ απλά αλλάζοντας την τιμή συγκεκριμένων δειγμάτων με δικά μας byte... οπότε στην ουσία θα αλλάξουμε την δυναμική ενός δείγματος με ένα χαρακτήρα ASCII...!!! Τι αποτέλεσμα θα έχει αυτό...? Στην ουσία θα αλλάξει η ένταση της κυματομορφής στο σημείο αυτό, αλλά επειδή η δειγματοληψία είναι 44.1ΚΗz, δηλαδή 44.100 δείγματα/δευτερόλεπτο, τότε το αυτί δεν πρόκειται να πάρει χαμπάρι τίποτα, ειδικά όταν μιλάμε για δυναμικές ανάλογες του εύρους των ASCII, δηλαδή από 30h-70h ή στην πραγματικότητα 30h-5Ah, βγάζοντας έξω τα πεζά και αφήνοντας μόνο αριθμούς και κεφαλαία...

Αυτό ισχύει μιλώντας πάντα για ASCII, αν θέλαμε να είμαστε πιο πονηροί θα είχαμε κάνει άλλη σύμβαση και θα είχαμε αντιστοιχήσει άλλα δεκαεξαδικά σε κάθε γράμμα και όχι μόνο αλλά δεν θα είχαμε μόνο ένα byte για κάθε γράμμα αλλά πάνω από 3 με 4, αλλά αυτό απλά το αναφέρω, δεν θα το χρησιμοποιήσουμε λόγο απλότητας...

 

Εδώ πια πρέπει να κάνουμε κάποιες συμβάσεις και να καταλήξουμε σε έναν αλγόριθμο ή πρωτόκολλο στεγανογραφίας το οποίο θα χρησιμοποιήσουμε μέσα στο κώδικά μας... Καταρχάς συμφωνούμε ότι για απλότητα θα χρησιμοποιούμε μόνο ASCII χαρακτήρες χωρίς κρυπτογράφηση (όπως μετάθεση κλπ) ή άλλη κωδικοποίηση... δεν θα προσθέσουμε λόγο απλότητας δείγματα, αλλά θα αλλάξουμε ήδη υπάρχοντα... επίσης θα αλλάζουμε ένα δείγμα χίλια, μία από το δεξί κανάλι και μια από το αριστερό...

Φυσικά, αν θέλει κάποιος μπορεί να περιπλέξει τα πράγματα και χρησιμοποιήσει πρώτα κάποιο συμμετρικό, ασύμμετρο ή υβριδικό αλγόριθμο για να κρυπτογραφήσει πρώτα το κείμενο και μετά να το βάλει μέσα στο wav με τέτοιο τρόπο έτσι ώστε να το περιπλέξει ακόμα περισσότερο π.χ. ανεστραμμένα bit-in-byte, pseudo-random τρόπο τοποθέτησης των bytes μέσα στα data, hush data για λέξεις κλειδιά και άλλα πολλά εκατομμύρια πράγματα που μπορεί να του κατέβει καθενός στο μυαλό... όσο πιο κουφός και απίστευτος γίνεται όχι ο αλγόριθμος, αλλά ο τρόπος του αλγορίθμου τόσο πιο δύσκολο να σπάσει κανείς τον κώδικα και να διαβάσει το κείμενο... υπάρχουν ακόμα και τρόποι για να αποφεύγεται το σπάσιμο με τον στατιστικό αλγόριθμο για κάθε γλώσσα, ό,τι θέλετε τέλος πάντων γίνεται... της Πόπης...

 

 

ΤΙ ΘΥΜΟΜΑΣΤΕ ΑΠΟ C++...???

 

Ξεσκονίζοντας το βιβλίο της C++ σας λοιπόν, περνάμε να τα κάνουμε όλα αυτά ένα προγραμματάκι... απλά πράγματα όμως, για να είμαστε συμβατοί μεταξύ μας στις διάφορες εκδόσεις και να μην έχουμε μακρινάρια κώδικες... οπότε μένουμε στην ουσία του αλγορίθμου και απορρίπτουμε κάθε γραφικό περιβάλλον, όμως αυτό δεν σημαίνει τίποτα, μπορείτε μετά απλά να ενσωματώσετε τον ίδιο κώδικα σε ένα παραθύρι στην Visual C++...

Πως άραγε θα ανοίξουμε το αρχείο...? φυσικά σαν ένα πίνακα, όμως για να έχουμε καλύτερη πρόσβαση σε αυτόν θα είναι με pointer (τα θυμάστε αυτά τα σιχαμένα pointers...?) και στην συνέχεια θα έχουμε πρόσβαση σε κάθε θέση μνήμης μέσω του δείκτη... Μουαχαχαχα...

 

Προειδοποίηση:

Αυτή την προειδοποίηση συνηθίζω να την κάνω σεβόμενος τους προγραμματιστές... Είμαι ηλεκτρονικός μηχανικός και άρα γράφω κώδικα σαν μηχανικός, δεν ευθύνομαι αν βγάλω κανένα μάτι κάποιου που παίζει την C στα δάχτυλα... οπότε δεν δηλώνω προγραμματιστής, αλλά εγγυώμαι ότι αυτό που έχω γράψει δουλεύει χωρίς να πάρει φωτιά ο υπολογιστής σας...!

Αν κάποιος βρει κάποιο τρανταχτό λάθος ας μου το πει και θα έρθω να τον βρω, ε... θα το διορθώσω ήθελα να πω... κάθε PM επί του θέματος και όχι μόνο ευπρόσδεκτο...

 

Υποθέτουμε ότι το αρχείο wav λέγεται -- sound.wav -- και ότι βρίσκεται στον ίδιο φάκελο με το πρόγραμμα μας που θα γράψουμε... στον ίδιο φάκελο υπάρχει ένα txt αρχείο με όνομα -- text.txt -- μέσα στο οποίο υπάρχει το κείμενο που θέλουμε να βάλουμε στο wav με την εξής μορφή, ΜΟΝΟ ΚΕΦΑΛΑΙΑ ΜΕ ΑΓΓΛΙΚΟΥΣ ΧΑΡΑΚΤΗΡΕΣ, επιτρέπονται αριθμοί, σημεία στίξης, τελείες, κόμματα κλπ...

Για wav αρχείο μπορούμε να χρησιμοποιήσουμε οποιοδήποτε ασυμπίεστο stereo (το οποίο και θα το ελέγχουμε αν είναι σωστό μέσω του κώδικα)., αρκεί να το κάνουμε rename σε sound.wav, το txt το δημιουργούμε εμείς και γράφουμε μέσα το κείμενο που θέλουμε...

 

Προειδοποιώ ότι πρέπει το txt αρχείο να περιέχει μόνο λατινικούς χαρακτήρες (καλό να είναι και κεφαλαία), σημεία στίξης και αριθμούς... Από χαρακτήρες κενού να χρησιμοποιείτε μόνο spacebar και όχι enter γιατί θα παραμορφώνεται το κείμενο μετά από την αποκωδικοποίηση...

Ο κώδικας που δίνω εμένα δούλεψε κανονικά... σίγουρα θα υπάρχουν αρκετά bug, αλλά σκοπός μου δεν είναι να φάω χρόνο να κάνω ένα bug-free κώδικα, αλλά να πάρετε μια ιδέα πως δουλεύει το όλο το πράγμα... καλό είναι να μην κάνετε μόνο copy-paste τον κώδικα, αλλά να του ρίξετε και μια ματιά γιατί θα βρείτε πολλά ενδιαφέροντα πράγματα, αλλά και θα δείτε τον τρόπο σκέψης μου...

 

 

 

ΠΑΡΑΤΗΡΗΣΕΙΣ:

 

Αυτό που δίνω είναι μια πολύ απλοποιημένη εκδοχή του τι μπορεί να κάνει κανείς με αυτό το πρόγραμμα ή αυτή την διαδικασία... αν θέλετε μπορείτε να χρησιμοποιήσετε και κρυπτογράφηση στο κείμενο πριν την κωδικοποίηση του μέσα στο wav, με τρόπους που έχουμε αναλύσει στα προηγούμενα άρθρα... Γενικά αυτά που μπορείτε να κάνετε είναι άπειρα αρκεί να κατεβάζετε ιδέες...

 

Παρόλο που μπορεί να καταλήξω σε κανά υπόγειο καμιάς ασφάλειας ή μυστικής υπηρεσίας με αυτά τα προγράμματα που γράφω, θέλω να πω ότι είναι δικαίωμα του καθενός να κρύβει τα δεδομένα του με όποιον τρόπο θέλει και μάλιστα με τρόπους που είναι δύσκολα ανιχνεύσιμοι...

 

Για αυτούς που μπορεί να πάνε βαθύτερα στο πράγμα, θα τους ψήσω λιγάκι λέγοντας τους ότι ο κώδικας και η φιλοσοφία του προγράμματος που δίνω είναι ελλιπής... όχι ως προς την λειτουργία του, αφού κάνει αυτό σας έχω πει, αλλά ως προς τον βαθμό ανάλυσης του και δυσκολίας του... Αν θέλει κανείς να πάει πιο βαθιά, τότε θα πω ότι για να είναι σωστότερος ο αλγόριθμος αυτός τότε θα πρέπει ο κώδικας να μπορεί να αναλύσει το wav αρχείο και μπορεί από μόνος του να κρίνει που θα μπουν τα δεδομένα και όχι σε μια προκαθορισμένη θέση... Αυτό θα πρέπει να γίνει λόγο της παραμόρφωσης του σήματος... Δηλαδή όταν αλλάζουμε την δυναμική στο κομμάτι με ένα ASCII χαρακτήρα θα πρέπει να τον τοποθετούμε εκεί που δεν θα ακουστεί σαν παραμόρφωση και δεν θα επηρεάσει πολύ το FFT του σημείου που βρίσκεται... Με μερικούς μαθηματικούς αλγόριθμους και προσεγγίσεις αυτό μπορεί να γίνει σχετικά εύκολα και να αποφύγουμε να εισάγουμε κβαντικό θόρυβο στο κομμάτι από το κείμενο και τους ASCII χαρακτήρες...

Ένας άλλος τρόπος να κρύψουμε καλύτερα το κείμενο είναι να βρούμε την μέση δυναμική ένταση του κομματιού και να δημιουργήσουμε ένα αλφάβητο με στάθμη κοντά στην μέση δυναμική ένταση... καλά μην βαράτε, θα εξηγήσω τι λέω... Αν πάρουμε όλες τις στάθμες - δείγματα του κομματιού, τα αθροίσουμε και μετά τα διαιρέσουμε με το πλήθος των δειγμάτων, αυτό που θα πάρουμε είναι η μέση στάθμη... αυτή είναι χονδρική και λάθος προσέγγιση όμως γιατί στα άκρα του κομματιού έχουμε το Fade-In και Fade-Out, άρα καλό είναι μην υπολογίσουμε τα δείγματα των πρώτων και των τελευταίων δευτερολέπτων του κομματιού και να βρούμε τη μέση στάθμη από τα μεσαία δείγματα... Υπολογίζοντας τώρα την μέση στάθμη των δυναμικών των δειγμάτων, αυτό που καταφέρνουμε είναι να μειώσουμε τον κβαντικό θόρυβο και να μειώσουμε την ειδική εντροπία του αλγόριθμου κρυπτογράφησης, κοινώς να επιτύχουμε καλύτερο λόγο σήματος - κρυπτογραφικού θορύβου... Η ανάλυση μπορεί να συνεχιστεί και άλλο, αλλά δεν αξίζει... έχω αναφέρει μου φαίνεται κάποια πράγματα για τις εντροπίες των κρυπτογραφικών αλγορίθμων στα προηγούμενα άρθρα... απλά έχουμε υπόψη μας ότι όσο μικρότερη η εντροπία του κρυπτογραφικού αλγορίθμου, τόσο δυσκολότερο είναι να τον σπάσει κανείς...Τέλος πάντων για να δημιουργήσουμε ένα αλφάβητο κοντά στην μέση στάθμη δυναμικών, τότε παίρνουμε την στάθμη αυτή και παραδεχόμαστε ότι το μεσαίο γράμμα της αλφαβήτου μας έχει δεκαεξαδική αναπαράσταση ίση με τον δεκαεξαδικό της στάθμης... στην συνέχεια για τα υπόλοιπα γράμματα μπορούμε να προχωρήσουμε με βήματα των δύο και πάνω από το κέντρο και να κάνουμε αντιστοίχιση... αν τα βήματα δεν είναι στατικά, αλλά δυναμικά τότε μειώνουμε την εντροπία... προσοχή ότι αν το κάνουμε αυτό θα πρέπει να σαρώσουμε μετά το κομμάτι για να αλλάξουμε όλες τις στάθμες που δεν είναι χαρακτήρες σε δεκαεξαδικούς διαφορετικούς από αυτούς που αντιστοιχούν στο αλφάβητο μας... άρα αν έχουμε αρκετό κενό ανάμεσα στα γράμματα του αλφαβήτου, μειώνουμε την παραμόρφωση του σήματος καθώς δεν δημιουργούμε περιοχές απογύμνωσης του σήματος... π.χ.

Αν η μέση στάθμη του κομματιού είναι 0x03d0 τότε στο ελληνικό αλφάβητο αντιστοιχούμε στο 0x03d το γράμμα Μ (Μ=0x03d0)...

Τώρα τι γίνεται όμως... Αν πω ότι (Ν=0x03d1), (Λ=0x03cf), (Ξ=0x03d2), (Κ=0x03ce) κ.ο.κ. τότε θα πρέπει τα δείγματα του κομματιού που δεν είναι χαρακτήρες από το αρχικό κείμενο, να μην έχουν μια από αυτές τις τιμές γιατί τότε στην μετατροπή από το WAV στο txt θα γίνεται της πουτάνας, καθώς μην ξεχνάμε ότι είμαστε στην μέση δυναμική και υπάρχουν πολλές τέτοιες στάθμες, άρα θα έχω ένα κενό από 0x03c4 μέχρι 0x03dc, που σημαίνει ότι θα έχω τρομερή παραμόρφωση, γιατί θα είναι σαν κενό αέρος στα αεροπλάνα...!

Αυτό που πρέπει να γίνει ότι η απόσταση των δεκαεξαδικών τιμών που αντιστοιχίζουμε στα γράμματα του αλφαβήτου να έχουν τέτοια απόσταση έτσι ώστε να μην δημιουργού αυτό το πρόβλημα... Για παράδειγμα αν είναι στατική να είναι ανά 1 ή 3 ή 10 ή ότι ναʼ ναι...

Π.χ. 0x03d0, 0x03d3, 0x03d6 κ.ο.κ. έτσι ώστε όσες τιμές του σήματος έχουν αυτή την δυναμική να μπορούν να κινηθούν σε διπλανές περιοχές...

Αν είναι δυναμική απόσταση μπορεί να είναι του τύπου 3+5*x κ.τ.λ. πράγμα το οποίο δίνει μεγαλύτερο κενό και μειώνει την εντροπία, προσοχή όμως να μην ξεφύγουμε πολύ από το δυναμικό μέσο...

Και έτσι για να σας σπάσω τα νεύρα και να σας μπερδέψω περισσότερο, μπορώ να σας πω ότι για να είναι ακόμα καλύτερος ο αλγόριθμος τότε μπορείτε να υπολογίσετε την γλωσσική εντροπία των ελληνικών και μετά να επιλέξετε πίνακα χαρακτήρων ανάλογα με αυτήν...! Αυτή η εντροπία στην ουσία αναφέρεται σε ένα στατιστικό μέγεθος που έχει να κάνει με την επαναληπτικότητα του κάθε χαρακτήρα του αλφαβήτου... για παράδειγμα στα ελληνικά τα φωνήεντα μας έχουν πολύ μεγαλύτερη επαναληπτικότητα (ειδικά τα α, ε) σε σχέση με άλλες γλώσσες και γενικά κάθε χαρακτήρας έχει ένα δικό του συντελεστή... οπότε μπορούμε ξέροντας αυτό να θωρακίσουμε καλύτερα τον αλγόριθμο δίνοντας τιμές κοντά στο μέση δυναμική σε χαρακτήρες με μεγάλη επαναλητικότητα έτσι ώστε να καμουφλάρονται καλύτερα μέσα στο σήμα και να δημιουργήσουμε μεγαλύτερη απόσταση μεταξύ των χαρακτήρων...

 

Λοιπόν αυτά δεν σας τα πρήξω άλλο... είναι πολλά ακόμα, άλλα σημαντικά, άλλα ασήμαντα... θα ήθελα όμως ένα ολόκληρο βιβλίο να γράψω... Μέχρι στιγμής η βιβλιογραφία σε αυτά τα θέματα δεν είναι και ωκεανός, ούτε βρυσούλα θα έλεγα... αλλά παρόλα αυτά μπορείτε να βρείτε κάποια πράγματα... στο δίκτυο δεν βρήκα κάποια εφαρμογή που να κάνει κάτι παρόμοιο, οπότε μάλλον πρωτοτυπήσαμε πάλι... αν βρει κάτι κάποιος που να κάνει αυτή την δουλειά ή κάποιο source code ας ποστάρει το link για να μην ανακαλύπτουμε όλοι μαζί πάλι τον τροχό...

 

Επιτέλους ακολουθεί ο κώδικάς... το #include <vcl.h> και #pragma hdrstop, με τα οποία ξεκινάει ο δικός μου δεν είναι απαραίτητα, απλά επειδή χρησιμοποίησα τον Borland C++ Builder 6 μου το κότσαρε μόνο του με το έτσι θέλω...

 

Έχω ανεβάσει ΕΔΩ ένα rar αρχείο με τον πηγαίο κώδικα και ένα παράδειγμα με ένα wav και ένα txt αρχείο... απλά παίξτε μαζί τους για να δείτε τι γίνεται και πως...

 

Καλή διασκέδαση...

 

>
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <iostream.h>
#include <fstream.h>"
#include<conio.h>  /*Μόνο για το clrscr(); που καθαρίζει την οθόνη*/

//Δήλωση συναρτήσεων
int menu(void);                 /*Κεντρικό μενού*/
void WavProperties(void);       /*Ανοίγει το wav και βλέπει τα properties του*/
void ReadText(void);            /*Διαβάζει το κείμενο που είναι προς κωδικοποίηση*/
void Text2Wav(void);            /*Μενού για την προετοιμασία της κωδικοποίησης*/
void Encode(unsigned long spacing, int channel);  /*Ότι λέει...*/
void Decode(void); /*Πάλι ότι λέει*/

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
       int selection=0;
       clrscr();
       cout << "TEXT2WAV v.1                       by Jaco\n";
       cout << "------------------------------------------\n\n";
       cout << "This is an application that hiddens a text\n";
       cout << "file into a wav file. My code is free to use.";
       cout << "\nBy Jaco 02/2005\n";
       cout << "\n\nYou must put a WAV called wave.wav file";
       cout << "\nin the same folder with the program. Also";
       cout << "\nyou must create a text.txt file and write";
       cout << "\nthe text you want to encode with CAPITALS.";
       cout << "\nIf all the above are true then make a choise";
       cout << "\nand press ENTER.";
       for(;
       {
               /*Δεν χρειάζονται σχόλια εδώ...*/
               if(selection==0) selection=menu();
               switch(selection)
               {
                       case 1:
                               WavProperties();
                               selection=0;
                               break;
                       case 2:
                               ReadText();
                               selection=0;
                               break;
                       case 3:
                               Text2Wav();
                               selection=0;
                               break;
                       case 4:
                               Decode();
                               selection=0;
                               break;
                       case 5:
                               return 0;
                       selection=0;
               }
       }

       return 0;
}
//---------------------------------------------------------------------------

int menu(void)
{
       int selection;
       cout << "\n\n\t(1) See the WAV file properties";
       cout << "\n\t(2) See the text.txt";
       cout << "\n\t(3) TEXT2WAV!!!";
       cout << "\n\t(4) WAV2TEXT!!!";
       cout << "\n\t(5) Exit...";
       cout << "\n\n\tChoise: ";
       cin >> selection;

       /*Επιλογή μενού*/
       while (selection<1 || selection>5)
       {
               cout << "\n\tChoose (1) to (5)";
               cout << "\n\n\tChoise: ";
               cin >> selection;
       }
       return selection;       /*επιστρέφει την επιλογή*/
}

void WavProperties()
{
       unsigned char ch;
       unsigned char properties[50];
       unsigned long srate;
       unsigned long size;
       unsigned long temp;

       ifstream wave;
       wave.open("wave.wav", ios::in|ios::binary);

       if (!wave)
{

	cout <<"\n\n\\n\n\t\t\tFile not found!\n\n\n\n";
	return;
}
       wave.seekg(0);          /*πηγαίνει τον δείκτη του αρχείου στην αρχή*/

       for (int i=0;i<44;i++)  /*Διαβάζει το header του wave σε ένα πίνακα*/
       {
               properties[i]=wave.get();
       }

       if (properties[8]==0x57 && properties[9]==0x41 && properties[10]==0x56 && properties[11]==0x45)
       {
               clrscr();
               cout << "\nFORMAT\t\t:\tWAVE FILE";

               /*Υπολογισμός της κωδικοποίησης από το Formaτ*/
               if (properties[16]==0x10) cout << "\nEncoding\t:\tPCM";

               /*Υπολογισμός της μορφής του αρχείου από το AudioFormat*/
               if (properties[20]==0x01) cout << "\nAudio Format\t:\tLinear Quantization";
               else cout << "\nAudio Format\t:\tCompressed";

               /*Υπολογισμός του αριθμού καναλιών από το NumChannels*/
               if (properties[22]==0x01) cout << "\nNum of Channels\t:\tMono";
               if (properties[22]==0x02) cout << "\nNum of Channels\t:\tStereo";

               /*Υπολογισμός του ρυθμού δειγματοληψίας από το SampleRate*/
               srate=0; srate=(long) properties[25]; srate=srate<<8; srate+=(long) properties[24];
               cout << "\nSample Rate\t:\t" <<srate;

               /*Υπολογισμός της κωδικοποίησης της δειγματοληψίας από το BitsPerSample*/
               temp=(long) properties[34];
               cout << "\nBits Per Sample\t:\t" << temp;

               /*Υπολογισμός μεγέθους αρχείου από το Subchunk2Size*/
               size=(long) properties[43]; size=size<<8;
               size+=(long) properties[42]; size=size<<8;
               size+=(long) properties[41]; size=size<<8;
               size+=(long) properties[40];
               cout <<"\nSize\t\t:\t" << size/1000000 << " MB";

               /*Υπολογισμός διάρκειας του αρχείου wav*/
               cout <<"\nPlaytime\t:\t" << size/4/srate/60 << ":" << size/4/srate-size/4/srate/60*60  <<" sec";

               /*Όπως αναφέρω και στο θεωρητικό τα λεπτά διαρκείας του κομματιού είναι
               (size/4/srate/60) το οποίο όμως επειδή είναι (long) δεν δίνει ακρίβεια
               δεκαδικού, αρά αρκεί να πολ/σουμε το αποτέλεσμα (size/4/srate/60) με το 60
               για να μας δώσει τα συνολικά δευτερόλεπτα και να βρούμε το σφάλμα αφαιρώντας
               από το πραγματικό... Δηλ. (size/4/srate)-(size/4/srate/60*60)=σφάλμα δευτερολέπτων
               άρα τα δευτερόλεπτα που προσθέτουμε στα λεπτά για να είμαστε ακριβείς...
               Βοήθειά σας... */

       }
       else cout << "\n\nThis File is not WAV file!";  //Αν συμβεί αυτό τότε κάποιος ξέχασες να βάλεις το αρχείο στον φάκελο
       wave.close();          /*Γειά σου αρχειάκι...*/
}

void ReadText()         /*Απλά απεικονίζει το κείμενο από το text.txt στην οθόνη*/
{
       char ch;
       ifstream text;
       text.open("text.txt");
       clrscr();
       cout << "\n";
       while (text.get(ch))
       {
               cout << ch;
       }
       text.close();
}

void Text2Wav()
{
       unsigned long spacing=50;
       string channel="L and R";
       int choise;
       int ichannel=4;
       bool ok;

       /*Οι παράμετροι έχουν να κάνουν με το ποιο κανάλι θα δεχθεί τα δεδομένα
       από το text.txt και κάθε πότε θα γράφει τα δεδομένα αυτά...
       Εδώ θέλει προσοχή γιατί το γινόμενο του spacing με τον αριθμό χαρακτήρων
       δεν πρέπει να είναι μεγαλύτερο από το μέγεθος του αρχείου...
       Δηλαδή spacing*num_of_characters < wave file size...
       S P A C I N G : είναι η απόσταση σε bytes του ενός χαρακτήρα από τον άλλο
       Εγώ έδωσα μέγιστο 5ΚΒ σε περίπτωση που έιναι μεγάλο το αρχείο...
       Το ελάχιστο είναι 44bytes για να μην πειράζει το header...*/

       while (choise!=4)
       {
       ok=FALSE;
       clrscr();
       cout << "\nOPTIONS";
       cout << "\n---------------------";
       cout << "\n(1) Select Spacing (Now:" << spacing <<")";
       cout << "\n(2) Select Channel (Now:" << channel <<")";
       cout << "\n(3) Use Encryption (Not available in this version)"; //Υπομονή, χεχεχ...*/
       cout << "\n(4) Encode It, baby...";     /*Τι να κάνει αυτό άραγε...?*/
       cout << "\n\nChoise : ";
       cin >> choise;

       switch (choise)
       {
               case 1:
                       clrscr();
                       while (!ok)
                       {
                               cout << "Enter spacing (45-50000): ";     /*Μέγιστο 5000bytes*/
                               cin >> spacing;
                               if (44<spacing<=5000) ok=TRUE;
                       }
                       break;
               case 2:
                       clrscr();
                       while (!ok)
                       {
                               cout << "\nEnter 0 for Right Channel, 1 for Left Channel, 2 for Stereo: ";
                               cin >> ichannel;
                               if (ichannel==0) channel="Mono Right";
                               if (ichannel==1) channel="Mono Left";
                               if (ichannel==2) channel="Stereo";
                               if (ichannel<=2) ok=TRUE;
                       }
                       break;
               case 3:
                       clrscr();
                       cout << "Not Supported in this version";
                       break;
               case 4:

                       Encode(spacing, ichannel);
                       return;
       }
       }


}

void Encode(unsigned long spacing, int channel)
{
       char buffer[1];
       unsigned char ch;
       unsigned char properties[50];
       unsigned long size;
       unsigned long counter2=0;
       unsigned long counter3=0;
       unsigned long temp=0;
       unsigned long num_of_char=0;
       int i;

       ifstream wave;
       wave.open("wave.wav", ios::in|ios::binary);

       if (!wave)
{

	cout <<"\n\n\\n\n\t\t\tFile not found!\n\n\n\n";
	return;
}
       wave.seekg(0);          /*πηγαίνει τον δείκτη του αρχείου στην αρχή*/

       for (int i=0;i<44;i++)  /*Διαβάζει το header του wave σε ένα πίνακα*/
       {
               properties[i]=wave.get();
       }

       if (properties[8]==0x57 && properties[9]==0x41 && properties[10]==0x56 && properties[11]==0x45)
       {
               clrscr();
               /*Υπολογισμός μεγέθους αρχείου από το Subchunk2Size*/
               size=(long) properties[43]; size=size<<8;
               size+=(long) properties[42]; size=size<<8;
               size+=(long) properties[41]; size=size<<8;
               size+=(long) properties[40];
       }

       ifstream text;
       text.open("text.txt");

       ofstream new_wave;
       new_wave.open("new_wave.wav",ios::out|ios::binary);

       wave.seekg(0);
       new_wave.seekp(0);
       text.seekg(0);

       clrscr();
       cout << "Please wait...\nNow processing the byte below:" <<endl;

       for (unsigned long counter=0; counter<size; counter++)
       {
               /*O counter είναι κάνει το indexing στα bytes του αρχείου WAV...
               Με αυτόν γράφουμε τα bytes του ενός αρχείου στο άλλο...
               Το ίδιο ισχύει και για τον counter2 ο οποίος κάνει το indexing
               του text.txt αρχείου, γιατί έχει διαφορετικό μέγεθος από τα άλλα δυο...*/
               counter2++;
               wave.seekg(counter);
               new_wave.seekp(counter);
               wave.read(buffer,1);    /*αντιγράφει byte προς byte*/

               if (temp==3363)
               /*Το 3363 είναι ένας τυχαίος αριθμός και χρησιμεύει μόνο για κάνουμε display το Byte που επεξεργαζόμαστε εκείνη την στιγμή...*/
               {
                       cout << "\b\b\b\b\b\b\b\b\b\b" << counter;
                       temp=0;
               }
               temp++;

               /*Εδώ ελέγχουμε το spacing και ανάλογα με το μέγεθος που έχουμε
               επιλέξει αντιγράφουμε το byte του text.txt στο new_wave.wav*/
               if (counter2==spacing+1 && text.get(ch))
               {
                       text.seekg(counter3);
                       text.read(buffer,1);
                       new_wave.write(buffer,1);
                       counter2=0;
                       counter3++;
                       num_of_char++;  /*Με την διπλανό μετράμε τον αριθμό χαρακτήρων του text.txt
                                       έτσι ώστε να το χρησιμοποιήσουμε κατά την αποκωδικοποίηση...*/
               }
               else new_wave.write(buffer,1);
       }

       /*Με το παρακάτω if καδικοποιούμε στην θέση 47 και 46 του αρχείου WAV το
       spacing (στο 47 το Low-Byte και στο 46 το High-Byte) που χρησιμοποιήσαμε
       για την κωδικοποίηση... Αυτό θα το χρησιμοποιήσουμε αργότερa για να
       αποκωδικοποιήσουμε το κείμενο μέσα από το αρχείο*/

       buffer[0]=spacing;
       new_wave.seekp(47);
       new_wave.write(buffer,1);
       new_wave.seekp(46);
       if (spacing>255) buffer[0]=spacing>>8;
       else buffer[0]=0x00;
       new_wave.write(buffer,1);

       /*Με το παρακάτω γράφουμε τον αριθμό χαρακτήρων του text.txt στο new_wave.wav
       έτσι ώστε να το χρησιμοποιήσουμε κατά την αποκωδικοποίηση...
       Αν το κείμενο είναι μεγαλύτερο από 255 χαρακτήρες, τότε το LSB πάει
       στο 49 και το MSB στο 48...*/
       buffer[0]=num_of_char;
       new_wave.seekp(49);
       new_wave.write(buffer,1);
       new_wave.seekp(48);
       if (num_of_char>255) buffer[0]=num_of_char>>8;
       else buffer[0]=0x00;
       new_wave.write(buffer,1);

       /*Η επόμενη ρουτίνα for είναι για να γράφει τα τελευταία byte του αρχείου που κλείνουν
       στην ουσία το header του WAV και πρέπει να αντιγραφούν ως έχουν*/
       for (unsigned long counter=size; counter<size+76; counter++)
       {
               wave.seekg(counter);
               new_wave.seekp(counter);
               wave.read(buffer,1);
               new_wave.write(buffer,1);
       }
       /*Το num_of_chares μετράει τους χαρακτήρες του text.txt
       έτσι ώστε να το γράψει στην θέση 49 και 48 του new_wave...
       Με τον τρόπο αυτό κατά την αποκωδικοποίηση θα ξέρει το
       πρόγραμμα πόσους χαρακτήρες πρέπει να διαβάσει...*/

       /*Κλείσιμο όλων των αρχείων*/
       text.close();
       wave.close();
       new_wave.close();

}

void Decode(void)
{
       char properties[50];
       char buffer[2];
       unsigned long spacing, num_of_char, srate, size;

       /*Άνοιγμα νέου αρχείου text για να εγγραφεί το αποκωδικοποιημένο κείμενο*/
       ofstream text;
       text.open("dec_text.txt", ios::out|ios::binary);

       /*Ψάχνουμε να δούμε αν υπάρχει το αρχείο new_wave.wav στον φάκελο
       και αν υπάχει το ανοίγουμε...*/
       ifstream wave;
       wave.open("new_wave.wav", ios::in|ios::binary);

       if (!wave)
{

	cout <<"\n\n\\n\n\t\t\tFile not found!\n\n\n\n";
	return;
}
       wave.seekg(0);          /*πηγαίνει τον δείκτη του αρχείου στην αρχή*/

       for (int i=0;i<50;i++)  /*Διαβάζει το header του wave σε ένα πίνακα*/
       {
               properties[i]=wave.get();
       }
       /*Στις θέσεις 47 και 46 πρέπει να υπάρχει το spacing και στις 48 και 49
       ο αριθμός των χαρακτήρων*/

       spacing=properties[46]; spacing=spacing<<8;
       spacing+=properties[47];
       num_of_char=properties[48]; num_of_char=num_of_char<<8;
       num_of_char+=properties[49];

       clrscr();
       cout << "\nThe WAV has been decoded and these are stats...:";
       cout << "\n\n";
       if (properties[20]==0x01) cout << "\nAudio Format\t:\tLinear Quantization";
       else cout << "\nAudio Format\t:\tCompressed";

       /*Υπολογισμός του αριθμού καναλιών από το NumChannels*/
       if (properties[22]==0x01) cout << "\nNum of Channels\t:\tMono";
       if (properties[22]==0x02) cout << "\nNum of Channels\t:\tStereo";

       /*Υπολογισμός του ρυθμού δειγματοληψίας από το SampleRate*/
       srate=0; srate=(long) properties[25]; srate=srate<<8; srate+=(long) properties[24];
       cout << "\nSample Rate\t:\t" <<srate;

       /*Υπολογισμός της κωδικοποίησης της δειγματοληψίας από το BitsPerSample*/
       size=(long) properties[34];
       cout << "\nBits Per Sample\t:\t" << size;

       /*Υπολογισμός μεγέθους αρχείου από το Subchunk2Size*/
       size=(long) properties[43]; size=size<<8;
       size+=(long) properties[42]; size=size<<8;
       size+=(long) properties[41]; size=size<<8;
       size+=(long) properties[40];
       cout <<"\nSize\t\t:\t" << size/1000000 << " MB";

       /*Υπολογισμός διάρκειας του αρχείου wav*/
       cout <<"\nPlaytime\t:\t" << size/4/srate/60 << ":" << size/4/srate-size/4/srate/60*60  <<" sec";

       cout << "\nCoding Spacing\t:\t" << spacing;
       cout << "\nNum of chars\t:\t" << num_of_char;

       for (unsigned long i=1; i<num_of_char+1; i++)
       {
               wave.seekg((spacing)*i-1);
               text.seekp(i);
               wave.read(buffer,1);
               text.write(buffer,1);
       }
       buffer[0]=0x0D; buffer[1]=0x0A; /*Χαρακτήρας κενού*/
       text.write(buffer,2);
       text.write(buffer,2);
       text << "NOTE:";
       text.write(buffer,2);
       text << "-----";
       text.write(buffer,2);
       text << "This text has been restored from the WAV...";
       text.write(buffer,2);
       text << "The spacing was   : " << spacing << "  bytes per text char...";
       text.write(buffer,2);
       text << "The text's number of characters are   : " << num_of_char;
       text.write(buffer,2);
       text.write(buffer,2);
       text.write(buffer,2);
       text << "\Code by Jaco, 9/2/05...";

       wave.close();
       text.close();

}


 

Update notes:

 

v.1.0.1 -- 10/02/2005

-----------------------

Bug fix: Όταν έκανε κωδικοποίηση με βήμα πάνω από 50 samples/char τότε κατά την αποκωδικοποίηση το κείμενο που προέκυπτε δεν ήταν σωστό...

 

Note: Δουλεύει και με ελληνικά...

 

Jaco...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 μήνες μετά...
  • Super Moderators
τωρα σοβαρα, τα εχει διαβασει κανει ολα?

 

Όποιος ενδιαφέρεται (και καταλαβαίνει) διαβάζει την εξαιρετική δουλειά του Jaco.

 

Σοβαρά.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 μήνες μετά...

ksexases na doseis kai ta run time files gia borland gia na treksei i efarmogi gia na glitosoume to compile :razz: . kala ola auta ta iksera. oxi toso analitika gia tin steganografia kai pos ginetai embedded ena arxeia se wav, jpg klp. to kalitero omos de to aneferes. pos tha ginei ektelesi allou programmatos embedded se arxeio allo ektos apo exe. an ginetai diladi giati den eimai sigouros. diladi na exoume ena wav ensomatomeno me enan io kai o allos na akouei to komati xoris na kserei oti tin exei @@@ giati exei ektelestei to komati tou iou prota. xexe. auto exei megalitero endiaferon. kai leo gia io dioti otan ensomatoneis kati se ena allo arxeio allazei to megethos tou. opote fainetai amesos oti exei metablithei to arxeio

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.


  • Δημιουργία νέου...