Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mcrypt_encrypt or mcrypt_decrypt is not working with basic html form

Tags:

php

mcrypt

Based on some examples on stackoverflow I've created a page which crpyts and decrypts the text that comes from html form. But somehow this is sometimes working sometimes not and usually it is not.

Why is this happening? Does htmlencode modifies the keys on posting proccess ? How do I fix that? Should I use base64 ?

<?php
$key_size = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM); // 16 bytes output


if($_POST){
    $iv = $_POST["iv"];
    $encryption_key = $_POST["key"];
    $string = $_POST["msg"];


    if($_POST["do"]=="encrypt"){
        echo "crypted";
        $result = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $string, MCRYPT_MODE_CFB, $iv);
    }else{
        echo "de-crypted";
        $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $string, MCRYPT_MODE_CFB, $iv);
    }

}

?>
<div class="main" id="main">
    <form method="POST" action="">
    <input type="text" value="<?php echo $iv; ?>" name="iv"/> <br/>
    <input type="text" value="<?php echo $encryption_key; ?>" name="key"/><br/>

    <textarea name="msg"><?php echo $result; ?></textarea><br/>
    <select name="do"><option>encrypt</option><option>decrypt</option></select><br/>
    <input type="submit" value="GO"/>
    </form>

</div>

live example can be found @ http://lab.ohshiftlabs.com/crypt/

like image 949
siniradam Avatar asked Nov 10 '22 12:11

siniradam


1 Answers

Here is some commented code that you may find useful. I think the main issue with your code is that the output from the 'mcrypt' routines are in 'binary' format and will need to be encoded in some sort of HTML 'safe' format. I have used base64.

The code has been tested.

<?php
/*
 * PHP 5.3.18 on windows XP
 *
 * I don't have open_ssl active from PHP so used MCRYPT_RAND for the salt.
 * It is adequate for this exercise.
 *
 * As the encoded SALT and encrypted output are binary code i have converted all
 * the output to Base64 encoding to ensure it is HTML safe.
 *
 * It selects the appropriate default action in the 'do' select list.
 *
 * There is a new 'salt' generated at each encryption and the user is prevented from
 * changing it by making the display field as 'readonly'. Normally this would be a 'hidden' field'.
 *
 */

$isEncrypted = null; // used to set default output options
                     // i like to pre-declare the script 'global' variables


$key_size = mcrypt_get_key_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CFB);


if($_POST){ // we have some input...

    $encryption_key = $_POST["key"];
    $string = $_POST["msg"]; // this may be base64 encoded...


    if($_POST["do"]=="encrypt"){
        $isEncrypted = true; // used to set defaults

        $iv = mcrypt_create_iv($iv_size,  MCRYPT_RAND); // new salt with each encryption
        $result = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $string, MCRYPT_MODE_CFB, $iv);
        $result = base64_encode($result); // $result is binary so encode as HTML safe.


    }else{
        $isEncrypted = false; // used to set defaults

        $iv = base64_decode($_POST["iv"]); // get current salt converted back to binary format
        $string = base64_decode($string); // convert encoded text back to binary string
        $result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $encryption_key, $string, MCRYPT_MODE_CFB, $iv);
    }
}else{ // no input so create something useful...
  $isEncrypted = false; // used to set default actions

  $result = 'enter text to encrypt...'; // sample text
  $iv = mcrypt_create_iv($iv_size,  MCRYPT_RAND); // new salt
  $encryption_key = substr('testing!' . uniqid() . '!testing', 0, $key_size);
}
?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Test Encryption with base64 encoding.</title>
  </head>

  <body>
    <div class="main" id="main">

        <!-- heading -->
        <strong><?php echo $isEncrypted ? 'Encrypted' : 'Decrypted'; ?></strong><br/>

        <form method="POST" action="">

            <!-- do not allow the user to change the salt by setting 'readonly' -->
            <input type="text" value="<?php echo base64_encode($iv); ?>" readonly name="iv"/> <br/>

            <!-- supply a suggested password but the user can change it -->
            <input type="text" value="<?php echo $encryption_key; ?>" name="key"/><br/>

            <!-- either show the encoded text as HTML safe string -->
            <!--- or show as plain text -->
            <textarea name="msg" ><?php echo $result; ?></textarea><br/>

            <!-- set the appropriate action as the default -->
            <select name="do">
              <option <?php echo $isEncrypted ? 'selected' : ''; ?>>decrypt</option>
              <option <?php echo $isEncrypted ? '' : 'selected'; ?>>encrypt</option>
            </select><br/>

            <input type="submit" value="GO"/>
        </form>
    </div>
  </body>
</html>
like image 55
Ryan Vincent Avatar answered Nov 14 '22 22:11

Ryan Vincent