/*---------------------------------------------------------*/ /* */ /* Public Key Encryption Demonstration */ /* Copyright (c) 1998 by David Canright */ /* */ /*---------------------------------------------------------*/ #define Uses_TKeys #define Uses_TApplication #define Uses_TEvent #define Uses_TRect #define Uses_TDialog #define Uses_TFileDialog #define Uses_TButton #define Uses_TMenuBar #define Uses_TSubMenu #define Uses_TMenuItem #define Uses_TStatusLine #define Uses_TStatusItem #define Uses_TStatusDef #define Uses_TDeskTop #define Uses_MsgBox #define Uses_TChDirDialog #define Uses_THistory #define Uses_TWindow #define Uses_TInputLine #include #include "PKE.h" #include #include #include #include // for ifstream #include // for puts() etc #include // for isspace() const char *helpFile = "pkehelp.txt"; const char *helpMathFile = "pkehow.txt"; const char *helpAboutFile = "pkeabout.txt"; // for error messages: char errorMsg[MAXSIZE]; ostrstream errstr( errorMsg, sizeof(errorMsg) ); char buf[maxLineLength]; // all-purpose line buffer PKEApp::PKEApp() : TProgInit( &PKEApp::initStatusLine, &PKEApp::initMenuBar, &PKEApp::initDeskTop ) { // Clear clipboard clipPriv = clipPub = clipMod = 0; // No help at start helpWin[0] = helpWin[1] = helpWin[2] = 0; kwinNum = 0; mwinNum = 0; } PKEApp::~PKEApp(){} void PKEApp::newKeyWin(const char *fileName) { TKeyWindow *p; TRect r(2,1, 2+13+numWidth, 1+5 ); int err=0; r.a.x += 2*(kwinNum%10); r.a.y += (kwinNum%10); r.b.x += 2*(kwinNum%10); r.b.y += (kwinNum%10); p = new TKeyWindow( r, fileName, this ); if ( fileName[3]==' ' ) // kludge to check "New Key" err = p->generate(); else err = p->readFile(fileName); if ( err ) { destroy(p); return; } deskTop->insert( validView(p) ); kwinNum++; } void PKEApp::keyfileOpen() { char fileName[MAXSIZE]; strcpy( fileName, "*.KEY" ); if( execDialog( new TFileDialog( "*.KEY", "Open file", "~N~ame", fdOpenButton, 100 ), fileName) != cmCancel ) { for( int i=0, j=0; fileName[i]; i++ ) if ( fileName[i] == '\\' || fileName[i] == ':' ) j = i+1; newKeyWin( fileName+j ); } } void PKEApp::newMsgWin(const char *fileName) { TMsgWindow *p; TRect r(30,1, 30+msgWidth+4, 1+7 ); int err=0; r.a.x += 2*(mwinNum%10); r.a.y += (mwinNum%10); r.b.x += 2*(mwinNum%10); r.b.y += (mwinNum%10); p = new TMsgWindow( r, fileName, this ); if ( fileName[3]!=' ' ) // kludge to check "New Key" err = p->readFile(fileName); if ( err ) { destroy(p); return; } deskTop->insert( validView(p) ); mwinNum++; } void PKEApp::msgfileOpen() { char fileName[MAXSIZE]; strcpy( fileName, "*.MES" ); if( execDialog( new TFileDialog( "*.MES", "Open file", "~N~ame", fdOpenButton, 100 ), fileName) != cmCancel ) { for( int i=0, j=0; fileName[i]; i++ ) if ( fileName[i] == '\\' || fileName[i] == ':' ) j = i+1; newMsgWin( fileName+j ); } } void PKEApp::doSuspend() { suspend(); } void PKEApp::doResume() { resume(); } void PKEApp::doHelp(int type, const char *aTitle, const char *fileName) { TView *p; p = deskTop->last; if ( p != 0 && helpWin[type] != 0 ) do { p = p->next; if ( p == helpWin[type] ) { helpWin[type]->select(); //deskTop->setCurrent( p, normalSelect ); return; } } while ( p != deskTop->last ); helpWin[type] = new THelpWindow( TRect(5,3,75,20), aTitle, fileName ); deskTop->insert( validView( helpWin[type] ) ); } void PKEApp::handleEvent(TEvent& event) { TApplication::handleEvent(event); switch (event.what) { case evCommand: switch (event.message.command) { case cmOpenKeyWin: keyfileOpen(); break; case cmNewKeyWin: newKeyWin("New Key"); break; case cmOpenMsgWin: msgfileOpen(); break; case cmNewMsgWin: newMsgWin("New Message"); break; case cmDoHelp: doHelp(0,"Help Window",helpFile); break; case cmDoHelpMath: doHelp(1,"How PKE Works",helpMathFile); break; case cmDoHelpAbout: doHelp(2,"About PKE Demo",helpAboutFile); break; case cmSaveKeyWin: case cmCopyKey: messageBox("Please select a Key Window first.", mfWarning | mfOKButton); break; case cmSaveMsgWin: case cmEncrMsgWin: case cmDecrMsgWin: case cmDbEnMsgWin: case cmDbDeMsgWin: messageBox("Please select a Message Window first.", mfWarning | mfOKButton); break; case cmEncrFile: encryptFile(); break; case cmDecrFile: decryptFile(); break; case cmDbEnFile: dblencryptFile(); break; case cmDbDeFile: dbldecryptFile(); default : return; } break; default: return; } clearEvent(event); } TMenuBar *PKEApp::initMenuBar(TRect r) { r.b.y = r.a.y + 1; return new TMenuBar( r, *new TSubMenu( "~F~ile", hcNoContext ) + *new TMenuItem( "New ~K~ey", cmNewKeyWin, kbAltK, hcNoContext, "Alt-K" ) + *new TMenuItem( "~S~ave Key", cmSaveKeyWin, kbAltS, hcNoContext, "Alt-S" ) + *new TMenuItem( "~O~pen Key", cmOpenKeyWin, kbAltO, hcNoContext, "Alt-O" ) + newLine() + *new TMenuItem( "New ~M~sg", cmNewMsgWin, kbAltM, hcNoContext, "Alt-M" ) + *new TMenuItem( "Sa~v~e Msg", cmSaveMsgWin, kbAltV, hcNoContext, "Alt-V" ) + *new TMenuItem( "O~p~en Msg", cmOpenMsgWin, kbAltP, hcNoContext, "Alt-P" ) + newLine() + *new TMenuItem( "E~x~it", cmQuit, kbAltX, hcNoContext, "Alt-X" ) + *new TSubMenu( "~C~ode", hcNoContext ) + *new TMenuItem( "C~l~ip Key", cmCopyKey, kbAltL, hcNoContext, "Alt-L" ) + newLine() + *new TMenuItem( "~E~ncode Msg", cmEncrMsgWin, kbAltE, hcNoContext, "Alt-E" ) + *new TMenuItem( "~D~ecode Msg", cmDecrMsgWin, kbAltD, hcNoContext, "Alt-D" ) + *new TSubMenu( "~A~dvanced", hcNoContext ) + *new TMenuItem( "Double ~E~ncode", cmDbEnMsgWin, kbAltB, hcNoContext, "Alt-B" ) + *new TMenuItem( "Double ~D~ecode", cmDbDeMsgWin, kbAltU, hcNoContext, "Alt-U" ) + newLine() + *new TMenuItem( "Encode F~i~le", cmEncrFile, kbF7, hcNoContext, "F7" ) + *new TMenuItem( "Decode Fi~l~e", cmDecrFile, kbF8, hcNoContext, "F8" ) + newLine() + *new TMenuItem( "D~o~uble Encode File", cmDbEnFile, kbF9, hcNoContext, "F9" ) + *new TMenuItem( "Do~u~ble Decode File", cmDbDeFile, kbF10, hcNoContext, "F10" ) + *new TSubMenu( "~W~indows", hcNoContext ) + *new TMenuItem( "~M~ove", cmResize, kbCtrlF5, hcNoContext, "Ctrl-F5" ) + *new TMenuItem( "~N~ext", cmNext, kbF6, hcNoContext, "F6" ) + *new TMenuItem( "~P~revious", cmPrev, kbShiftF6, hcNoContext, "Shift-F6" ) + *new TMenuItem( "~C~lose",cmClose, kbAltF3, hcNoContext, "Alt-F3",0 ) + *new TSubMenu( "~H~elp", hcNoContext ) + *new TMenuItem( "~H~elp Window", cmDoHelp, kbF1, hcNoContext, "F1" ) + *new TMenuItem( "How ~P~KE Works", cmDoHelpMath, kbF2, hcNoContext, "F2" ) + *new TMenuItem( "A~b~out PKE", cmDoHelpAbout, kbF3, hcNoContext, "F3" ) ); } TStatusLine *PKEApp::initStatusLine(TRect r) { r.a.y = r.b.y - 1; return new TStatusLine( r, *new TStatusDef( 0, 0xFFFF ) + *new TStatusItem( "~F1~ Help", kbF1, cmDoHelp ) + *new TStatusItem( "~Alt-K~ New Key", kbAltK, cmNewKeyWin ) + *new TStatusItem( "~Alt-M~ New Message", kbAltM, cmNewMsgWin ) + // *new TStatusItem( "~F10~ Menu", kbF10, cmMenu ) + *new TStatusItem( "~Alt-X~ Exit", kbAltX, cmQuit ) + *new TStatusItem( 0, kbAltF3, cmClose ) + *new TStatusItem( 0, kbCtrlF5, cmResize ) + *new TStatusItem( 0, kbF5, cmZoom) + *new TStatusItem("", kbF6, cmNext) ); } void PKEApp::outOfMemory() { messageBox("Out of memory.", mfError | mfOKButton); } int main() { PKEApp myApp; randomize(); myApp.run(); return 0; } ushort execDialog( TDialog *d, void *data ) { TView *p = TProgram::application->validView( d ); if( p == 0 ) return cmCancel; else { if( data != 0 ) p->setData( data ); ushort result = TProgram::deskTop->execView( p ); if( result != cmCancel && data != 0 ) p->getData( data ); TObject::destroy( p ); return result; } } /******** File Encryption ***********/ const int minchar = 0X20, cbase = 0X5F, coff = 0X01; extern int c2n(char c); extern int n2c(int c); extern int mypowmod(int m, int e, int n0); void PKEApp::encryptFile() { char fileName[MAXSIZE]; strcpy( fileName, "*.TXT" ); if( execDialog( new TFileDialog( "*.TXT", "File to Encode", "~N~ame", fdOpenButton, 100 ), fileName) == cmCancel ) return; ifstream fileIn( fileName ); if( !fileIn ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } strcpy( fileName, "*.PKE" ); if( execDialog( new TFileDialog( "*.PKE", "Destination File", "~N~ame", fdOKButton, 100 ), fileName) == cmCancel ) return; ofstream fileOut( fileName ); if( !fileOut ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } int key=0, mod=0; TKeyDialog *pd = new TKeyDialog( "Enter Key & Modulus",mod,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key); pd->modin->getData(buf); sscanf(buf,"%d",&mod); } } destroy( pd ); if (key <= 1 || mod <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } // Now ready to encrypt int ic, is=0; char c,mc[2],sc[3],spc[MAXSIZE]; spc[0]=0; int m, s=mod; // here know mod & key pos. sc[2] = n2c(s); s /= cbase; sc[1] = n2c(s); s /= cbase; sc[0] = n2c(s) + coff; fileOut.write(sc,3); while ( ( ic = fileIn.get() ) != EOF ) { while ( ic != ' ' && isspace(ic) ) { fileOut.put((char)ic); ic = fileIn.get(); } c = ic; m = c2n(c) * cbase; ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; m += c2n(c); // c2n guarantees pos. s = mypowmod(m,key,mod); sc[2] = n2c(s); s /= cbase; sc[1] = n2c(s); s /= cbase; sc[0] = n2c(s) + coff; if ( is ) { fileOut.put(sc[0]); fileOut.write(spc,is); fileOut.write(sc+1,2); is = 0; } else fileOut.write(sc,3); } fileOut.flush(); } void PKEApp::decryptFile() { char fileName[MAXSIZE]; strcpy( fileName, "*.PKE" ); if( execDialog( new TFileDialog( "*.PKE", "File to Decode", "~N~ame", fdOpenButton, 100 ), fileName) == cmCancel ) return; ifstream fileIn( fileName ); if( !fileIn ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } strcpy( fileName, "*.TXT" ); if( execDialog( new TFileDialog( "*.TXT", "Destination File", "~N~ame", fdOKButton, 100 ), fileName) == cmCancel ) return; ofstream fileOut( fileName ); if( !fileOut ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } // First get key int key=0; int ic, is=0; char c,mc[2],sc[3],spc[MAXSIZE]; spc[0]=0; int m, s, mod; c = fileIn.get(); s = (c2n(c - coff))& 0X0003 ; // to guarantee pos c = fileIn.get(); s = s*cbase + c2n(c); c = fileIn.get(); s = s*cbase + c2n(c); mod = s; if ( mod <= 1 ) { // this check prob. redund. messageBox("Invalid secret!", mfError | mfOKButton); return; } TKeyDialog *pd = new TKeyDialog( "Enter Other Key",mod,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key); pd->modin->getData(buf); sscanf(buf,"%d",&mod); } } destroy( pd ); if (key <= 1 || mod <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } // Now ready to decrypt while ( ( ic = fileIn.get() ) != EOF ) { while ( ic != ' ' && isspace(ic) ) { fileOut.put((char)ic); ic = fileIn.get(); } c = ic; s = (c2n(c - coff))& 0X0003 ; // to guarantee pos ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; s = s*cbase + c2n(c); ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; s = s*cbase + c2n(c); m = mypowmod(s,key,mod); mc[1] = n2c(m); m /= cbase; mc[0] = n2c(m); fileOut.put(mc[0]); if ( is ) { fileOut.write(spc,is); is = 0; } fileOut.put(mc[1]); } // if(mc[1] == ' ') { // long endpos = fileOut.tellp(); // fileOut.seekp(endpos-1); // fileOut.put('X'); // } // did not work fileOut.flush(); } void PKEApp::dblencryptFile() { char fileName[MAXSIZE]; strcpy( fileName, "*.TXT" ); if( execDialog( new TFileDialog( "*.TXT", "File to Encode", "~N~ame", fdOpenButton, 100 ), fileName) == cmCancel ) return; ifstream fileIn( fileName ); if( !fileIn ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } strcpy( fileName, "*.PKE" ); if( execDialog( new TFileDialog( "*.PKE", "Destination File", "~N~ame", fdOKButton, 100 ), fileName) == cmCancel ) return; ofstream fileOut( fileName ); if( !fileOut ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } int key1=0, mod1=0, key2=0, mod2=0; TKeyDialog *pd = new TKeyDialog( "INNER Key & Modulus",mod1,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key1); pd->modin->getData(buf); sscanf(buf,"%d",&mod1); } } destroy( pd ); if (key1 <= 1 || mod1 <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } pd = new TKeyDialog( "OUTER Key & Modulus",mod2,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key2); pd->modin->getData(buf); sscanf(buf,"%d",&mod2); } } destroy( pd ); if (key2 <= 1 || mod2 <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } // Now ready to encrypt int ic, is=0; char c,mc[2],sc[3],spc[MAXSIZE]; spc[0]=0; int m=mod1, r, s=mod2; // here know mod & key pos. sc[2] = n2c(s); s /= cbase; sc[1] = n2c(s); s /= cbase; sc[0] = n2c(s) + coff; fileOut.write(sc,3); r = m/mod2; m = m % mod2; s = mypowmod(m,key2,mod2); sc[2] = n2c(s); s /= cbase; sc[1] = n2c(s); s /= cbase; sc[0] = n2c(r*4 + s) + coff; fileOut.write(sc,3); while ( ( ic = fileIn.get() ) != EOF ) { while ( ic != ' ' && isspace(ic) ) { fileOut.put((char)ic); ic = fileIn.get(); } c = ic; m = c2n(c) * cbase; ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; m += c2n(c); // c2n guarantees pos. m = mypowmod(m,key1,mod1); r = m/mod2; m = m % mod2; s = mypowmod(m,key2,mod2); sc[2] = n2c(s); s /= cbase; sc[1] = n2c(s); s /= cbase; sc[0] = n2c(r*4 + s) + coff; if ( is ) { fileOut.put(sc[0]); fileOut.write(spc,is); fileOut.write(sc+1,2); is = 0; } else fileOut.write(sc,3); } fileOut.flush(); } void PKEApp::dbldecryptFile() { char fileName[MAXSIZE]; strcpy( fileName, "*.PKE" ); if( execDialog( new TFileDialog( "*.PKE", "File to Decode", "~N~ame", fdOpenButton, 100 ), fileName) == cmCancel ) return; ifstream fileIn( fileName ); if( !fileIn ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } strcpy( fileName, "*.TXT" ); if( execDialog( new TFileDialog( "*.TXT", "Destination File", "~N~ame", fdOKButton, 100 ), fileName) == cmCancel ) return; ofstream fileOut( fileName ); if( !fileOut ) { messageBox("Invalid file name...", mfError | mfOKButton); return; } // First get key int key1=0, mod1=0, key2=0, mod2=0; int ic, is=0; char c,mc[2],sc[3],spc[MAXSIZE]; spc[0]=0; int m, s, r; c = fileIn.get(); s = (c2n(c - coff))& 0X0003 ; // to guarantee pos c = fileIn.get(); s = s*cbase + c2n(c); c = fileIn.get(); s = s*cbase + c2n(c); mod2 = s; if ( mod2 <= 1 ) { // this check prob. redund. messageBox("Invalid secret!", mfError | mfOKButton); return; } TKeyDialog *pd = new TKeyDialog( "OUTER Key & Modulus",mod2,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key2); pd->modin->getData(buf); sscanf(buf,"%d",&mod2); } } destroy( pd ); if (key2 <= 1 || mod2 <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } c = fileIn.get(); s = (c2n(c - coff))& 0X000F ; // to guarantee pos r = s/4; s = s%4; c = fileIn.get(); s = s*cbase + c2n(c); c = fileIn.get(); s = s*cbase + c2n(c); m = mypowmod(s,key2,mod2); mod1 = m + r*mod2; pd = new TKeyDialog( "INNER Key & Modulus",mod1,this ); if( pd ) { ushort control = deskTop->execView( pd ); if( control == cmCancel ) return;{ pd->keyin->getData(buf); sscanf(buf,"%d",&key1); pd->modin->getData(buf); sscanf(buf,"%d",&mod1); } } destroy( pd ); if (key1 <= 1 || mod1 <= 1) { messageBox("Invalid key or modulus", mfError | mfOKButton); return; } // Now ready to decrypt while ( ( ic = fileIn.get() ) != EOF ) { while ( ic != ' ' && isspace(ic) ) { fileOut.put((char)ic); ic = fileIn.get(); } c = ic; s = (c2n(c - coff))& 0X000F ; // to guarantee pos r = s/4; s = s%4; s = (c2n(c - coff))& 0X0003 ; // to guarantee pos ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; s = s*cbase + c2n(c); ic = fileIn.get(); while ( ic != ' ' && isspace(ic) && is < MAXSIZE-1) { spc[is++] = ic; ic = fileIn.get(); } c = ic; s = s*cbase + c2n(c); m = mypowmod(s,key2,mod2); m = m + r*mod2; m = mypowmod(m,key1,mod1); mc[1] = n2c(m); m /= cbase; mc[0] = n2c(m); fileOut.put(mc[0]); if ( is ) { fileOut.write(spc,is); is = 0; } fileOut.put(mc[1]); } fileOut.flush(); }