#include #include /* Korduvate kombinatsioonide otsimine */ #define FIND_SEQUENCE_CMD "SEQ" int find_sequences(char*); /* Krüptoteksti sõnedeks lahutamine */ #define SPLIT_SUBWORDS_CMD "SPLIT" int split_subwords(char*, int); /* Nihkega omavaheliste kokkulangevuste indeksite leidmine */ #define SHIFT_MATCH_IDX_2_CMD "SMI2" int match_index_shift_ii(char*, char*); /* 26 Vigenere nihkega teksti trükkimine */ #define PRINT_VIGENERE_SHIFT_26_CMD "PVS26" int print_vigenere_shift(char*, char*); /* argc ja argv on vahetuses. püha kristus, mis viga.. */ int main(int argv, char **argc) { char *tmp; int i; /* Vale argumentide arv */ if(argv < 3) { printf("Kasutus: '%s' [parameetrid]\n\n" "\tkäsk := { %2$s, %3$s, %4$s, %5$s }\n" "\t\t%2$s\tLeia kõik enam kui 3-tähelised korduvad kombinatsioonid\n" "\t\t%3$s\tLahuta krüptotekst sõnedeks (sõnede arv anda lisaparameetrina)\n" "\t\t%4$s\tLeia krüptotekstidevahelised kokkulangevusindeksid nihkega kuni 26\n" "\t\t\t\t\t(teine krüptotekst lisaparameetrina)\n" "\t\t%5$s\tTrüki 26 Vigenere nihkeshifri võimalikku lahendit\n" "\t\t\t\t\t(suhtelised võtmed lisaparameetritena, ka esimene 0)\n" "\n" "\tMõni käsk võib vajada lisaparameetreid\n", argc[0], FIND_SEQUENCE_CMD, SPLIT_SUBWORDS_CMD, SHIFT_MATCH_IDX_2_CMD, PRINT_VIGENERE_SHIFT_26_CMD); return 1; } /* Korduvate kombinatsioonide otsimine */ if(strcasecmp(argc[1], FIND_SEQUENCE_CMD) == 0) { return find_sequences(argc[2]); } /* Sõnedeks lahutamine */ else if(strcasecmp(argc[1], SPLIT_SUBWORDS_CMD) == 0) { /* Lisaparameetri verifitseerimine */ if(argv < 4) { printf("See käsk vajab lisaparameetrit käsureal krüptoteksti järel - sõnede arvu.\n"); return 1; } if(atoi(argc[3]) == 0) { printf("Sõnede arv on sobimatu (ta peab olema arv ja suurem kui 0).\n"); return 1; } return split_subwords(argc[2], atoi(argc[3])); } /* Kürptotekstidevaheline kokkulangevusindeks nihkega */ else if(strcasecmp(argc[1], SHIFT_MATCH_IDX_2_CMD) == 0) { /* Lisaparameetri verifitseerimine */ if(argv < 4) { printf("See käsk vajab lisaparameetrit käsureal krüptoteksti järel - teist krüptoteksti.\n"); return 1; } return match_index_shift_ii(argc[2], argc[3]); } /* Vigenere nihkega trükkimine */ else if(strcasecmp(argc[1], PRINT_VIGENERE_SHIFT_26_CMD) == 0) { /* Lisaparameetrite moondamine */ if(argv < 4) { printf("See käsk vajab lisaparameetreid käsureal krüptoteksti järel - suhtelisi võtmeid.\n"); return 1; } tmp = malloc(argv - 2); for(i = 0; i < argv - 3; i++) { tmp[i] = atoi(argc[3 + i]) + 'A'; } tmp[i] = 0; return print_vigenere_shift(argc[2], tmp); } /* Käsku ei tuntud ära */ printf("Tundmatu käsk: %s\nAbi saamiseks käivita '%s' ilma argumentideta.\n", argc[1], argc[0]); return 1; } /* Korduvate kombinatsioonide otsimine */ int find_sequences(char *cyph) { int cyphlen, matchlen; char *seq_start, *comp, tmp; cyphlen = strlen(cyph); printf("Korduvate tähekombinatsioonide otsimine (krüptoteksti pikkus: %d):\n%s\n\n", cyphlen, cyph); /* Iga krüptoteksti täht on potensiaalse korduva kombinatsiooni alguseks */ for(seq_start = cyph; seq_start < cyph + cyphlen - 5; seq_start++) { /* Potensiaalne kombinatsioon peitub iga ülejäänud krüptoteksti tähe juures */ for(comp = seq_start + 3; comp < cyph + cyphlen - 2; comp++) { /* Võtame nii palju võrdseid tähti, kui saab */ matchlen = 0; while ((seq_start[matchlen] == comp[matchlen]) && (seq_start + matchlen != comp)) { matchlen++; } /* Kui võrdseid tähti oli piisavalt */ if(matchlen >= 3) { tmp = seq_start[matchlen]; seq_start[matchlen] = 0; printf("Positsioonide %d & %d vahel on %d-täheline kokkulangevus: %s\n", (long) (seq_start - cyph), (long) (comp - cyph), matchlen, seq_start); seq_start[matchlen] = tmp; } } /* for (comp = seq_start .. cyphlen) */ } /* for (seq_start = cyph .. cypphlen) */ return 0; } /* Krüptoteksti sõnedeks lahutamine */ int split_subwords(char *cyph, int subwords) { int subword, cyphlen; char *walker; cyphlen = strlen(cyph); printf("Krüptoteksti sõnedeks lahutamine (%d sõne):\n\n", subwords); /* Iga sõne eraldi vaatluse alla */ for(subword = 0; subword < subwords; subword++) { printf("Sõne %d:\n", subword); /* Sõnede arvuga aritmeetiliselt võrdse sammuga tähti trükkima */ for(walker = cyph + subword; walker < cyph + cyphlen; walker += subwords) { putchar(*walker); } printf("\n\n"); } /* for (i = 0 ... subwords) */ } /* EELDAB: krüptotekst koosneb suurtest tähtedest */ /* Nihkega omavahelise kokkulangevuste indeksite leidmine */ int match_index_shift_ii(char *cyph1, char *cyph2) { int *counts1, *counts2, i, shift; double match_index; printf("Krüptotekstidevaheliste kokkulangevusindeksite leidmine nihkega kuni 26:\n\n"); /* Loendurite mälu prepareerimine */ counts1 = malloc(26 * sizeof(int)); counts2 = malloc(26 * sizeof(int)); if(!(counts1 && counts2)) { printf("Viga mälu hankimisel.\n"); return 1; } memset(counts1, 0, (26 * sizeof(int))); memset(counts2, 0, (26 * sizeof(int))); /* Krüptotekstide sageduste leidmine */ for(i = 0; i < strlen(cyph1); i++) { counts1[cyph1[i] - 'A']++; } for(i = 0; i < strlen(cyph2); i++) { counts2[cyph2[i] - 'A']++; } /* Kokkulangevusindeksid kõikvõimalike nihetega */ for(shift = 0; shift < 26; shift++) { match_index = 0; for(i = 0; i < 26; i++) { match_index += counts1[i] * counts2[(i + shift) % 26]; } match_index /= strlen(cyph1)*strlen(cyph2); printf("Nihkel %d: %f\n", shift, match_index); } return 0; } /* 26 Vigenere nihkega teksti trükkimine */ int print_vigenere_shift(char* cyph, char* dif_key) { int shift, i, cyphlen, keylen; char *tmpkey; cyphlen = strlen(cyph); keylen = strlen(dif_key); printf("Nihkega kuni 26 Vigenere suhtelise võtmega teksti trükkimine:\n\n"); /* Võtme trükkimise jaoks */ tmpkey = malloc(keylen + 1); if(tmpkey == NULL) { printf("Viga mälu eraldamisel.\n"); return 1; } tmpkey[keylen + 1] = 0; /* Erinevate nihete kalkuleerimine */ for(shift = 0; shift < 26; shift++) { /* Uus võti */ for(i = 0; i < keylen; i++) { tmpkey[i] = (dif_key[i] - 'A' + shift) % 26 + 'A'; } printf("Võtmega '%s':\n", tmpkey); for(i = 0; i < cyphlen; i++) { putchar((cyph[i] - 'A' + tmpkey[i % keylen] - 'A') % 26 + 'A'); } printf("\n\n"); } return 0; }