PHP Crypter dengan Passphrase Key

Simple PHP program untuk encode dan decode data menggunakan passphrase dengan Rijndael 256 bit encryption.

Minggu lalu ceritanya iseng2 bikin script buat encrypt file. Nah karena eterbatasan waktu, ane belom sempet utak atik lagi. Inspirasinya dari PGP yang pake pertukaran public key, bedanya ini pertukarannya pake passphrase keynya. Mungkin ada yg berminat buat ngembangin.

  • Tool Name : PHP Crypter
  • Program Language : PHP
  • Environment : CLI
  • Tested On : PHP 5.4.4 (built: Jun 13 2012)
  • Linux Requirement : PHP mcrypt library
  • Description : Encode or decode data using specific key passphrase with Rijndael256 bit encryption.
  • Repo: https://github.com/ditatompel/PHP-Crypter.
  1<?php
  2/**
  3 * PHP Crypter
  4 *
  5 * This program used to encode or decode data using specific key passphrase
  6 * with Rijndael 256 bit encryption.
  7 *
  8 * Still very early release, just for fun coding purpose :)
  9 *
 10 * LICENSE :
 11 * This program is free software; you can redistribute it and/or modify it
 12 * under the terms of the GNU General Public License version 2 as published by
 13 * the Free Software Foundation.
 14 * This program is distributed in the hope that it will be useful, but WITHOUT
 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 17 * more details.
 18 *
 19 * @author Christian Ditaputratama <[email protected]>
 20 *
 21 * Usage :
 22 * new phpCrypter($argv);
 23 */
 24
 25class phpCrypter
 26{
 27    const V = 0.01; // this is the program version
 28    const PASSPHARSE = "di7atomp3l"; // change this
 29    const EXT = '.tpl'; // file extention result
 30    private $verbose = FALSE; // verbose mode. Default false = off
 31    private $decrypt = FALSE; // default mode = encrypt
 32    private $key = NULL; // property for custom key or use PASSPHARSE constant
 33
 34    /* Contructor. Set up arguments, print banner and execute main program. */
 35    function __construct($opts) {
 36        $cmd = $this->arguments($opts);
 37        print $this->banner();
 38
 39        /**
 40         * Required parameter is "d" for decrypt OR "e" for encrypt.
 41         * Stop the program if both option has been set.
 42         */
 43        if ( array_key_exists('d', $cmd) && array_key_exists('e', $cmd) ) {
 44            print "\n" . $this->crot("[!] Double method, please choose 1 beetween decrypt / encrypt", 'red') . "\n";
 45            print $this->usage($cmd['input'][0]);
 46            exit;
 47        }
 48
 49        /* Print help screen then exit if file param is not set */
 50        if ( !array_key_exists('file', $cmd) ) {
 51            print $this->usage($cmd['input'][0]);
 52            exit;
 53        }
 54
 55        if ( array_key_exists('d', $cmd) ) $this->decrypt = TRUE;
 56        if ( array_key_exists('v', $cmd) ) $this->verbose = TRUE;
 57
 58        if ( array_key_exists('key', $cmd) ) $this->key = is_null ($cmd['key']) ? self::PASSPHARSE :  $cmd['key'];
 59        else $this->key = self::PASSPHARSE;
 60
 61        if ( $this->cekData($cmd['file']) ) {
 62            if ( !array_key_exists('o', $cmd) )
 63                print "\n" . $this->crypter($this->readData($cmd['file']));
 64            else
 65                $this->writeData($cmd['file'] . self::EXT, $this->crypter($this->readData($cmd['file'])));
 66        }
 67        else
 68            print $this->crot(" [!] Data is not exist or is not wirtable!", 'red') . "\n";
 69    }
 70
 71    /**
 72     * The cool banner
 73     * @return string
 74     */
 75    function banner() {
 76        $msg = " ________________________________________________________\n";
 77        $msg .= "|         mm                                             |\n";
 78        $msg .= "|      /^(  )^\   PHP Crypter " .  $this->crot('v' . self::V,'cyan') . "                      |\n";
 79        $msg .= "|      \,(..),/   Encode / decode data using specific    |\n";
 80        $msg .= "|        V~~V     key passphrase with " .  $this->crot('Rijndael 256','red') . " bit   |\n";
 81        $msg .= "|      encryption. Coded by [email protected]    |\n";
 82        $msg .= "|________________________________________________________|\n\n";
 83        return $msg;
 84    }
 85
 86    /**
 87     * Help Screen
 88     * @return string
 89     */
 90    function usage($file) {
 91        $msg = "\nUsage : ";
 92        $msg .= $file . " --file=[file] [option(s)]\n";
 93        $msg .= "Example : ";
 94        $msg .= $file . " --file=/home/dit/private.txt --key=\"RAHASIA\" -dvo\n";
 95        $msg .= "Option(s) :\n";
 96        $msg .= " -d : Decrypt | -e : Encrypt (required)\n";
 97        $msg .= " --key=[key] : passphrase key to encrypt / decrypt file\n";
 98        $msg .= " -v : verbose mode, print all output to terminal\n";
 99        $msg .= " -o : write output to [file].tpl\n";
100        return $msg;
101    }
102
103    /**
104     * The Crypter
105     * Encrypt / Decrypt the data using PHP mcrypt rinjadael 256 ECB mode.
106     * @return string
107     */
108    function crypter($str=NULL) {
109        // notify user if the program cannot encrypt/decrypt empty string
110        if( is_null($str) ) {
111            print $this->crot(" [!] Cannot encrypt/decrypt null string", 'red') . "\n";
112            return $str;
113        }
114
115        $mode = 'encrypt';
116        if ( $this->decrypt ) $mode = 'decrypt';
117        if ( $this->verbose ) {
118            print " [*] Trying to " . $this->crot($mode, 'purple') . " file...\n";
119            print " [+] Using " . $this->crot($this->key,'l_cyan') . " as passpharse key\n";
120        }
121        $data = NULL;
122        $header = "-----BEGIN PHP CRYPTER BLOCK-----\n";
123        $header .= "Version: " . self::V . " ([email protected])\n\n";
124        $footer = "\n";
125        $footer .= "-----END PHP CRYPTER BLOCK-----\n";
126        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
127        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
128        $key_size = mcrypt_get_key_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
129        $key = substr($this->key,0,$key_size);
130
131        if( $this->decrypt )
132            $return = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_ECB, $iv);
133        else {
134            $strings = str_split(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_ECB, $iv)), 65);
135            foreach ( $strings as $string )
136                $data .= $string . "\n";
137            $return = $header . $data . $footer;
138        }
139        return $return;
140    }
141
142    /**
143     * Human readable file size function
144     * @return string
145     */
146    function xfilesize($size) {
147        switch ( $size ) {
148            case $size > 1099511627776 :
149                $size = number_format($size / 1099511627776, 2, ".", ",") . " TB";
150            break;
151            case $size > 1073741824 :
152                $size = number_format($size / 1073741824, 2, ".", ",") . " GB";
153            break;
154            case $size > 1048576 :
155                $size = number_format($size / 1048576, 2, ".", ",") . " MB";
156            break;
157            case $size > 1024 :
158                $size = number_format($size / 1024, 2, ".", ",") . " kB";
159            break;
160            default :
161                $size = number_format($size, 2, ".", ",") . " Bytes";
162        }
163        return $size;
164    }
165
166    /**
167     * Check target data
168     * @return bool. TRUE if file exists and readable.
169     */
170    function cekData ($file) {
171        if ( $this->verbose ) print "\n [*] Checking " . $file . " if it's exists..\n";
172        if ( !is_file($file) || !is_readable($file) )
173            return false;
174        else {
175            if ( $this->verbose )
176                print $this->crot(" [+] File " . $file . " is exists and readable..", 'l_green') . "\n";
177            return true;
178        }
179    }
180
181    /**
182     * Read target data
183     * @return string.
184     */
185    function readData ($file) {
186        $msg = NULL;
187        $read = fopen($file, "r");
188        $msg .= fread($read, filesize($file));
189        if ( $this->verbose )
190            print " [*] File size is " . $this->xfilesize(filesize($file)) ."\n";
191        if ( $this->decrypt ) {
192            $msg = explode("\n\n", $msg);
193            $msg = str_replace("\n", '', $msg[1]);
194        }
195        fclose($read);
196        return $msg;
197    }
198
199    /**
200     * Create file and and write data to the file.
201     * @return bool
202     */
203    function writeData ($file, $data) {
204        $fh = fopen($file, 'wx+');
205        fwrite($fh, $data);
206        fclose($fh);
207        if ( $this->verbose )
208            print $this->crot(" [*] Data has been writed to " . $file, 'l_green') . "\n";
209        return true;
210    }
211
212
213    /**
214     * Make UNIX like parameter command.
215     * This function from losbrutos and modified by earomero. Thankyou. =)
216     * @author losbrutos <[email protected]>
217     * @author earomero <[email protected]>
218     * @param array argv
219     * @return array
220     */
221    function arguments($argv) {
222        $_ARG = array();
223        foreach ($argv as $arg) {
224            if (preg_match('#^-{1,2}([a-zA-Z0-9]*)=?(.*)$#', $arg, $matches)) {
225                $key = $matches[1];
226                switch ($matches[2]) {
227                    case '':
228                    case 'true':
229                    $arg = true;
230                    break;
231                    case 'false':
232                    $arg = false;
233                    break;
234                    default:
235                    $arg = $matches[2];
236                }
237
238                // make unix like -afd == -a -f -d
239                if(preg_match("/^-([a-zA-Z0-9]+)/", $matches[0], $match)) {
240                    $string = $match[1];
241                    for($i=0; strlen($string) > $i; $i++) {
242                        $_ARG[$string[$i]] = true;
243                    }
244                } else {
245                    $_ARG[$key] = $arg;
246                }
247            } else {
248                $_ARG['input'][] = $arg;
249            }
250        }
251        return $_ARG;
252    }
253
254    /**
255     * Function to print colorful output to terminal.
256     * @param string    $string    String to be colored.
257     * @param string    $fontColor The available color
258     *        Available color :
259     *                  black, dark_gray, blue, green, l_green, cyan, l_cyan
260     *                  red, l_red, purple, l_purple, brown, yellow, l_gray,
261     *                  white.
262     * @return string
263     */
264    private function crot($string, $fontColor=NULL) {
265        switch ($fontColor) {
266            case 'black' : $color = '0;30'; break;
267            case 'dark_gray' : $color = '1;30'; break;
268            case 'blue' : $color = '0;34'; break;
269            case 'l_blue' : $color = '1;34'; break;
270            case 'green' : $color = '0;32'; break;
271            case 'l_green' : $color = '1;32'; break;
272            case 'cyan' : $color = '0;36'; break;
273            case 'l_cyan' : $color = '0;36'; break;
274            case 'red' : $color = '0;31'; break;
275            case 'l_red' : $color = '1;31'; break;
276            case 'purple' : $color = '0;35'; break;
277            case 'l_purple' : $color = '1;35'; break;
278            case 'brown' : $color = '0;33'; break;
279            case 'yellow' : $color = '1;33'; break;
280            case 'l_gray' : $color = '0;37'; break;
281            case 'white' : $color = '1;37'; break;
282        }
283        $colored_string = "";
284        $colored_string .= "\033[" . $color . "m";
285        $colored_string .=  $string . "\033[0m";
286        return $colored_string;
287    }
288}
289?>

