Junior Spellweaver
- Joined
- Nov 26, 2008
- Messages
- 196
- Reaction score
- 62
PLEASE NOTE: Due to laziness, the class isn't that clean and it could of been coded a lot better.
This is a class that uses the steganography technique to hide encrypted data within a bitmap image (.BMP).
Th3 class can hide the data very well in 24 or 32 bit RGB images.
The class could be used to hide the data in indexed color images, for instance of 256 colors, but that would require adding a few functions to deal with the modifications to the color palette.
The class implements 4 levels of bit stream encoding. Each level uses an increasing number of bits per each byte in the RGB pixel table. Therefore, the higher level of encoding will hold more bytes of data in the bitmap image.
Class:
Command Line example:
I'll edit this post once I done the webpage example.
This is a class that uses the steganography technique to hide encrypted data within a bitmap image (.BMP).
Th3 class can hide the data very well in 24 or 32 bit RGB images.
The class could be used to hide the data in indexed color images, for instance of 256 colors, but that would require adding a few functions to deal with the modifications to the color palette.
The class implements 4 levels of bit stream encoding. Each level uses an increasing number of bits per each byte in the RGB pixel table. Therefore, the higher level of encoding will hold more bytes of data in the bitmap image.
Class:
PHP:
<?php
class Steganography
{
var $m_errMsg;
var $m_dataCarrier;
var $m_data;
var $m_key;
var $m_outFile;
function __construct()
{
$this->m_errMsg = "";
$this->m_dataCarrier = "";
$this->m_data = "";
$this->m_key = "ExiledHeroBmpCrypt";
$this->m_outFile = "";
}
function Encrypt( $bmpFile, $indata, $key, $outFile, $level = 1)
{
if ( !file_exists( $bmpFile ) )
{
$this->m_errMsg = "The bitmap file '" . $bmpFile . "' was not found!";
return false;
}
if ( $indata == "" )
{
$this->m_errMsg = "No data to encrypt!";
return false;
}
if ( $outFile == "" )
{
$this->m_errMsg = "The output file was not specified!";
return false;
}
$this->m_dataCarrier = $bmpFile;
$this->m_data = $indata;
if ( $key != "" ) $this->m_key = $key;
$this->m_outFile = $outFile;
if ( $level == 1 )
return $this->_encrypt_1();
else if ( $level == 2 )
return $this->_encrypt_2();
else if ( $level == 3 )
return $this->_encrypt_3();
else if ( $level == 4 )
return $this->_encrypt_4();
else
{
$this->m_errMsg = "The encryption level is out of range!";
return false;
}
}
function Decrypt( $bmpFile, $key, $outFile = "" )
{
if ( !file_exists( $bmpFile ) )
{
$this->m_errMsg = "The bitmap file '" . $bmpFile . "' was not found!";
return false;
}
if ( $key != "" ) $this->m_key = $key;
$this->m_outFile = $outFile;
$this->m_dataCarrier = $bmpFile;
$this->m_data = file_get_contents( $this->m_dataCarrier );
if ( !$this->_get_encryption_info( $level, $cryptKey, $offset, $datSize ) )
return false;
$nbytes = ( $level == 1 ) ? 8 : ( ( $level == 2 ) ? 4 : ( ( $level == 3 ) ? 3 : 2 ) );
if ( $offset + $datSize * $nbytes > strlen( $this->m_data ) )
{
$this->m_errMsg = "The bitmap file '" . $this->m_dataCarrier . "' contains no encrypted data!" . $level . ", $nbytes";
return false;
}
$data = "";
for ( $i = 0; $i < $datSize; $i++ )
$data = chr( 0 );
for ( $i = $offset, $j = 0; $i < $offset + $datSize * $nbytes; $i += $nbytes, $j++ )
{
if ( $level == 1 )
{
for ( $k = 0, $n = 7; $k < 8; $k++, $n-- )
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i + $k ] ) & 1 ) << $n ) );
}
else if ( $level == 2 )
{
for ( $k = 0, $n = 6; $k < 4; $k++, $n -= 2 )
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i + $k ] ) & 3 ) << $n ) );
}
else if ( $level == 3 )
{
for ( $k = 0; $k < 3; $k++ )
{
if ( $k == 0 )
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i ] ) & 7 ) << 5 ) );
else if ( $k == 1 )
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i + 1 ] ) & 7 ) << 2 ) );
else
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ord( $this->m_data[ $i + 2 ] ) & 3 ) );
}
}
else if ( $level == 4 )
{
for ( $k = 0; $k < 2; $k++ )
{
if ( $k == 0 )
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i ] ) & 15 ) << 4 ) );
else
$data[ $j ] = chr( ord( $data[ $j ] ) | ( ( ord( $this->m_data[ $i + 1 ] ) & 15 ) );
}
}
}
for ( $i = 0, $j = 0; $i < $datSize; $i++, $j = ( $j + 1 ) % 32 )
$data[ $i ] = chr( ord( $data[ $i ] ) ^ ord( $cryptKey[ $j ] ) );
if ( $this->m_outFile != "" )
(
$fp = fopen( $this->m_outFile, "wb" );
fwrite( $fp, $data, $datSize );
fclose( $fp );
return true;
}
return $data;
}
function GetErrorMessage()
{
return "ERROR: " . $this->m_errMsg;
}
function _encrypt_1()
{
$bmpSize = filesize( $this->m_dataCarrier );
$datSize = strlen( $this->m_data );
$totalSize = ( 12 + $datSize ) * 8;
if ( ( $bmpSize - 55 ) < $totalSize )
{
$this->m_errMsg = "The bitmap file '" . $bmpFile . "' is too small to carry the input data!";
return false;
}
$cryptKey = md5( $this->m_key );
$cryptData = sprintf( "SCC1%08x", $datSize );
$bmpBuffer = file_get_contents( $this->m_dataCarrier );
for ( $i = 0, $j = 0; $i < $datSize; $i++, $j = ( $j + 1 ) % 32 )
$cryptData . = chr( ord( $this->m_data[ $i ] ) ^ ord( $cryptKey[ $j ] ) );
for ( $i = 0, $j = 55; $i < strlen( $cryptData ); $i++, $j += 8 )
{
$temp = sprintf( "%08s", decbin( ord( $cryptData[ $i ] ) ) );
for ( $k = 0; $k < 8; $k++ )
{
$bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) & 254 );
if ( $temp[ $k ] == '1' ) $bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) + 1 );
}
}
$fp = fopen($ this->m_outFile, "wb" );
fwrite( $fp, $bmpBuffer );
fclose( $fp );
return true;
}
function _encrypt_2()
{
$bmpSize = filesize( $this->m_dataCarrier );
$datSize = strlen( $this->m_data );
$totalSize = ( 12 + $datSize ) * 4;
if ( ( $bmpSize - 55 ) < $totalSize )
{
$this->m_errMsg = "The bitmap file '" . $this->m_dataCarrier . "' is too small to carry the input data!";
return false;
}
$cryptKey = md5( md5( $this->m_key ) );
$cryptData = sprintf( "SCC2%08x", $datSize );
$bmpBuffer = file_get_contents( $this->m_dataCarrier );
for ( $i = 0, $j = 0; $i < $datSize; $i++, $j = ( $j + 1 ) % 32 )
$cryptData .= chr( ord( $this->m_data[ $i ] ) ^ ord( $cryptKey[ $j ] ) );
for ( $i = 0, $j = 55; $i < strlen( $cryptData ); $i++, $j += 4 )
{
$temp = sprintf( "%08s", decbin( ord( $cryptData[ $i ] ) ) );
for ( $k = 0; $k < 4; $k++ )
{
$bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) & 252 );
$n = ( $temp[ $k * 2 ] == '1' ) ? 2 : 0;
$n += ( $temp[ $k * 2 + 1 ] == '1' ) ? 1 : 0;
if ( $n != 0 ) $bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) + $n );
}
}
$fp = fopen( $this->m_outFile, "wb" );
fwrite( $fp, $bmpBuffer );
fclose( $fp );
return true;
}
function _encrypt_3()
{
$bmpSize = filesize( $this->m_dataCarrier );
$datSize = strlen( $this->m_data );
$totalSize = ( 12 + $datSize ) * 3;
if ( ( $bmpSize - 55 ) < $totalSize )
{
$this->m_errMsg = "The bitmap file '" . $this->m_dataCarrier . "' is too small to carry the input data!";
return false;
}
$cryptKey = md5( md5( md5( $this->m_key ) ) );
$cryptData = sprintf( "SCC3%08x", $datSize );
$bmpBuffer = file_get_contents( $this->m_dataCarrier );
for ($i = 0, $j = 0; $i < $datSize; $i++, $j = ( $j + 1 ) % 32 )
$cryptData .= chr( ord( $this->m_data[ $i ] ) ^ ord( $cryptKey[ $j ] ) );
for ( $i = 0, $j = 55; $i < strlen( $cryptData ); $i++, $j += 3 )
{
$temp = sprintf( "%08s", decbin( ord( $cryptData[ $i ] ) ) );
for ( $k = 0; $k < 3; $k++ )
{
if ( $k != 2 )
{
$bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) & 248 );
$n = ( $temp[ $k * 3 ] == '1' ) ? 4 : 0;
$n += ( $temp[ $k * 3 + 1 ] == '1' ) ? 2 : 0;
$n += ( $temp[ $k * 3 + 2 ] == '1') ? 1 : 0;
if ( $n != 0 ) $bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) + $n );
}
else
{
$bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) & 252 );
$n = ( $temp[ $k * 3 ] == '1' ) ? 2 : 0;
$n += ( $temp[ $k * 3 + 1 ] == '1' ) ? 1 : 0;
if ( $n != 0 ) $bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) + $n );
}
}
}
$fp = fopen( $this->m_outFile, "wb" );
fwrite( $fp, $bmpBuffer );
fclose( $fp );
return true;
}
function _encrypt_4()
{
$bmpSize = filesize( $this->m_dataCarrier );
$datSize = strlen( $this->m_data );
$totalSize = ( 12 + $datSize ) * 2;
if ( ( $bmpSize - 55 ) < $totalSize )
{
$this->m_errMsg = "The bitmap file '" . $this->m_dataCarrier . "' is too small to carry the input data!";
return false;
}
$cryptKey = md5( md5( md5( md5( $this->m_key ) ) ) );
$cryptData = sprintf( "SCC4%08x", $datSize );
$bmpBuffer = file_get_contents( $this->m_dataCarrier );
for ( $i = 0, $j = 0; $i < $datSize; $i++, $j = ( $j + 1 ) % 32 )
$cryptData .= chr( ord( $this->m_data[ $i ] ) ^ ord( $cryptKey[ $j ] ) );
for ( $i = 0, $j = 55; $i < strlen( $cryptData ); $i++, $j += 2 )
{
$temp = sprintf( "%08s", decbin( ord( $cryptData[ $i ] ) ) );
for ( $k = 0; $k < 2; $k++ )
{
$bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) & 240 );
$n = ( $temp[ $k * 4 ] == '1' ) ? 8 : 0;
$n += ( $temp[ $k * 4 + 1] == '1' ) ? 4 : 0;
$n += ( $temp[ $k * 4 + 2 ] == '1' ) ? 2 : 0;
$n += ( $temp[ $k * 4 + 3] == '1' ) ? 1 : 0;
if ( $n != 0 ) $bmpBuffer[ $k + $j ] = chr( ord( $bmpBuffer[ $k + $j ] ) + $n );
}
}
$fp = fopen( $this->m_outFile, "wb" );
fwrite( $fp, $bmpBuffer );
fclose( $fp );
return true;
}
function _get_encryption_info( &$level, &$cryptKey, &$offset, &$datSize )
{
$cryptKey = md5( $this->m_key );
$cryptHeader = "";
for ( $i = 0; $i < 12; $i++ )
$cryptHeader = chr( 0 );
for ( $i = 55, $j = 7, $k = 0; $i < 151; $i++ )
{
$cryptHeader[ $k ] = chr( ord( $cryptHeader[ $k ] ) | ( ( ord( $this->m_data[ $i ] ) & 1 ) << $j ) );
$j--;
if ( $j < 0 )
{
$j = 7;
$k++;
}
}
if ( !strcmp( substr( $cryptHeader, 0, 4 ), "SCC1" ) )
{
sscanf( substr( $cryptHeader, 4, 8 ), "%x", $datSize );
$level = 1;
$offset = 151;
return true;
}
$cryptKey = md5( $cryptKey );
$cryptHeader = "";
for ( $i = 0; $i < 12; $i++ )
$cryptHeader = chr( 0 );
for ( $i = 55, $j = 6, $k = 0; $i < 103; $i++ )
{
$cryptHeader[ $k ] = chr( ord( $cryptHeader[ $k ] ) | ( ( ord( $this->m_data[ $i ] ) & 3 ) << $j ) );
$j -= 2;
if ( $j < 0 )
{
$j = 6;
$k++;
}
}
if ( !strcmp( substr( $cryptHeader, 0, 4 ), "SCC2" ) )
{
sscanf( substr( $cryptHeader, 4, 8 ), "%x", $datSize );
$level = 2;
$offset = 103;
return true;
}
$cryptKey = md5( $cryptKey );
$cryptHeader = "";
for ( $i = 0; $i < 12; $i++ )
$cryptHeader = chr( 0 );
for ( $i = 55, $j = 0; $i < 91; $i += 3, $j++ )
{
for ( $k = 0; $k < 3; $k++ )
{
if ( $k == 0 )
$cryptHeader[ $j ] = chr( ord( $cryptHeader[ $j ] ) | ( ( ord( $this->m_data[ $i ] ) & 7 ) << 5 ) );
else if ( $k == 1 )
$cryptHeader[ $j ] = chr( ord( $cryptHeader[ $j ] ) | ( ( ord( $this->m_data[ $i + 1 ] ) & 7 ) << 2 ) );
else
$cryptHeader[ $j ] = chr( ord( $cryptHeader[ $j ] ) | ( ord( $this->m_data[ $i + 2 ] ) & 3 ) );
}
}
if ( !strcmp( substr( $cryptHeader, 0, 4 ), "SCC3" ) )
{
sscanf( substr( $cryptHeader, 4, 8 ), "%x", $datSize );
$level = 3;
$offset = 91;
return true;
}
$cryptKey = md5( $cryptKey );
$cryptHeader = "";
for ( $i = 0; $i < 12; $i++ )
$cryptHeader = chr( 0 );
for ( $i = 55, $j = 0; $i < 79; $i += 2, $j++ )
{
for ( $k = 0; $k < 2; $k++ )
{
if ( $k == 0 )
$cryptHeader[ $j ] = chr( ord($cryptHeader[ $j ] ) | ( ( ord( $this->m_data[ $i ] ) & 15 ) << 4 ) );
else
$cryptHeader[ $j ] = chr( ord( $cryptHeader[ $j ] ) | ( ord( $this->m_data[ $i + 1 ] ) & 15 ) );
}
}
if ( !strcmp( substr( $cryptHeader, 0, 4 ), "SCC4" ) )
{
sscanf( substr( $cryptHeader, 4, 8 ), "%x", $datSize );
$level = 4;
$offset = 79;
return true;
}
$this->m_errMsg = "The bitmap file '" . $this->m_dataCarrier . "' contains no encrypted data!" . $cryptHeader;
return false;
}
}
/* EOF */
Command Line example:
PHP:
<?php
include("steganography.php");
$method = "";
if ( $argc > 1 )
{
if ( strcmp( $argv[ 1 ], "-e" ) == 0 ) $method = " Encrypt ";
else if ( strcmp( $argv[ 1 ], "-d" ) == 0 ) $method = " Decrypt ";
}
if ( $method == "Encrypt" && $argc >= 4 )
{
if ( !file_exists( $argv[ 3 ] ) )
{
echo "File '" . $argv[ 3 ] . "' was not found!\n";
exit();
}
$bmpEnc = new BmpCrypt();
$return = $bmpEnc->Encrypt( $argv[ 2 ], file_get_contents( $argv[ 3 ] ), ( $argc > 4 ) ? $argv[ 5 ] : "", $argv[ 4 ], ( $argc > 5 ) ? $argv[ 6 ] : 1 );
if ( $return == false ) echo $bmpEnc->GetErrorMessage() . "\n";
}
else if ( $method == "Decrypt" && $argc >= 3 )
{
$bmpEnc = new Steganography();
$return = $bmpEnc->Decrypt($argv[2], ($argc > 3) ? $argv[4] : "", $argv[3]);
if ( $return == false ) echo $bmpEnc->GetErrorMessage() . "\n";
}
else
{
echo "USAGE:\n";
echo " To encrypt data and hide it in a bitmap file:\n";
echo " php -f Steg_CmdLine_Example.php -e bitmap_file data_file output_file [key] [level]\n";
echo " To decrypt data and recover it from a bitmap file:\n";
echo " php -f Steg_CmdLine_Example.php -d bitmap_file output_file [key]\n";
}
/* EOF */
I'll edit this post once I done the webpage example.
Last edited: