#--------------------------------------------------------------------# # CryptoPad # Date Written: 07-Nov-2001 09:29:47 AM # Last Modified: 29-Nov-2002 10:03:08 AM # Author: Kurt Kincaid (sifukurt@yahoo.com) # Copyright (c) 2002, Kurt Kincaid # All Rights Reserved # # NOTICE: This package is free software and may be modified and/or # redistributed under the same terms as Perl itself. #--------------------------------------------------------------------# use Tk; use Tk::Dialog; use Tk::DialogBox; use Tk::Text; use Tk::FileSelect; use Tk::FileDialog; use Tk::Menu; use Tk::Menubutton; use Tk::widgets qw(Menu); use Tk::Checkbutton; use File::Butler; use File::Glob; use Crypt::RC4; use Crypt::GOST_PP; use Crypt::TripleDES; use Crypt::CBC; use Crypt::Rijndael_PP ':all'; use Crypt::RIPEMD160; use Crypt::PPDES; use Crypt::RC5; use Crypt::CBC; use Crypt::CAST5_PP; use URI::Escape; use Digest::MD2; use Digest::MD4; use Digest::MD5; use Digest::SHA1; use constant; use strict; use vars qw/ $temp_var $cipher $info $t $title $enc_type $mw $passphrase $ref $algorithm $f $fileName $ea $help $saveas $des $aes $hex $hex2 $hex3 $hex4 $hex5 $tripledes_header $tripledes_footer $rc4_header $rc4_footer $rc5_header $rc5_footer $cast5_header $cast5_footer $gost_header $gost_footer $m $fname $mod_date $FSref $ripemd $aes_header $aes_footer $VERSION $mm $tt $md2 $md4 $md5 $helptext $help_label $error @lines $sha /; $VERSION = "2.00"; $mod_date = "29-Nov-2002 10:03:08 AM"; $title = "CryptoPad v" . $VERSION; $rc4_header = "----- CryptoPad RC4 Encrypted Message: Begin -----\n"; $rc4_footer = "\n----- CryptoPad RC4 Encrypted Message: End -----"; $tripledes_header = "----- CryptoPad TripleDES Encrypted Message: Begin -----\n"; $tripledes_footer = "\n----- CryptoPad TripleDES Encrypted Message: End -----"; $aes_header = "----- CryptoPad AES (Rijndael) Encrypted Message: Begin -----\n"; $aes_footer = "\n----- CryptoPad AES (Rijndael) Encrypted Message: End -----"; $gost_header = "----- CryptoPad GOST Encrypted Message: Begin -----\n"; $gost_footer = "\n----- CryptoPad GOST Encrypted Message: End -----"; $rc5_header = "----- CryptoPad RC5 Encrypted Message: Begin -----\n"; $rc5_footer = "\n----- CryptoPad RC5 Encrypted Message: End -----"; $cast5_header = "----- CryptoPad CAST5 Encrypted Message: Begin -----\n"; $cast5_footer = "\n----- CryptoPad CAST5 Encrypted Message: End -----"; $mw = MainWindow->new; $mw->title( $title ); $m = $mw->Frame( -relief => 'groove', -bd => 2 )->pack( -side => 'top', -anchor => 'n', -fill => 'x' ); $m->Menubutton( -text => "File", -tearoff => 0, -menuitems => [ [ "command" => "New", -command => \&clear ], [ "command" => "Open", -command => \&OpenDocument ], [ "command" => "Save", -command => \&SaveDocument ], [ "command" => "Save As", -command => \&SaveAs ], [ "command" => "Exit", -command => sub { exit } ] ] )->pack( -side => 'left' ); $m->Menubutton( -text => "Help", -tearoff => 0, -menuitems => [ [ "command" => "Help...", -command => \&help ], [ "command" => "About...", -command => \&about ] ] )->pack( -side => 'left' ); $f = $mw->Frame->pack( -side => 'top', -fill => 'x' ); $ea = "ENCRYPTION ALGORITHM:"; $f->Menubutton( -text => "Choose Algorithm", -relief => 'raised', -tearoff => 0, -menuitems => [ [ "command" => "AES", -command => sub { $algorithm = "$ea AES"; $enc_type = "aes"; } ], [ "command" => "TripleDES", -command => sub { $algorithm = "$ea TripleDES"; $enc_type = "tripledes"; } ], [ "command" => "GOST", -command => sub { $algorithm = "$ea GOST"; $enc_type = "gost"; } ], [ "command" => "RC4", -command => sub { $algorithm = "$ea RC4"; $enc_type = "rc4"; } ], [ "command" => "RC5", -command => sub { $algorithm = "$ea RC5"; $enc_type = "rc5"; } ], [ "command" => "CAST5", -command => sub { $algorithm = "$ea CAST5"; $enc_type = "cast5"; } ] ] )->pack( -side => 'left' ); $f->Label( -text => "Passphrase:" )->pack( -side => 'left', -anchor => 'w' ); $f->Entry( -show => '*', -textvariable => \$passphrase )->pack( -side => 'left', -anchor => 'w', -fill => 'x', -expand => 1 ); $f->Button( -text => "Message Digest", -command => \&Digest )->pack( -side => 'right' ); $f->Button( -text => "Decrypt", -command => \&decrypt )->pack( -side => 'right', -anchor => 'e' ); $f->Button( -text => "Encrypt", -command => \&encrypt )->pack( -side => 'right', -anchor => 'e' ); if ( $algorithm eq "" ) { $algorithm = "No Encryption Algorithm Selected"; } $f->Button( -text => "Clear", -command => \&clear )->pack( -side => 'right', -anchor => 'e' ); $mw->Label( -textvariable => \$algorithm, -relief => 'ridge' )->pack( -side => 'top', -fill => 'x' ); $mw->Label( -textvariable => \$info, -relief => 'ridge' )->pack( -side => 'bottom', -fill => 'x' ); $t = $mw->Scrolled( "Text", -wrap => 'word', -scrollbars => 'e' )->pack( -side => 'bottom', -fill => 'both', -expand => 1 ); $info = $title; MainLoop; #--------------------------------------------------------------------# # Encryption Sub-Routines #--------------------------------------------------------------------# sub encrypt { if ( $enc_type eq "aes" ) { aes_encrypt(); } elsif ( $enc_type eq "tripledes" ) { tripledes_encrypt(); } elsif ( $enc_type eq "gost" ) { gost_encrypt(); } elsif ( $enc_type eq "rc4" ) { rc4_encrypt(); } elsif ( $enc_type eq "rc5" ) { rc5_encrypt(); } elsif ( $enc_type eq "cast5" ) { cast5_encrypt(); } elsif ( $enc_type eq "" ) { Error( "Error", "No encryption algorithm has been selected. Please select an algorithm and try again." ); } } sub decrypt { if ( $enc_type eq "aes" ) { aes_decrypt(); } elsif ( $enc_type eq "tripledes" ) { tripledes_decrypt(); } elsif ( $enc_type eq "gost" ) { gost_decrypt(); } elsif ( $enc_type eq "rc4" ) { rc4_decrypt(); } elsif ( $enc_type eq "rc5" ) { rc5_decrypt(); } elsif ( $enc_type eq "cast5" ) { cast5_decrypt(); } elsif ( $enc_type eq "" ) { Error( "Error", "No encryption algorithm has been selected. Please select an algorithm and try again." ); } } sub rc4_encrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $cipher = RC4( $passphrase, $temp_var ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $rc4_header . $cipher . $rc4_footer; $t->insert( "end", $cipher ); $info = $title; } } sub rc4_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $temp_var =~ s/$rc4_header//; $temp_var =~ s/$rc4_footer//; $temp_var =~ s/\n//g; $temp_var = uri_unescape( $temp_var ); $cipher = RC4( $passphrase, $temp_var ); chomp $cipher; $info = ""; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } sub rc5_encrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { my $ref = Crypt::RC5->new( $passphrase, 16 ); $cipher = $ref->encrypt( $temp_var ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $rc5_header . $cipher . $rc5_footer; $t->insert( "end", $cipher ); $info = $title; } } sub rc5_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $temp_var =~ s/$rc5_header//; $temp_var =~ s/$rc5_footer//; $temp_var =~ s/\n//g; $temp_var = uri_unescape( $temp_var ); my $ref = Crypt::RC5->new( $passphrase, 16 ); $cipher = $ref->decrypt( $temp_var ); chomp $cipher; $info = ""; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } sub cast5_encrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { my $ref = Crypt::CBC->new( { key => $passphrase, cipher => "CAST5_PP", } ); $cipher = $ref->encrypt( $temp_var ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $cast5_header . $cipher . $cast5_footer; $t->insert( "end", $cipher ); $info = $title; } } sub cast5_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $temp_var =~ s/$cast5_header//; $temp_var =~ s/$cast5_footer//; $temp_var =~ s/\n//g; $temp_var = uri_unescape( $temp_var ); my $ref = Crypt::CBC->new( { key => $passphrase, cipher => "CAST5_PP", } ); $cipher = $ref->decrypt( $temp_var ); chomp $cipher; $info = ""; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } sub tripledes_encrypt { $info = "Processing...."; my $des = new Crypt::TripleDES; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $cipher = $des->encrypt3( $temp_var, $passphrase ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $tripledes_header . $cipher . $tripledes_footer; $t->insert( "end", $cipher ); $info = $title; } } sub tripledes_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { my $des = new Crypt::TripleDES; $temp_var =~ s/$tripledes_header//; $temp_var =~ s/$tripledes_footer//; $temp_var =~ s/\n//g; $temp_var = uri_unescape( $temp_var ); $cipher = $des->decrypt3( $temp_var, $passphrase ); $cipher =~ s/\s*$//; chomp $cipher; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } sub aes_encrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $aes = new Crypt::CBC( $passphrase, 'Rijndael_PP' ); $cipher = $aes->encrypt( $temp_var ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $aes_header . $cipher . $aes_footer; $t->insert( "end", $cipher ); $info = $title; } } sub aes_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { @lines = split ( /\n/, $temp_var ); shift @lines; pop @lines; $temp_var = join ( "", @lines ); $temp_var = uri_unescape( $temp_var ); $aes = new Crypt::CBC( $passphrase, 'Rijndael_PP' ); $cipher = $aes->decrypt( $temp_var ); chomp $cipher; $info = ""; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } sub gost_encrypt { $info = "Processing...."; my $ref = Crypt::GOST_PP->new( $passphrase ); $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { $cipher = $ref->encrypt( $temp_var ); $info = ""; $t->delete( "1.0", "end" ); $cipher = uri_escape( $cipher ); $cipher =~ s/.{80}/$&\n/g; chomp $cipher; $cipher = $gost_header . $cipher . $gost_footer; $t->insert( "end", $cipher ); $info = $title; } } sub gost_decrypt { $info = "Processing...."; $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( Confirm() ) { my $ref = Crypt::GOST_PP->new( $passphrase ); $temp_var =~ s/$gost_header//; $temp_var =~ s/$gost_footer//; $temp_var =~ s/\n//g; $temp_var = uri_unescape( $temp_var ); $cipher = $ref->decrypt( $temp_var ); $cipher =~ s/\s*$//; chomp $cipher; $t->delete( "1.0", "end" ); $t->insert( "end", $cipher ); $info = $title; } } #--------------------------------------------------------------------# # End Encryption Sub-Routines #--------------------------------------------------------------------# sub clear { $t->delete( "1.0", "end" ); $passphrase = ""; $info = $title; $algorithm = "No Encryption Algorithm Selected"; $enc_type = ""; } sub about { $mw->Dialog( -title => "About...", -text => <<"END", -popover => $mw, -font => 'ansi' )->Show; $title Last Modified: $mod_date Copyright 2002 Kurt Kincaid. All rights reserved. CryptoPad is free software; you can redistribute it and/or modify it under the same terms as Perl itself. END } sub Digest { $info = "Generating Message Digest...."; $hex = Digest::MD5->new(); $temp_var = $t->get( "1.0", "end" ); chomp $temp_var; if ( $temp_var eq "" ) { $info = $title; return; } $hex->add( $temp_var ); $md5 = $hex->hexdigest(); $hex2 = Digest::SHA1->new(); $hex2->add( $temp_var ); $sha = $hex2->hexdigest(); $hex3 = Digest::MD4->new(); $hex3->add( $temp_var ); $md4 = $hex3->hexdigest(); $hex4 = Digest::MD2->new(); $hex4->add( $temp_var ); $md2 = $hex4->hexdigest(); $hex5 = Crypt::RIPEMD160->new(); $hex5->reset(); $hex5->add( $temp_var ); $ripemd = $hex5->hexdigest(); $mw->Dialog( -title => "Message Digest", -text => <<"END", -popover => $mw, -font => 'ansi' )->Show; [ SHA ] $sha [ MD5 ] $md5 [ MD4 ] $md4 [ MD2 ] $md2 [ RIPEMD-160 ] $ripemd END $info = $title; } sub OpenDocument { $FSref = $mw->FileSelect(); $fileName = $FSref->Show(); $temp_var = Butler( $fileName, "read" ); if ( !-e $fileName ) { $info = "Cannot open $fileName: $!"; return; } $t->delete( "1.0", "end" ); $t->insert( "end", $temp_var ); } sub SaveDocument { if ( $fileName eq "" ) { $saveas = $mw->FileDialog( -Title => 'Save As', -Create => 1 ); $saveas->Label( -text => "File Name: ", -relief => 'groove' ); $saveas->Entry( -width => 20, -textvariable => \$fileName ); $fname = $saveas->Show(); } $saveas->destroy(); $temp_var = $t->get( "1.0", "end" ); Butler( $fname, "write", \$temp_var ); $info = "$fname saved"; } sub SaveAs { undef $fileName; SaveDocument(); } sub help { $helptext = " $title Last Modified: $mod_date The encryption is accomplished with your choice of several encryption algorithms, TripleDES (the previous, interim NIST Data Encryption Standard), AES (also known as Advanced Encryption Standard, or Rijndael, after the authors, Vincent Rijmen and Joan Daemen, the current NIST Data Encryption Standard), GOST (a 64-bit block cipher with a 256-bit key, which was the encryption standard in the former Soviet Union) RC5, a fast block cipher by RSA Security Inc., RC4, which is a symmetrical stream cipher by RSA Security Inc, and the CAST5 block cipher, also known as CAST-128. It should be noted that to avoid complications with displaying meta-characters, the encyrpted output is escaped via URI::Escape. CryptoPad supports multiple rounds of encryption. For example, it is possible to encrypt your data with TripleDES, then with AES, then with RC4. Decryption would then be possible in the reverse order. The name of the encryption algorithm is shown to facilitate this. It is important to note that knowing which encryption algorithm was used in no way diminishes the security of the encryption. The Message Digests are generated with SHA1, MD5, MD4, and MD2 Message Digest algorithms by RSA Security Inc., and RIPEMD-160 by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel, of Katholieke Universiteit Leuven. A Message Digest (also known as \"fingerprint\") is a one-way encrypted hash function based on the content of the document. It is mathematically infeasible to have two documents with the same Message Digest, and even less likely that the document would say what you want it to say. As such, a Message Digest can be used to \"sign\" a document and verify that the contents of the document have not been altered, either by accident or design. "; $help_label = "$title Help"; $help = MainWindow->new(); $help->title( "Help" ); $mm = $help->Frame->pack( -side => 'top', -fill => 'x' ); $mm->Button( -text => "Close Window", -command => sub { $help->destroy() } )->pack( -side => 'right' ); $help->Label( -textvariable => \$help_label, -relief => 'ridge' )->pack( -side => 'bottom', -fill => 'x' ); $tt = $help->Scrolled( "Text", -width => 120, -wrap => 'word', -background => '#ffff88', -font => 'ansi', -scrollbars => 'e' )->pack( -side => 'bottom', -fill => 'both', -expand => 1 ); $tt->insert( "end", $helptext ); } sub Confirm { if ( $temp_var eq "" ) { return 0; } if ( length( $passphrase ) < 5 ) { Error( "Passphrase Error", "The passphrase must be at least 5 characters" ); return 0; } return 1; } sub Error { my $error; my( $et, $em ) = @_; $error = $mw->Dialog( -bitmap => 'error', -title => $et, -text => <<"END", -popover => $mw, -font => 'ansi' )->Show; $em END $info = $title; }