/* This is one of the cipher files for the cipher interface written ** by wart@ugcs.caltech.edu ** ** Please don't steal my code without my permission. ** */ #include #include #include #include "term.h" #include "types.h" #include "ctypes.h" vigenere_base::vigenere_base(){ period = 0; period_set = FALSE; length = 0; } int vigenere_base::execute_option(char option){ int valid = TRUE; switch(option){ case CHANGEPERIOD: change_period(); break; case SUBSTITUTE: substitute(); break; case UNDO: undo(); break; case ALPHFIT: alphfit(); break; default: valid = base_exec_option(option); break; } return valid; } void vigenere_base::change_period(){ period_set = FALSE; set_period(); clear_to_prompt(); } void vigenere_base::setup_key(){ key.init(period); } void vigenere_base::substitute(){ int column; char tmp_str[STRINGLENGTH]; char ct_letter, pt_letter; prompt("What column is the letter in? "); read_line(tmp_str); if(sscanf(tmp_str, "%d", &column) != 1) msgerror("Bad input."); else if(column < 1 || column > period) msgerror("Bad position."); else{ prompt("What is the new letter? (ct,pt) "); read_line(tmp_str); if(sscanf(tmp_str, "%c,%c", &ct_letter, &pt_letter) != 2){ msgerror("Bad format."); } else if(!isalpha(ct_letter) || !isalpha(pt_letter)){ msgerror("Bad letter."); } else{ sub_letter(ct_letter | ' ', pt_letter | ' ', column-1); } } } void vigenere_base::alphfit(){ char tmp_str[STRINGLENGTH]; int i, column; prompt("Fit which column? (* for all) "); read_line(tmp_str); if(*tmp_str == '*'){ for(i = 0; i < period; i++){ fit_column(i); } } else if(sscanf(tmp_str, "%d", &column) != 1){ msgerror("Bad column."); } else if(column < 1 || column > period){ msgerror("Column out of range."); } else{ fit_column(column-1); } } void vigenere_base::undo(){ int column, i; prompt("Which column? (* for all) "); column = get_char(); if(column == '*'){ for(i = 0; i < period; i++) key.clearkey(i); } else{ column -= '1'; key.clearkey(column); } } void vigenere_base::show_menu(){ menu(2, "Options: (S)ubstitute (A)pply fit (U)ndo (C)hange period"); menu(1, " (W)rite (Q)uit"); } void vigenere_base::show_cipher(){ int i, line_length; char tmp_str[20]; line_length = COLS / (period+1); i = 0; while(i < length){ strncpy(tmp_str, cipher+i, period); tmp_str[period] = (char) NULL; msgprint((i*(period+1)/period)%(line_length*(period+1)), (i/(line_length*period))*3 + 1, tmp_str); decode(tmp_str); msgprint((i*(period+1)/period)%(line_length*(period+1)), (i/(line_length*period))*3 + 0, tmp_str); i += period; } } void vigenere_base::decode(char *message){ int i; for(i = 0; i < strlen(message); i++){ if(key.val(i) == BLANK) message[i] = BLANK; else message[i] = get_pt(message[i], key.val(i)); } } void vigenere_base::show_key(){ int i; for(i = 0; i < period; i++){ if(key.val(i) != BLANK){ msgprint(3*i+4, 15, "%2d", key.val(i) - 'a'); put_char(key.val(i), 3*i + 5, 16); } else{ msgprint(3*i+4, 15, " ."); put_char(BLANK, 3*i + 5, 16); } } } void porta::show_key(){ int i, row_offset; for(i = 0; i < period; i++){ if(key.val(i) != BLANK){ row_offset = (key.val(i)-'a')%2; /* Print the first key letter */ msgprint(3*i+4, 15+row_offset, "%2d", (key.val(i)-'a')/2); put_char(key.val(i), 3*i + 5, 16+row_offset); /* Print the second key letter */ if(row_offset == 1) put_char(key.val(i)-1, 3*i + 5, 16); else put_char(key.val(i)+1, 3*i + 5, 16+1); } else{ msgprint(3*i+4, 15, " ."); put_char(BLANK, 3*i + 5, 16); } } } void vigenere_base::sub_letter(char ct_letter, char pt_letter, int column){ char key_letter; key_letter = get_key_letter(ct_letter, pt_letter); if(key_letter){ key.alter(key_letter, column); } } void vigenere_base::fit_column(int column){ int i, k, fweights[26]; static int weights[] = { 1863, 954, 1477, 1644, 2114, 1447, 1204, 1544, 1869, 301, 477, 1544, 1398, 1892, 1869, 1431, 477, 1887, 1799, 1969, 1431, 1114, 1204, 699, 1279, 0}; int maxweight=0, maxpos=0; for(i = 0; i < 26; i++) fweights[i] = 0; /* Rotate through the 26 possible keys */ for(k = 0; k < 26; k++){ /* Rotate each letter in the column */ for(i = column; i < length; i+=period){ fweights[k] += weights[get_pt(cipher[i], k+'a') - 'a']; } } /* Find the largest weight and make that substitution. */ for(i = 0; i < 26; i++){ if(maxweight < fweights[i]){ maxweight = fweights[i]; maxpos = i; } } sub_letter(get_ct('a', maxpos+'a'), 'a', column); } void vigenere_base::decipher(char *string){ int i=0; while(i < length){ *string++ = get_pt(cipher[i], key.val(i%period)); i++; } *string = (char) NULL; }