Contoh exec.php :

1<?php
2set_time_limit(0);
3ini_set('memory_limit', '-1'); // use this for large data file
4require_once('phpCrypter.php');
5new phpCrypter($argv);
6?>
1Usage : file.php --file=[file] [option(s)]
2Option(s) :
3-d : Decrypt | -e : Encrypt (required)
4--key=[key] : passphrase key to encrypt / decrypt file
5-v : verbose mode, print all output to terminal
6-o : write output to [file].tpl

Contoh melakukan encrypt

1/home/dit/PHP-Crypter/exec.php --file=/home/dit/private.txt --key="RAHASIA" -evo

atau

1/home/dit/PHP-Crypter/exec.php -e -v -o --file=/home/dit/private.txt --key="RAHASIA"

Dari contoh command di atas :

dia akan mengenkripsi file private.txt pada direktori /home/dit dengan passphrase key RAHASIA lalu menuliskan hasil enkripsi ke file private.txt.tpl di direktori yg sama.

Contoh melakukan decrypt

1/home/dit/PHP-Crypter/exec.php --file=/home/dit/private.txt.tpl --key="RAHASIA" -dvo

atau

1/home/dit/PHP-Crypter/exec.php -d -v -o --file=/home/dit/private.txt.tpl --key="RAHASIA"

Dia akan mendekrip file private.txt.tpl pada direktori /home/dit dengan passphrase key RAHASIA lalu menuliskan hasil dekripsi ke file private.txt.tpl.tpl di direktori yg sama.

Note : Jika option “o” tidak di set maka dia akan menampilkan output ke terminal, bukan ke file.

TODO

  • Ketika mengenkripsi file, dia akan membuat file baru dengan penambahan extension .tpl. Sedangkan akan lebih baik jika ketika mendekrip file akan kembali ke file extension semula.
  • Belum bisa mengetahui apakah file tersebut benar2 terdekrip atau tidak.