#!/usr/bin/env perl # 123.pl v1.0 # Copyright (C) by Ace 2005-2006 < danielakesson@gmail.com > use Time::localtime; #use Digest::MD5 qw(md5 md5_hex md5_base64); use Digest::SHA1 qw(sha1 sha1_hex sha1_base64); use Getopt::Long; use Crypt::CBC; use File::stat; use File::Glob; use Carp::Heavy; use Crypt::Blowfish; use Crypt::Rijndael; use strict; use warnings; #use diagnostics; my $USE_CIPHER = 'Rijndael'; # Blowfish not as good.. (?) my $BASE_DIR = "."; my $REVERSE; my $RENAME; my $ENCRYPT_KEY = ""; my $DECRYPT_KEY = ""; my $ENCRYPT_FILE; my $DECRYPT_FILE; my $KEY; my $PARANOID; my $DECRYPT_OK = 1; my $SHOW_COUNTER = 1; if (@ARGV < 1) { #my @catalogerstat; #if (-e "123.pl") { # @catalogerstat = stat("123.pl"); #} #elsif (-e "123") { # @catalogerstat = stat("123"); #} #elsif (-e "123.exe") { # @catalogerstat = stat("123.exe"); #} #my $modtime = $catalogerstat[9]; #my $temp_time = localtime($modtime); #my $time = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $temp_time->year+1900, $temp_time->mon+1, $temp_time->mday, $temp_time->hour, $temp_time->min, $temp_time->sec; #print "\n123 v[$time]\n"; #print "--------------------------\n"; print "\n123 v1.0 (2005-10-04)\n"; print "--------\n"; print qq/ Usage: 123 [Options] This utility is for renaming files to a "unique" filename, and also save this unique sha1 hex of the filename(s) and the original name next to it in a file (named files.123). Furthermore, this "files.123" file's content can also be encrypted and decrypted. This utility also has the ability to encrypt and decrypt the files using AES. If a file named key.123 is located in the same dir as this application, its content is used as a . Note also that when encrypting files, this app does NOT delete the original files! Not yet anyway... [Options] --reverse - Change from the md5hex mentioned in .123 to the original filename. --rename - Rename files aswell. --encrypt[=] - Encrypt the .123 file's content aswell using the provided. --decrypt[=] - Tells the application that the .123 file's content is encrypted, and try to decypt this first by using the provided. -[-]c[=] - Encrypt file(s). -[-]d[=] - Decrypt file(s). --paranoid - Using this option it first encrypts the files before doing sha1hex on their names (this, if creating the .123 file). Otherwise (if option --reverse is used), this will lastly decrypt the file(s). --key[=] - Used with --c, --d and --paranoid option. Examples: #1) 123 --rename . - This will create the files.123 file, and also rename the files in the current directory. #2) 123 --rename --reverse . - This will change the files back to their original name. ("Undo" the above). #3) 123 --rename --encrypt=secret_pass . - This will do as #1, but also encrypt the "files.123"'s content using "secret_pass" as a key. #4) 123 -c=*.zip --key=secret_pass . - This will encrypt all .zip files in the current directory with the key "secret_pass". Note: Any 32 length filename is ----- ignored, aswell as "key.123" and "files.123". Use at your own risk! (although I have taken a few precautions to make heavy loss quite hard) Have fun, (C) 2005-2006 by Ace < danielakesson\@gmail.com > /; exit; } else { $BASE_DIR = @ARGV[@ARGV - 1]; # This MUST be before GetOptions, since that one pops(?) from ARGV my $result = GetOptions ("reverse" => \$REVERSE, "rename" => \$RENAME, "encrypt=s" => \$ENCRYPT_KEY, "decrypt=s" => \$DECRYPT_KEY, "c=s" => \$ENCRYPT_FILE, "d=s" => \$DECRYPT_FILE, "key=s" => \$KEY, "paranoid" => \$PARANOID ); # flag if ($BASE_DIR =~ /^\-/ or length($BASE_DIR) < 1) { print "No path entered. Using current directory.\n"; $BASE_DIR = "."; } } if ($REVERSE && length($ENCRYPT_KEY) > 0) { print "\nReverse option enabled. Did you mean no --reverse and --encrypt= or\n"; print "--reverse and --decrypt==?\n"; exit; } elsif (!$REVERSE && length($DECRYPT_KEY) > 0) { print "\nReverse option disabled. Did you mean --reverse and --decrypt= or\n"; print "no --reverse and --encrypt==?\n"; exit; } print "Using path: " . $BASE_DIR . "\n\n"; if (-e "key.123") { print "Using key in the key.123 file.\n\n"; open KEY, "./key.123"; $KEY = ; close KEY; } if (defined($ENCRYPT_FILE)) { my @all_matches = glob $ENCRYPT_FILE; my @files = grep {-f} @all_matches; foreach (@files) { &encryptFile($_); print "\n"; } } elsif (defined($DECRYPT_FILE)) { my @all_matches = glob $DECRYPT_FILE; my @files = grep {-f} @all_matches; foreach (@files) { &decryptFile($_); print "\n"; } } elsif (!$REVERSE) { # CREATE the .123 if (-e "files.123") { print "\nfiles.123 already exits! I do not want to screw with possible current\n"; print "conversion to .123 of files, so please remove this file if it's of no use.\n"; print "Maybe you wanted to do --reverse?\n"; exit; } opendir(DIR, $BASE_DIR) or die ("Cannot open current directory!"); my @contents = readdir(DIR); closedir(DIR); my @files = grep {-f} @contents; my $data = ""; foreach (@files) { next if (m/files\.123/); next if (m/^[0-9a-f]{32}$/); next if (m/^123$/); next if (m/^123\.pl$/); next if (m/^key\.123$/); next if (m/^123\.exe$/); #print $_ . " " . md5_hex($_) . "\n"; if ($PARANOID) { &encryptFile($_); $_ .= ".3nc"; } #my $hex_version = md5_hex($_); my $hex_version = sha1_hex($_); if ($RENAME) { if (rename ($_, $hex_version)) { print $hex_version . " <= " . $_ . "\n"; $data .= $hex_version . " = " . $_ . "\n"; } else { print "Error renaming $_. $!\n"; } } else { print $hex_version . " <= " . $_ . "\n"; $data .= $hex_version . " = " . $_ . "\n"; } #print "\n"; } if (length($data) < 1) { print "Nothing to be done. Empty dir?\n"; exit; } if (length($ENCRYPT_KEY) > 0) { my $cipher = Crypt::CBC->new( -key => $ENCRYPT_KEY, -cipher => $USE_CIPHER, #-iv => '$KJh#(}q', -padding => 'space', #-add_header => 1, -salt => 0 ); $data = $cipher->encrypt_hex($data); print "\nData encrypted.\n"; } open FILE, ">files.123"; print FILE $data; close FILE; if (!$RENAME) { print "\nNo files renamed.\n"; } if (-e "files.123") { print "\nfiles.123 created. You better not delete this file now if\nyou want your files back!"; } } else { # GET original filenames from the .123. open(FILE123, $BASE_DIR . "/files.123") or (print("Cannot open " . $BASE_DIR ."/files.123\n") && exit); my @lines = ; close FILE123; if (length($DECRYPT_KEY) > 0) { my $cipher = Crypt::CBC->new( -key => $DECRYPT_KEY, -cipher => $USE_CIPHER, #-iv => '$KJh#(}q', -padding => 'space', -add_header => 1, -salt => 0 ); #$cipher->key($DECRYPT_KEY); my $decrypted_data = eval { $cipher->decrypt_hex(join('', @lines)) }; if (defined($decrypted_data)) { @lines = split /\n/, $decrypted_data; } else { print "\nData really encrypted?\n"; exit; } } foreach (@lines) { $_ =~ s/\n//g; $_ =~ s/\r//g; #my ($md5_hex, $org_file_name) = split (/=+/, $_); my ($sha1_hex, $org_file_name) = split (/=+/, $_); if (!defined($org_file_name)) { print "files.123 not recognized. "; if (defined($DECRYPT_KEY) > 0 && length($DECRYPT_KEY) > 0) { print "Wrong password maybe?"; } else { print "Encrypted maybe? (use --decrypt[=] option)"; } exit; } $sha1_hex =~ s/^ +//g; $sha1_hex =~ s/ +$//g; $org_file_name =~ s/^ +//g; $org_file_name =~ s/ +$//g; if ($RENAME) { if (rename ($sha1_hex, $org_file_name)) { print $sha1_hex . " => " . $org_file_name . "\n"; } else { if (-e $org_file_name) { print "Already renamed? Found: " . $org_file_name . "\n"; } else { print "Error renaming $sha1_hex: $!\n"; } } } else { print $sha1_hex . " => " . $org_file_name . "\n"; } if ($PARANOID) { &decryptFile($org_file_name); print "\n"; } } if (!$RENAME) { print "\nNo files renamed.\n"; } else { if ($DECRYPT_OK) { print "\nYou may now remove the files.123 file!\n"; } } } sub encryptFile { my $filename = shift; if (!defined($KEY)) { print "Please provide an encryption key using the --key[=] option.\n"; exit; } return if (substr($filename, -4, 4) eq ".3nc"); return if ($filename eq "files.123"); return if ($filename eq "key.123"); return if ($filename eq "123"); return if ($filename eq "123.exe"); if (!-e "./$filename") { print "$filename not found.\n"; return; } if (-e "./$filename.3nc") { print "$filename.3nc exists already.\n"; return; } my $stat = stat($filename); my $file_size = $stat->size; $| = 1; print "Encrypting $filename...\n"; $| = 0; my $cipher = Crypt::CBC->new( -key => $KEY, -cipher => $USE_CIPHER, #-'iv' => '$KJh#(}q', -padding => 'space', -add_header => 1 ); $cipher->start('encrypting'); open(ORGINAL, "<./$filename"); open(ENCRYPTED, ">./$filename.3nc"); binmode ORGINAL; binmode ENCRYPTED; my $buffer_size = 1024; my $on = 0; while (sysread(ORGINAL, my $buffer, $buffer_size)) { syswrite(ENCRYPTED, $cipher->crypt($buffer)); $on += $buffer_size; if ($SHOW_COUNTER) { my $text = &getNice($on, 2) . " / " . &getNice($file_size, 2) . " " . sprintf("%d%%", ($on / $file_size) * 100) . " "; print $text; for (my $i=0; $i < length($text); ++$i) { print chr(0x08); } } #print (ENCRYPTED $cipher->crypt($buffer)); } syswrite(ENCRYPTED, $cipher->finish); $| = 0; close ENCRYPTED; close ORGINAL; utime $stat->atime, $stat->mtime, "./$filename.3nc"; # Put the date back to original! print "\n"; } sub decryptFile { my $filename = shift; print "Working with: " . $filename . "\n"; if (!defined($KEY)) { print "Please provide a decryption key.\n"; exit; } if (substr($filename, -4, 4) eq ".3nc") { $filename = substr($filename, 0, length($filename) - 4); } return if ($filename eq "files.123"); return if ($filename eq "key.123"); return if ($filename eq "123"); return if ($filename eq "123.exe"); if (!-e "./$filename.3nc") { print "$filename.3nc not found on harddrive. --rename may have to be turned on. Expected the encrypted to end with .3nc.\n"; $DECRYPT_OK = 0; return; } if (-e "./$filename") { print "$filename exists already. Will not decrypt over existing.\n"; $DECRYPT_OK = 0; return; } my $stat = stat($filename . ".3nc"); my $file_size = $stat->size; $| = 1; print "Decrypting $filename.3nc...\n"; $| = 0; my $cipher = Crypt::CBC->new( -key => $KEY, -cipher => $USE_CIPHER, #-'iv' => '$KJh#(}q', -padding => 'space', -add_header => 1 ); $cipher->start('decrypting'); open(ENCRYPTED, "<./$filename.3nc"); open(DECRYPTED, ">./$filename"); binmode ENCRYPTED; binmode DECRYPTED; my $buffer_size = 1024; my $on = 0; while (sysread(ENCRYPTED, my $buffer, $buffer_size)) { syswrite(DECRYPTED, $cipher->crypt($buffer)); $on += $buffer_size; if ($SHOW_COUNTER) { my $text = &getNice($on, 2) . " / " . &getNice($file_size, 2) . " " . sprintf("%d%%", ($on / $file_size) * 100) . " "; print $text; for (my $i=0; $i < length($text); ++$i) { print chr(0x08); } } } syswrite(DECRYPTED, $cipher->finish); close DECRYPTED; close ENCRYPTED; utime $stat->atime, $stat->mtime, "./$filename"; # Put the date back to original! print "\n$filename decrypted.\n"; } sub getNice { #my ($self)=@_; my $bytes = shift; my $decimals = shift; my $kb=1024; my $mb=1048576; my $gb=1073741824; my $tb=1099511627776; if ($bytes > $gb) { return round($bytes / $gb, $decimals) . "Gb"; } elsif ($bytes > $mb) { return round($bytes / $mb, $decimals) . "Mb"; } elsif ($bytes > $kb) { return round($bytes / $kb, $decimals) . "Kb"; } else { return $bytes . "b"; } } sub round { my ($number,$decimals) = @_; #my $x = Math::BigFloat->new($number); #my $rounded = $x->fround(0); #return $rounded; if ($decimals > 0) { return substr($number+("0."."0"x$decimals."5"), 0, $decimals+length(int($number))+1); } return substr($number+("05"), 0, $decimals+length(int($number))+1); }