Advertisement
Guest User

Untitled

a guest
Sep 21st, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.50 KB | None | 0 0
  1. /* Implementiert in dieser Datei die Teilaufgabe (b) */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. #include "otp_encrypt.h"
  10. #include "vorgabe.h"
  11.  
  12. extern int exitcode;    /* diesen Wert gibt die main()-Funktion als Exit-
  13.                            Code zurueck (in otp.c definiert) */
  14.  
  15.  
  16.  
  17. /* praktische Fehlermeldungen fuer eure Fehlerbehandlungen */
  18. #define ERRMSG_ENCRYPTED_EXISTS "Die verschluesselte Datei existiert " \
  19.                                 "bereits!"
  20. #define ERRMSG_PLAINTEXT_MISSING "Die Klartext-Datei existiert nicht!"
  21. #define ERRMSG_PLAINTEXT_NOT_REG "Die Klartext-Datei ist keine regulaere " \
  22.                                  "Datei!"
  23. #define ERRMSG_OTP_MISSING "Die OTP-Datei existiert nicht!"
  24. #define ERRMSG_OTP_NOT_REG "Die OTP-Datei ist keine regulaere Datei!"
  25. #define ERRMSG_OTP_TOO_SHORT "Die OTP-Datei ist nicht lang genug!"
  26.  
  27. #define ERRMSG_PLAINTEXT_OPEN "Kann die Klartext-Datei nicht oeffnen!"
  28. #define ERRMSG_OTP_OPEN "Kann die OTP-Datei nicht oeffnen!"
  29.  
  30. #define ERRMSG_OTP_READ "Die OTP-Datei laesst sich nicht lesen!"
  31. #define ERRMSG_MAGIC_OTPENC_USED "Das One-Time Pad wurde bereits zum " \
  32.                                  "Verschluesseln benutzt!"
  33. #define ERRMSG_MAGIC_OTPDEC "Das One-Time Pad ist nur zum Entschluesseln " \
  34.                             "geeignet!"
  35. #define ERRMSG_MAGIC_NO_OTP "Die angegebene OTP-Datei enthaelt kein " \
  36.                             "One-Time Pad!"
  37.  
  38. #define ERRMSG_ENCRYPTED_CREATE "Kann die verschluesselte Datei nicht " \
  39.                                 "erzeugen!"
  40. #define ERRMSG_ENCRYPTED_WRITE "Die verschluesselte Datei laesst sich " \
  41.                                "nicht schreiben!"
  42.  
  43. #define ERRMSG_OTPENC_MARK "Kann die OTP-Datei nicht als benutzt markieren!"
  44.  
  45. #define ERRMSG_PLAINTEXT_READ "Die Klartext-Datei laesst sich nicht lesen!"
  46.  
  47. #define ERRMSG_PLAINTEXT_CLOSE "Kann die Klartext-Datei nicht schliessen!"
  48. #define ERRMSG_OTP_CLOSE "Kann die OTP-Datei nicht schliessen!"
  49. #define ERRMSG_ENCRYPTED_CLOSE "Kann die verschluesselte Datei nicht " \
  50.                                "schliessen!"
  51.  
  52.  
  53.  
  54. void otp_encrypt(char *in, char *otpenc, char *out)
  55. {
  56.  
  57.     int val1;
  58.     int val2;
  59.     int val3;
  60.     struct stat fileinfo1 = {0};
  61.     struct stat fileinfo2 = {0};
  62.     struct stat fileinfo3 = {0};
  63.     int val4;
  64.     size_t test;
  65.     int mnr;
  66.     int i;
  67.     int count = 0;
  68.     size_t fill;
  69.  
  70.  
  71.     /*
  72.        Hier soll mit Hilfe eines One-Time Pads eine Klartext-Datei
  73.        (eine normale Datei mit vertraulichem Inhalt) verschluesselt werden.
  74.  
  75.        "in" enthaelt den Namen dieser Klartext-Datei. "otpenc" enthaelt den
  76.        Namen eines unverbrauchten (noch nicht benutzten) One Time Pads.
  77.        "out" ist der Name der zu erzeugenden verschluesselten Datei.
  78.  
  79.        Wichtig: denkt auch immer an die Fehlerbehandlung.
  80.     */
  81.  
  82.     FILE *in_file = NULL, *otpenc_file = NULL, *out_file = NULL;
  83.     char inout_buf[BUF_SIZE], otpenc_buf[BUF_SIZE];
  84.  
  85.  
  86.     /* Makros zur Erleichterung der Fehlerbehandlung */
  87. #define cancel2(errmsg) {               \
  88.         fprintf(stderr, "%s\n", errmsg);        \
  89.                                                         \
  90.         /* Schliesst alle Dateien die erfolgreich       \
  91.            geoeffnet wurden (fclose(3)). Man sollte     \
  92.            eigentlich auch die unfertige ver-           \
  93.            schluesselte Datei loeschen, aber setzt  \
  94.            remove(3) sehr umsichtig ein! */             \
  95. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */             \
  96.     if (otpenc_file != NULL) {                  \
  97.         fclose(otpenc_file);            \
  98.     }                       \
  99.     if (in_file != NULL) {              \
  100.         fclose(in_file);            \
  101.     }                       \
  102.         if (out_file != NULL) {                         \
  103.         fclose(out_file);           \
  104.         remove(out);                \
  105.     }                       \
  106.         exitcode = EXIT_FAILURE;            \
  107.         return;                     \
  108.     }  /* cancel2() */
  109.  
  110. #define cancel(failedcall, errmsg) {    \
  111.         perror(failedcall);     \
  112.         cancel2(errmsg);        \
  113.     }  /* cancel() */
  114.  
  115.     /* Wenn ihr das parametrisierte Makro cancel2() vervollstaendigt, dann
  116.        koennt ihr euch wieder jede Menge Tipparbeit bei der Fehlerbehandlung
  117.        ersparen. cancel() ist wie in generate_otp() fuer fehlgeschlagene
  118.        Systemaufrufe gedacht, und cancel2() fuer alle anderen Fehler. */
  119.  
  120.  
  121.     /* (passt diesen printf() geringfuegig an) */
  122.     printf("Es wird eine Klartext-Datei mit dem Schluessel aus einer "
  123.            "OTP-Datei\n"
  124.            "verschluesselt in eine andere Datei geschrieben.\n\n"
  125.            "Klartext-Datei: %s\n"
  126.            "OTP-Datei: %s\n"
  127.            "verschluesselte Datei: %s\n\n",
  128.            in, otpenc, out);
  129.  
  130.  
  131.     /* HINWEIS: Ihr habt schon ein paar Variablen vorgegeben, die ihr
  132.        verwenden koennt:
  133.        in, otpenc und out mit den gegebenen Dateinamen,
  134.        in_file, otpenc_file und out_file fuer die geoeffneten Dateien,
  135.        und inout_buf[BUF_SIZE] und otpenc_buf[BUF_SIZE] fuer die Puffer.*/
  136.  
  137.  
  138.     /* Es darf keine existierende Datei ueberschrieben werden ("out" darf
  139.        also nicht bereits existieren). Ueberprueft dies mit stat(2). */
  140. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  141.  
  142.     val1 = stat(otpenc, &fileinfo1);
  143.     if (val1 == -1) {
  144.         cancel("stat", ERRMSG_OTP_MISSING);
  145.     }
  146.     val2 = stat(in, &fileinfo2);
  147.     if (val2 == -1) {
  148.         cancel("stat", ERRMSG_PLAINTEXT_MISSING);
  149.     }
  150.     val3 = stat(out, &fileinfo3);
  151.     if (val3 != -1) {
  152.         cancel("stat", ERRMSG_ENCRYPTED_EXISTS);
  153.     }
  154.  
  155.  
  156.     /* Ueberprueft nun ebenfalls mit stat(2), ob die Klartext-Datei aus "in"
  157.        und die OTP-Datei aus "otpenc" nicht nur existieren, sondern auch
  158.        regulaere Dateien sind (S_ISREG(m)). */
  159. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  160.  
  161.  
  162.     if (!(S_ISREG(fileinfo1.st_mode))) {
  163.         cancel("S_ISREG", ERRMSG_OTP_NOT_REG);
  164.     }
  165.     if (!(S_ISREG(fileinfo2.st_mode))) {
  166.         cancel("S_ISREG", ERRMSG_PLAINTEXT_NOT_REG);
  167.     }
  168.  
  169.     /* Ausserdem muss die OTP-Datei mindestens 4 Bytes laenger als die
  170.        Klartext-Datei sein, damit das One-Time Pad lang genug ist, da es
  171.        vier Bytes kuerzer als die gesamte OTP-Datei ist (aufgrund der magic
  172.        number in der OTP-Datei). */
  173. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  174.  
  175.  
  176.     if (fileinfo1.st_size < (fileinfo2.st_size + 4)) {
  177.         cancel("st_size", ERRMSG_OTP_TOO_SHORT);
  178.     }
  179.  
  180.  
  181.     /* Oeffnet die Klartext-Datei und die OTP-Datei mit fopen(3). */
  182. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  183.  
  184.  
  185.     in_file = fopen(in, "r");
  186.     if (in_file == NULL) {
  187.         cancel("fopen", ERRMSG_PLAINTEXT_OPEN);
  188.     }
  189.     otpenc_file = fopen(otpenc, "r+");
  190.     if (otpenc_file == NULL) {
  191.         cancel("fopen", ERRMSG_OTP_OPEN);
  192.     }
  193.  
  194.     /* Lest die magic number der OTP-Datei mit fread(3) und ueberprueft sie
  195.        (MAGIC_OTPENC_NEW). Benutzt hier die vorgegebene Funktion
  196.        bigendian(), da die magic number immer im Big-Endian-Format sein
  197.        soll. */
  198. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  199.  
  200.     test = fread(&val4, sizeof(int), 1, otpenc_file);
  201.     if (test != 1) {
  202.         cancel("fread", ERRMSG_OTP_READ);
  203.     }
  204.     if (val4 != bigendian(MAGIC_OTPENC_NEW)) {
  205.         if (val4 == bigendian(MAGIC_OTPENC_USED)) {
  206.             cancel("validate", ERRMSG_MAGIC_OTPENC_USED);
  207.         }
  208.         else if (val4 == bigendian(MAGIC_OTPDEC)) {
  209.             cancel("validate", ERRMSG_MAGIC_OTPDEC);
  210.         }
  211.         cancel("validate", ERRMSG_MAGIC_NO_OTP)
  212.     }
  213.  
  214.  
  215.  
  216.     /* Erzeugt die verschluesselte Datei indem ihr sie mit fopen(3)
  217.        oeffnet. */
  218. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  219.  
  220.     out_file = fopen(out, "w");
  221.     if (out_file == NULL) {
  222.         cancel("fopen", ERRMSG_ENCRYPTED_CREATE );
  223.     }
  224.  
  225.  
  226.     /* Schreibt auch sofort mit fwrite(3) die magic number in die neue
  227.        verschluesselte Datei (MAGIC_ENCRYPTED_FILE). Benutzt dabei wieder
  228.        bigendian(). */
  229. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  230.  
  231.     mnr = bigendian(MAGIC_ENCRYPTED_FILE);
  232.     test = fwrite(&mnr, sizeof(int), 1, out_file);
  233.     if (test != 1) {
  234.         cancel("fwrite", ERRMSG_ENCRYPTED_WRITE);
  235.     }
  236.  
  237.  
  238.  
  239.     /* "Entwertet" die OTP-Datei, indem ihr die magic number in
  240.        MAGIC_OTPENC_USED aendert (damit das OTP nicht mehrfach verwendet
  241.        werden kann). Auch hier muss wieder bigendian() benutzt werden.
  242.        Springt dazu mit fseek(3) an den Anfang der Datei zurueck und
  243.        schreibt mit fwrite(3) die neue magic number. */
  244. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  245.  
  246.     /* Hier keine Fehlerbehandlung, da unnötig: Springen an den Anfang muss immer gehen */
  247.     fseek(otpenc_file, 0, SEEK_SET);
  248.     mnr = bigendian(MAGIC_OTPENC_USED);
  249.     test = fwrite(&mnr, sizeof(int), 1, otpenc_file);
  250.     if (test != 1) {
  251.         cancel("fwrite", ERRMSG_OTPENC_MARK);
  252.     }
  253.    
  254.  
  255.  
  256.  
  257.     /* Verschluesselt den Inhalt der Klartext-Datei (Inhalt und OTP mit
  258.        fread(3) lesen, Inhalt verschluesseln und mit fwrite(3) schreiben).
  259.        Dazu muesst ihr in einer Schleife blockweise (BUF_SIZE) arbeiten,
  260.        da eine Datei sehr lang sein kann. */
  261.     while ( !(feof(in_file)) ) {  /* Ersetzt die 0 durch einen geeigneten feof(3)-Aufruf. */
  262.  
  263.         /* einen Block aus der Klartext-Datei lesen */
  264. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  265.  
  266.     if (fileinfo2.st_size-(count*BUF_SIZE+4) < BUF_SIZE) {
  267.         fill = (size_t)(fileinfo2.st_size-(count*BUF_SIZE+4));
  268.     }
  269.     else {
  270.         fill = BUF_SIZE;
  271.     }
  272.  
  273.  
  274.  
  275.     test = fread(&inout_buf, sizeof(char), fill, in_file);
  276.     if (ferror(in_file)) {
  277.         cancel("fread", ERRMSG_PLAINTEXT_READ);
  278.     }
  279.  
  280.  
  281.  
  282.         /* einen genauso grossen Block aus dem OTP lesen */
  283. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  284.  
  285.     test = fread(&otpenc_buf, sizeof(char), fill, otpenc_file);
  286.     if (ferror(otpenc_file)) {
  287.         cancel("fread", ERRMSG_OTP_READ);
  288.     }
  289.  
  290.  
  291.  
  292.         /* den Block byteweise mit dem XOR-Operator verschluesseln */
  293. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  294.  
  295.     for (i = 0; i < fill; i++)
  296.         inout_buf[i] = inout_buf[i] ^ otpenc_buf[i];
  297.  
  298.  
  299.         /* den verschluesselten Block in die Zieldatei schreiben */
  300. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  301.  
  302.  
  303.     test = fwrite(&inout_buf, sizeof(char), fill, out_file);
  304.     if(ferror(out_file)) {
  305.         cancel("fwrite", ERRMSG_ENCRYPTED_WRITE);
  306.     }
  307.  
  308.  
  309.     }
  310.  
  311.     /* Schliesst nun wieder alle Dateien mit fclose(3). */
  312. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  313.  
  314.     val1 = fclose(otpenc_file);
  315.     if (val1 != 0)
  316.         cancel("fclose", ERRMSG_OTP_CLOSE);
  317.     val2 = fclose(in_file);
  318.     if (val2 != 0)
  319.         cancel("fclose", ERRMSG_ENCRYPTED_CLOSE);
  320.     val3 = fclose(out_file);
  321.     if (val3 != 0)
  322.         cancel("fclose", ERRMSG_PLAINTEXT_CLOSE);
  323.  
  324.  
  325.  
  326.     /* Gebt abschliessend eine Erfolgsmeldung aus. */
  327. /* HIER MUESST IHR EUREN CODE EINFUEGEN! */
  328.  
  329.     printf(" Die Datei wurde erfolgreich verschlüsselt, und das OneTimePad entwertet.\n\n");
  330.  
  331.  
  332.  
  333. #undef cancel
  334. #undef cancel2
  335. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement