/* PlayFair chiper */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTR 1000
#define WIDTH 5
#define TABLESIZE 25
#define NLETTER 26
#define ENCRYPTION 1
#define DECRYPTION (WIDTH - ENCRYPTION)
char * extract( char * , const char * ) ;
void delX( char * ) ;
char * getpair( char * , const char * ) ;
int lookup( const char * , int ) ;
void makepair( char * , const char * ) ;
void maketable( char * , const char * ) ;
char * playfair( const char * , const char * , int , int ) ;
char * replace( char * , const char * , int ) ;
void replace_all( char * , const char * , int ) ;
int rowcoltochar( const char * , int , int ) ;
void showpair( const char * ) ;
const char * topair( char * , const char * ) ;
void showtable( char * ) ;
int main( int argc, char * argv[ ] )
{
char * out = NULL , * out2 = NULL ;
printf ( "<< ENCRYPTION >>\n " ) ;
out = playfair( "hello, world" , "fairplay" , ENCRYPTION, 1 ) ;
printf ( "%s\n " , out) ;
printf ( "\n << DECRYPTION >>\n " ) ;
out2 = playfair( out, "fairplay" , DECRYPTION, 1 ) ;
printf ( "%s\n " , out2) ;
free ( out) ;
free ( out2) ;
return 0 ;
}
char * playfair( const char * src, const char * key, int direction, int verbose)
{
char table[ TABLESIZE] ;
char * es = ( char * ) malloc ( strlen ( src) + 1 ) ;
char * ek = ( char * ) malloc ( strlen ( src) + 1 ) ;
char * out = NULL ;
if ( direction ! = ENCRYPTION && direction ! = DECRYPTION)
goto error;
if ( es == NULL || ek == NULL )
goto error;
ek = extract( ek, key) ;
if ( verbose)
printf ( "key:\n %s\n %s\n " , key, ek) ;
maketable( table, key) ;
if ( verbose)
showtable( table) ;
es = extract( es, src) ;
if ( verbose)
printf ( "src:\n %s\n %s\n " , src, es) ;
out = ( char * ) malloc ( strlen ( es) * 2 + 1 ) ;
if ( out == NULL )
goto error;
if ( direction == ENCRYPTION) {
makepair( out, es) ;
} else {
strcpy ( out, es) ;
}
if ( verbose)
showpair( out) ;
replace_all( out, table, direction) ;
if ( verbose) {
showpair( out) ;
fflush ( stdout ) ;
}
if ( direction == DECRYPTION)
delX( out) ;
return out;
error:
free ( ek) ;
free ( es) ;
free ( out) ;
return NULL ;
}
void maketable( char * table, const char * key)
{
int i, j;
char used[ NLETTER] ;
static char k[ MAXSTR] ;
memset ( table, '\0 ' , TABLESIZE) ;
memset ( used, 0 , sizeof ( used) ) ;
used[ 'J' - 'A' ] = 1 ;
extract( k, key) ;
for ( i = 0 , j = 0 ; k[ i] ; i++ ) {
int c = ( k[ i] == 'J' ) ? 'I' : k[ i] ;
if ( used[ c - 'A' ] )
continue ;
used[ c - 'A' ] = 1 ;
table[ j++ ] = c;
}
for ( i = 0 ; j < TABLESIZE; j++ ) {
while ( used[ i] )
i++ ;
table[ j] = i++ + 'A' ;
}
}
void showtable( char * table)
{
int i;
for ( i = 0 ; i < TABLESIZE; i++ ) {
int c = table[ i] ;
if ( c == '\0 ' )
c = '.' ;
printf ( ( i % WIDTH) ? " %c" : "%c" , c) ;
if ( ( i + 1 ) % WIDTH == 0 )
printf ( "\n " ) ;
}
}
char * extract( char * to, const char * from)
{
char * retval = to;
for ( ; * from; from++ )
if ( isalpha ( * from) )
* to++ = toupper ( * from) ;
* to = '\0 ' ;
return retval;
}
void makepair( char * out, const char * p)
{
while ( p = topair( out, p) )
out + = 2 ;
out = '\0 ' ;
}
const char * topair( char * pair, const char * s)
{
if ( * s == '\0 ' )
return NULL ;
pair[ 0 ] = * s++ ;
if ( pair[ 0 ] == * s || * s == '\0 ' )
pair[ 1 ] = 'X' ;
else
pair[ 1 ] = * s++ ;
return s;
}
void showpair( const char * s)
{
int isfirst = 1 ;
while ( * s) {
if ( ! isfirst)
printf ( "-" ) ;
isfirst = 0 ;
if ( s[ 1 ] == '\0 ' ) {
/* ありえないと思うが */
printf ( "%c" , s[ 0 ] ) ;
s++ ;
} else {
printf ( "%c%c" , s[ 0 ] , s[ 1 ] ) ;
s + = 2 ;
}
}
printf ( "\n " ) ;
}
void replace_all( char * s, const char * table, int dec)
{
while ( s[ 0 ] && s[ 1 ] ) {
replace( s, table, dec) ;
s + = 2 ;
}
}
char * replace( char * pair, const char * table, int dec)
{
int i, pos[ 2 ] , row[ 2 ] , col[ 2 ] ;
for ( i = 0 ; i < 2 ; i++ ) {
pos[ i] = lookup( table, pair[ i] ) ;
row[ i] = pos[ i] / WIDTH;
col[ i] = pos[ i] % WIDTH;
}
if ( row[ 0 ] == row[ 1 ] ) {
for ( i = 0 ; i < 2 ; i++ )
col[ i] = ( col[ i] + dec) % WIDTH;
} else if ( col[ 0 ] == col[ 1 ] ) {
for ( i = 0 ; i < 2 ; i++ )
row[ i] = ( row[ i] + dec) % WIDTH;
} else {
int tmp = col[ 0 ] ;
col[ 0 ] = col[ 1 ] ;
col[ 1 ] = tmp;
}
for ( i = 0 ; i < 2 ; i++ )
pair[ i] = rowcoltochar( table, row[ i] , col[ i] ) ;
return pair;
}
int lookup( const char * table, int c)
{
char * p = strchr ( table, c) ;
return p - table;
}
int rowcoltochar( const char * table, int row, int col)
{
return table[ row * WIDTH + col] ;
}
void delX( char * s)
{
char * t = s;
while ( s[ 0 ] && s[ 1 ] ) {
* t++ = * s++ ;
if ( * s ! = 'X' )
* t++ = * s;
s++ ;
}
* t = '\0 ' ;
}
/* END OF FILE */
LyogUGxheUZhaXIgY2hpcGVyICovCgojaW5jbHVkZSA8Y3R5cGUuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKI2RlZmluZSBNQVhTVFIgMTAwMAojZGVmaW5lIFdJRFRIIDUKI2RlZmluZSBUQUJMRVNJWkUgMjUKI2RlZmluZSBOTEVUVEVSIDI2CiNkZWZpbmUgRU5DUllQVElPTiAxCiNkZWZpbmUgREVDUllQVElPTiAoV0lEVEggLSBFTkNSWVBUSU9OKQoKY2hhciAqZXh0cmFjdChjaGFyICosIGNvbnN0IGNoYXIgKik7CnZvaWQgZGVsWChjaGFyICopOwpjaGFyICpnZXRwYWlyKGNoYXIgKiwgY29uc3QgY2hhciAqKTsKaW50IGxvb2t1cChjb25zdCBjaGFyICosIGludCk7CnZvaWQgbWFrZXBhaXIoY2hhciAqLCBjb25zdCBjaGFyICopOwp2b2lkIG1ha2V0YWJsZShjaGFyICosIGNvbnN0IGNoYXIgKik7CmNoYXIgKnBsYXlmYWlyKGNvbnN0IGNoYXIgKiwgY29uc3QgY2hhciAqLCBpbnQsIGludCk7CmNoYXIgKnJlcGxhY2UoY2hhciAqLCBjb25zdCBjaGFyICosIGludCk7CnZvaWQgcmVwbGFjZV9hbGwoY2hhciAqLCBjb25zdCBjaGFyICosIGludCk7CmludCByb3djb2x0b2NoYXIoY29uc3QgY2hhciAqLCBpbnQsIGludCk7CnZvaWQgc2hvd3BhaXIoY29uc3QgY2hhciAqKTsKY29uc3QgY2hhciAqdG9wYWlyKGNoYXIgKiwgY29uc3QgY2hhciAqKTsKdm9pZCBzaG93dGFibGUoY2hhciAqKTsKCmludCBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCnsKICAgIGNoYXIgKm91dCA9IE5VTEwsICpvdXQyID0gTlVMTDsKICAgIHByaW50ZigiPDwgRU5DUllQVElPTiA+PlxuIik7CiAgICBvdXQgPSBwbGF5ZmFpcigiaGVsbG8sIHdvcmxkIiwgImZhaXJwbGF5IiwgRU5DUllQVElPTiwgMSk7CiAgICBwcmludGYoIiVzXG4iLCBvdXQpOwogICAgcHJpbnRmKCJcbjw8IERFQ1JZUFRJT04gPj5cbiIpOyAKICAgIG91dDIgPSBwbGF5ZmFpcihvdXQsICJmYWlycGxheSIsIERFQ1JZUFRJT04sIDEpOyAKICAgIHByaW50ZigiJXNcbiIsIG91dDIpOyAKICAgIGZyZWUob3V0KTsKICAgIGZyZWUob3V0Mik7CiAgICByZXR1cm4gMDsKfQoKY2hhciAqcGxheWZhaXIoY29uc3QgY2hhciAqc3JjLCBjb25zdCBjaGFyICprZXksIGludCBkaXJlY3Rpb24sIGludCB2ZXJib3NlKQp7CiAgICBjaGFyIHRhYmxlW1RBQkxFU0laRV07CiAgICBjaGFyICplcyA9IChjaGFyICopIG1hbGxvYyhzdHJsZW4oc3JjKSArIDEpOwogICAgY2hhciAqZWsgPSAoY2hhciAqKSBtYWxsb2Moc3RybGVuKHNyYykgKyAxKTsKICAgIGNoYXIgKm91dCA9IE5VTEw7CiAgICAKICAgIGlmIChkaXJlY3Rpb24gIT0gRU5DUllQVElPTiAmJiBkaXJlY3Rpb24gIT0gREVDUllQVElPTikKICAgICAgICBnb3RvIGVycm9yOwogICAgaWYgKGVzID09IE5VTEwgfHwgZWsgPT0gTlVMTCkKICAgICAgICBnb3RvIGVycm9yOwoKICAgIGVrID0gZXh0cmFjdChlaywga2V5KTsKICAgIGlmICh2ZXJib3NlKQogICAgICAgIHByaW50Zigia2V5OlxuJXNcbiVzXG4iLCBrZXksIGVrKTsKICAgIG1ha2V0YWJsZSh0YWJsZSwga2V5KTsKICAgIGlmICh2ZXJib3NlKQogICAgICAgIHNob3d0YWJsZSh0YWJsZSk7CiAgICBlcyA9IGV4dHJhY3QoZXMsIHNyYyk7CiAgICBpZiAodmVyYm9zZSkKICAgICAgICAgICAgcHJpbnRmKCJzcmM6XG4lc1xuJXNcbiIsIHNyYywgZXMpOwogICAgb3V0ID0gKGNoYXIgKikgbWFsbG9jKHN0cmxlbihlcykgKiAyICsgMSk7CiAgICBpZiAob3V0ID09IE5VTEwpCiAgICAgICAgICAgIGdvdG8gZXJyb3I7CiAgICBpZiAoZGlyZWN0aW9uID09IEVOQ1JZUFRJT04pIHsKICAgICAgICBtYWtlcGFpcihvdXQsIGVzKTsKICAgIH0gZWxzZSB7CiAgICAgICAgc3RyY3B5KG91dCwgZXMpOwogICAgfQogICAgaWYgKHZlcmJvc2UpCiAgICAgICAgc2hvd3BhaXIob3V0KTsKICAgIHJlcGxhY2VfYWxsKG91dCwgdGFibGUsIGRpcmVjdGlvbik7CiAgICBpZiAodmVyYm9zZSkgewogICAgICAgIHNob3dwYWlyKG91dCk7CiAgICAgICAgZmZsdXNoKHN0ZG91dCk7CiAgICB9CiAgICBpZiAoZGlyZWN0aW9uID09IERFQ1JZUFRJT04pCiAgICAgICAgZGVsWChvdXQpOwogICAgcmV0dXJuIG91dDsKCmVycm9yOgogICAgZnJlZShlayk7CiAgICBmcmVlKGVzKTsKICAgIGZyZWUob3V0KTsKICAgIHJldHVybiBOVUxMOwp9Cgp2b2lkIG1ha2V0YWJsZShjaGFyICp0YWJsZSwgY29uc3QgY2hhciAqa2V5KQp7CiAgICBpbnQgaSwgajsKICAgIGNoYXIgdXNlZFtOTEVUVEVSXTsKICAgIHN0YXRpYyBjaGFyIGtbTUFYU1RSXTsKCiAgICBtZW1zZXQodGFibGUsICdcMCcsIFRBQkxFU0laRSk7CiAgICBtZW1zZXQodXNlZCwgMCwgc2l6ZW9mKHVzZWQpKTsKICAgIHVzZWRbJ0onIC0gJ0EnXSA9IDE7CiAgICBleHRyYWN0KGssIGtleSk7CiAgICBmb3IgKGkgPSAwLCBqID0gMDsga1tpXTsgaSsrKSB7CiAgICAgICAgaW50IGMgPSAoa1tpXSA9PSAnSicpID8gJ0knIDoga1tpXTsKICAgICAgICBpZiAodXNlZFtjIC0gJ0EnXSkKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgdXNlZFtjIC0gJ0EnXSA9IDE7CiAgICAgICAgdGFibGVbaisrXSA9IGM7CiAgICB9CiAgICBmb3IgKGkgPSAwOyBqIDwgVEFCTEVTSVpFOyBqKyspIHsKICAgICAgICB3aGlsZSAodXNlZFtpXSkKICAgICAgICAgICAgaSsrOwogICAgICAgIHRhYmxlW2pdID0gaSsrICsgJ0EnOwogICAgfQp9Cgp2b2lkIHNob3d0YWJsZShjaGFyICp0YWJsZSkKewogICAgaW50IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgVEFCTEVTSVpFOyBpKyspIHsKICAgICAgICBpbnQgYyA9IHRhYmxlW2ldOwogICAgICAgIGlmIChjID09ICdcMCcpCiAgICAgICAgICAgIGMgPSAnLic7CiAgICAgICAgcHJpbnRmKChpICUgV0lEVEgpID8gIiAlYyIgOiAiJWMiLCBjKTsKICAgICAgICBpZiAoKGkgKyAxKSAlIFdJRFRIID09IDApCiAgICAgICAgICAgIHByaW50ZigiXG4iKTsKICAgIH0KfQoKY2hhciAqZXh0cmFjdChjaGFyICp0bywgY29uc3QgY2hhciAqZnJvbSkKewogICAgY2hhciAqcmV0dmFsID0gdG87CiAgICBmb3IgKDsgKmZyb207IGZyb20rKykgCiAgICAgICAgaWYgKGlzYWxwaGEoKmZyb20pKQogICAgICAgICAgICAqdG8rKyA9IHRvdXBwZXIoKmZyb20pOwogICAgKnRvID0gJ1wwJzsKICAgIHJldHVybiByZXR2YWw7Cn0KCnZvaWQgbWFrZXBhaXIoY2hhciAqb3V0LCBjb25zdCBjaGFyICpwKQp7CiAgICB3aGlsZSAocCA9IHRvcGFpcihvdXQsIHApKQogICAgICAgIG91dCArPSAyOwogICAgb3V0ID0gJ1wwJzsKfQoKY29uc3QgY2hhciAqdG9wYWlyKGNoYXIgKnBhaXIsIGNvbnN0IGNoYXIgKnMpCnsKICAgIGlmICgqcyA9PSAnXDAnKQogICAgICAgIHJldHVybiBOVUxMOwogICAgcGFpclswXSA9ICpzKys7CiAgICBpZiAocGFpclswXSA9PSAqcyB8fCAqcyA9PSAnXDAnKQogICAgICAgIHBhaXJbMV0gPSAnWCc7CiAgICBlbHNlCiAgICAgICAgcGFpclsxXSA9ICpzKys7CgogICAgcmV0dXJuIHM7Cn0KCnZvaWQgc2hvd3BhaXIoY29uc3QgY2hhciAqcykKewogICAgaW50IGlzZmlyc3QgPSAxOwogICAgd2hpbGUgKCpzKSB7CiAgICAgICAgaWYgKCFpc2ZpcnN0KQogICAgICAgICAgICBwcmludGYoIi0iKTsKICAgICAgICBpc2ZpcnN0ID0gMDsKICAgICAgICBpZiAoc1sxXSA9PSAnXDAnKSB7CiAgICAgICAgICAgIC8qIOOBguOCiuOBiOOBquOBhOOBqOaAneOBhuOBjCAqLwogICAgICAgICAgICBwcmludGYoIiVjIiwgc1swXSk7CiAgICAgICAgICAgIHMrKzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwcmludGYoIiVjJWMiLCBzWzBdLCBzWzFdKTsKICAgICAgICAgICAgcyArPSAyOwogICAgICAgIH0KICAgIH0KICAgIHByaW50ZigiXG4iKTsKfQoKdm9pZCByZXBsYWNlX2FsbChjaGFyICpzLCBjb25zdCBjaGFyICp0YWJsZSwgaW50IGRlYykKewogICAgd2hpbGUgKHNbMF0gJiYgc1sxXSkgewogICAgICAgIHJlcGxhY2UocywgdGFibGUsIGRlYyk7CiAgICAgICAgcyArPSAyOwogICAgfQp9CgpjaGFyICpyZXBsYWNlKGNoYXIgKnBhaXIsIGNvbnN0IGNoYXIgKnRhYmxlLCBpbnQgZGVjKQp7CiAgICBpbnQgaSwgcG9zWzJdLCByb3dbMl0sIGNvbFsyXTsKICAgIGZvciAoaSA9IDA7IGkgPCAyOyBpKyspIHsKICAgICAgICBwb3NbaV0gPSBsb29rdXAodGFibGUsIHBhaXJbaV0pOwogICAgICAgIHJvd1tpXSA9IHBvc1tpXSAvIFdJRFRIOwogICAgICAgIGNvbFtpXSA9IHBvc1tpXSAlIFdJRFRIOwogICAgfQogICAgaWYgKHJvd1swXSA9PSAgcm93WzFdKSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykKICAgICAgICAgICAgY29sW2ldID0gKGNvbFtpXSArIGRlYykgJSBXSURUSDsKICAgIH0gZWxzZSBpZiAoY29sWzBdID09IGNvbFsxXSkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCAyOyBpKyspCiAgICAgICAgICAgIHJvd1tpXSA9IChyb3dbaV0gKyBkZWMpICUgV0lEVEg7CiAgICB9IGVsc2UgewogICAgICAgIGludCB0bXAgPSBjb2xbMF07CiAgICAgICAgY29sWzBdID0gY29sWzFdOwogICAgICAgIGNvbFsxXSA9IHRtcDsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCAyOyBpKyspCiAgICAgICAgcGFpcltpXSA9IHJvd2NvbHRvY2hhcih0YWJsZSwgcm93W2ldLCBjb2xbaV0pOwogICAgcmV0dXJuIHBhaXI7Cn0KCmludCBsb29rdXAoY29uc3QgY2hhciAqdGFibGUsIGludCBjKQp7CiAgICBjaGFyICpwID0gc3RyY2hyKHRhYmxlLCBjKTsKICAgIHJldHVybiBwIC0gdGFibGU7Cn0KCmludCByb3djb2x0b2NoYXIoY29uc3QgY2hhciAqdGFibGUsIGludCByb3csIGludCBjb2wpCnsKICAgIHJldHVybiB0YWJsZVtyb3cgKiBXSURUSCArIGNvbF07Cn0KCnZvaWQgZGVsWChjaGFyICpzKQp7CiAgICBjaGFyICp0ID0gczsKICAgIHdoaWxlIChzWzBdICYmIHNbMV0pIHsKICAgICAgICAqdCsrID0gKnMrKzsKICAgICAgICBpZiAoKnMgIT0gJ1gnKQogICAgICAgICAgICAqdCsrID0gKnM7CiAgICAgICAgcysrOwogICAgfQogICAgKnQgPSAnXDAnOwp9CgovKiBFTkQgT0YgRklMRSAqLw==