The code below is a wrapper class around the AES-128 implementation at http://www.phpclasses.org/browse/package/3650.html and the MCrypt extension. It use the MCrypt extension if it is enabled and use the pure PHP AES-128 class otherwise.
001 |
function hex2bin( $hex ) { |
002 |
003 |
return pack ( "H*" , $hex ); |
004 |
005 |
} |
006 |
007 |
class Cipher { |
008 |
009 |
public $password ; |
010 |
011 |
public $plainText ; |
012 |
013 |
public $encryptedText ; |
014 |
015 |
public $iv ; |
016 |
017 |
public $mode ; |
018 |
019 |
const AES_128_ECB = "AES_128_ECB" ; |
020 |
021 |
const AES_128_CBC = "AES_128_CBC" ; |
022 |
023 |
public function __construct() { |
024 |
025 |
$this ->mode = self::AES_128_ECB; |
026 |
027 |
} |
028 |
029 |
public function encrypt( $useSuppliedIV = false) { |
030 |
031 |
if (! $this ->plainText) { |
032 |
return "" ; |
033 |
} |
034 |
035 |
switch ( $this ->mode) { |
036 |
037 |
case self::AES_128_ECB : |
038 |
case self::AES_128_CBC : |
039 |
if ( strlen ( $this ->password) > 16) { |
040 |
$this ->password = substr ( $this ->password, 0, 16); |
041 |
} |
042 |
break ; |
043 |
044 |
} |
045 |
046 |
if (function_exists ( "mcrypt_module_open" ) && function_exists ( "mcrypt_create_iv" ) && function_exists ( "mcrypt_generic_init" ) && function_exists ( "mcrypt_generic" ) && function_exists ( "mcrypt_generic_deinit" )) { |
047 |
048 |
switch ( $this ->mode) { |
049 |
050 |
case self::AES_128_ECB : |
051 |
$td = mcrypt_module_open ( 'rijndael-128' , '' , 'ecb' , '' ); |
052 |
break ; |
053 |
054 |
case self::AES_128_CBC : |
055 |
$td = mcrypt_module_open ( 'rijndael-128' , '' , 'cbc' , '' ); |
056 |
break ; |
057 |
058 |
} |
059 |
060 |
if ( $useSuppliedIV ) { |
061 |
if ( strlen ( $this ->iv ) != mcrypt_enc_get_iv_size ( $td )) { |
062 |
return null; |
063 |
} |
064 |
} else { |
065 |
$this ->iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND ); |
066 |
} |
067 |
068 |
mcrypt_generic_init ( $td , $this ->password, $this ->iv ); |
069 |
$this ->encryptedText = mcrypt_generic ( $td , $this ->plainText ); |
070 |
mcrypt_generic_deinit ( $td ); |
071 |
072 |
} else { |
073 |
074 |
$aes = new AES128 ( ); |
075 |
$key = $aes ->makeKey ( $this ->password ); |
076 |
077 |
$plainTextArray = str_split ( $this ->plainText, 16 ); |
078 |
079 |
$lastIndex = count ( $plainTextArray ) - 1; |
080 |
if ( strlen ( $plainTextArray [ $lastIndex ]) != 16) { |
081 |
082 |
for ( $i = strlen ( $plainTextArray [ $lastIndex ]); $i < 16; $i ++) { |
083 |
$plainTextArray [ $lastIndex ] .= chr (0); |
084 |
} |
085 |
086 |
} |
087 |
088 |
$this ->encryptedText = "" ; |
089 |
090 |
if ( $useSuppliedIV ) { |
091 |
if ( strlen ( $this ->iv ) != 16) { |
092 |
return null; |
093 |
} |
094 |
} else { |
095 |
$this ->iv = "" ; |
096 |
for ( $i = 0; $i < 16; $i ++) { |
097 |
$this ->iv .= chr (rand(0, 255)); |
098 |
} |
099 |
} |
100 |
101 |
switch ( $this ->mode) { |
102 |
103 |
case self::AES_128_ECB : |
104 |
105 |
for ( $i = 0; $i < count ( $plainTextArray ); $i ++) { |
106 |
$this ->encryptedText .= $aes ->blockEncrypt ( $plainTextArray [ $i ], $key ); |
107 |
} |
108 |
109 |
break ; |
110 |
111 |
case self::AES_128_CBC : |
112 |
$encryptedTextArray = array (); |
113 |
for ( $i = 0; $i < count ( $plainTextArray ); $i ++) { |
114 |
if ( $i == 0) { |
115 |
$input = $this ->iv ^ $plainTextArray [ $i ]; |
116 |
} else { |
117 |
$input = $encryptedTextArray [ $i - 1] ^ $plainTextArray [ $i ]; |
118 |
} |
119 |
120 |
$encryptedTextArray [ $i ] = $aes ->blockEncrypt ( $input , $key ); |
121 |
} |
122 |
123 |
$this ->encryptedText = join( "" , $encryptedTextArray ); |
124 |
125 |
break ; |
126 |
} |
127 |
} |
128 |
129 |
} |
130 |
131 |
public function decrypt() { |
132 |
if (! $this ->encryptedText) { |
133 |
return "" ; |
134 |
} |
135 |
136 |
if (function_exists ( "mcrypt_module_open" ) && function_exists ( "mcrypt_create_iv" ) && function_exists ( "mcrypt_enc_get_iv_size" ) && function_exists ( "mcrypt_generic_init" ) && function_exists ( "mcrypt_generic" ) && function_exists ( "mcrypt_generic_deinit" )) { |
137 |
138 |
switch ( $this ->mode) { |
139 |
140 |
case self::AES_128_ECB : |
141 |
$td = mcrypt_module_open ( 'rijndael-128' , '' , 'ecb' , '' ); |
142 |
$this ->iv = mcrypt_create_iv ( mcrypt_enc_get_iv_size ( $td ), MCRYPT_RAND ); |
143 |
break ; |
144 |
145 |
case self::AES_128_CBC : |
146 |
$td = mcrypt_module_open ( 'rijndael-128' , '' , 'cbc' , '' ); |
147 |
if ( strlen ( $this ->iv ) != mcrypt_enc_get_iv_size ( $td )) { |
148 |
return null; |
149 |
} |
150 |
break ; |
151 |
152 |
} |
153 |
154 |
mcrypt_generic_init ( $td , $this ->password, $this ->iv ); |
155 |
$this ->plainText = mdecrypt_generic ( $td , $this ->encryptedText ); |
156 |
mcrypt_generic_deinit ( $td ); |
157 |
158 |
} else { |
159 |
160 |
$aes = new AES128 ( ); |
161 |
$key = $aes ->makeKey ( $this ->password ); |
162 |
163 |
$encryptedTextArray = str_split ( bin2hex ( $this ->encryptedText ), 32 ); |
164 |
165 |
$this ->plainText = "" ; |
166 |
167 |
switch ( $this ->mode) { |
168 |
169 |
case self::AES_128_ECB : |
170 |
for ( $i = 0; $i < count ( $encryptedTextArray ); $i ++) { |
171 |
$this ->plainText .= $aes ->blockDecrypt ( hex2bin ( $encryptedTextArray [ $i ] ), $key ); |
172 |
} |
173 |
break ; |
174 |
175 |
case self::AES_128_CBC : |
176 |
if ( strlen ( $this ->iv ) != 16) { |
177 |
return null; |
178 |
} |
179 |
180 |
$plainTextArray = array (); |
181 |
for ( $i = 0; $i < count ( $encryptedTextArray ); $i ++) { |
182 |
$output = $aes ->blockDecrypt ( hex2bin( $encryptedTextArray [ $i ]), $key ); |
183 |
184 |
if ( $i == 0) { |
185 |
$plainTextArray [ $i ] = $this ->iv ^ $output ; |
186 |
} else { |
187 |
$plainTextArray [ $i ] = hex2bin( $encryptedTextArray [ $i - 1]) ^ $output ; |
188 |
} |
189 |
190 |
$this ->plainText = join( "" , $plainTextArray ); |
191 |
} |
192 |
break ; |
193 |
194 |
} |
195 |
196 |
} |
197 |
198 |
$this ->plainText = trim ( $this ->plainText ); |
199 |
200 |
} |
201 |
202 |
} |
Save the code above to cipher.php. In addition to this, you will need the AES128.php file from http://www.phpclasses.org/browse/package/3650.html
Here’s an example of AES-128 ECB mode encryption:
01 |
include_once ( "AES128.php" ); |
02 |
include_once ( "cipher.php" ); |
03 |
04 |
$encrypt = new Cipher; |
05 |
$encrypt ->password = "password" ; |
06 |
$encrypt ->plainText = "this is a very long string that we would like to encrypt using AES128" ; |
07 |
$encrypt ->encrypt(); |
08 |
09 |
echo "encrypted: " . bin2hex( $encrypt ->encryptedText ) . "<br>" ; |
10 |
11 |
$decrypt = new Cipher; |
12 |
$decrypt ->password = "password" ; |
13 |
$decrypt ->encryptedText = $encrypt ->encryptedText; |
14 |
$decrypt ->decrypt(); |
15 |
16 |
echo "plain text: " . $decrypt ->plainText; |
The default mode is ECB. So, we don’t need to set $encrypt->mode and $decrypt->mode to Cipher::AES_128_ECB .
Here’s an example of AES-128 CBC mode encryption using an initialization vector:
01 |
include_once ( "AES128.php" ); |
02 |
include_once ( "cipher.php" ); |
03 |
04 |
$encrypt = new Cipher; |
05 |
$encrypt ->mode = Cipher::AES_128_CBC; |
06 |
$encrypt ->password = "password" ; |
07 |
$encrypt ->plainText = "this is a very long string that we would like to encrypt using AES128" ; |
08 |
$encrypt ->encrypt(); |
09 |
10 |
echo "iv: " . bin2hex( $encrypt ->iv ) . "<br>" ; |
11 |
echo "encrypted: " . bin2hex( $encrypt ->encryptedText ) . "<br>" ; |
12 |
13 |
$decrypt = new Cipher; |
14 |
$decrypt ->mode = Cipher::AES_128_CBC; |
15 |
$decrypt ->iv = $encrypt ->iv; |
16 |
$decrypt ->password = "password" ; |
17 |
$decrypt ->encryptedText = $encrypt ->encryptedText; |
18 |
$decrypt ->decrypt(); |
19 |
20 |
echo "plain text: " . $decrypt ->plainText; |
Related posts: