Skip to content
This repository has been archived by the owner on May 9, 2020. It is now read-only.

Add CFB mode. #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 24 additions & 8 deletions blowfish.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Blowfish {
# Mode constants
const BLOWFISH_MODE_EBC = 10;
const BLOWFISH_MODE_CBC = 11;
const BLOWFISH_MODE_CFB = 12;

# Padding mode constants
const BLOWFISH_PADDING_NONE = 20;
Expand All @@ -36,7 +37,7 @@ function Blowfish($key, $mode, $padding, $iv=NULL) {
*
* @param string $plaintext the string to encrypt
* @param string $key the encryption key
* @param int $mode one of BLOWFISH_MODE_CBC, BLOWFISH_MODE_EBC. BLOWFISH_MODE_CBC is recommened
* @param int $mode one of BLOWFISH_MODE_[CBC, CFB, EBC]. BLOWFISH_MODE_CBC is recommened
* @param int $padding one of BLOWFISH_PADDING_NONE, BLOWFISH_PADDING_RFC, BLOWFISH_PADDING_ZERO. BLOWFISH_PADDING_RFC is recommened
* @param int $iv the initialisation vector. Required when using CBC mode.
* @return string Returns the encrypted string. It is recommended you base64encode this for storage.
Expand All @@ -58,11 +59,19 @@ function encrypt($plaintext, $key, $mode=Blowfish::BLOWFISH_MODE_CBC, $padding=B
if ($mode == Blowfish::BLOWFISH_MODE_CBC) {
$chain = ($i == 0) ? $fish->IV : substr($ciphertext, $i - $block, $block);
list(, $xL, $xR) = unpack('N2', substr($paded, $i, $block) ^ $chain);
} else {
$fish->_encipher($xL, $xR);
list(, $a, $b) = unpack('N2', pack('N2', $xL, $xR));
$ciphertext .= pack('N2', $xL, $xR);
} else if ($mode ==Blowfish::BLOWFISH_MODE_CFB) {
$chain = ($i == 0) ? $fish->IV : substr($ciphertext, $i - $block, $block);
list(, $xL, $xR) = unpack('N2', $chain);
$fish->_encipher($xL, $xR);
$ciphertext .= substr($paded, $i, $block) ^ pack('N2', $xL, $xR);
}else {
list(, $xL, $xR) = unpack('N2', substr($paded, $i, $block));
$fish->_encipher($xL, $xR);
$ciphertext .= pack('N2', $xL, $xR);
}
$fish->_encipher($xL, $xR);
$ciphertext .= pack('N2', $xL, $xR);
}
unset($fish);
return $ciphertext;
Expand All @@ -80,7 +89,7 @@ function encrypt($plaintext, $key, $mode=Blowfish::BLOWFISH_MODE_CBC, $padding=B
* @author Matt Harris
**/
function decrypt($ciphertext, $key, $mode=Blowfish::BLOWFISH_MODE_CBC, $padding=Blowfish::BLOWFISH_PADDING_RFC, $iv=NULL) {
if ( $mode == Blowfish::BLOWFISH_MODE_CBC and empty($iv) ) {
if ( ($mode == Blowfish::BLOWFISH_MODE_CBC || $mode == Blowfish::BLOWFISH_MODE_CFB) and empty($iv) ) {
throw new Exception('CBC Mode requires an IV key');
return;
}
Expand All @@ -92,12 +101,19 @@ function decrypt($ciphertext, $key, $mode=Blowfish::BLOWFISH_MODE_CBC, $padding=

# encrypt in 1 byte intervals
for ($i=0; $i < $len; $i+=$block) {
list(, $xL, $xR) = unpack('N2', substr($ciphertext, $i, $block));
$fish->_decipher($xL, $xR);
if ($mode == Blowfish::BLOWFISH_MODE_CBC) {
list(, $xL, $xR) = unpack('N2', substr($ciphertext, $i, $block));
$fish->_decipher($xL, $xR);
$chain = ($i == 0) ? $fish->IV : substr($ciphertext, $i - $block, $block);
$plaintext .= (pack('N2', $xL, $xR) ^ $chain);
} elseif ($mode == Blowfish::BLOWFISH_MODE_CFB) {
$chain = ($i == 0) ? $fish->IV : substr($ciphertext, $i - $block, $block);
list(, $xL, $xR) = unpack('N2', $chain);
$fish->_encipher($xL, $xR); // ENcipher!
$plaintext .= (substr($ciphertext, $i, $block) ^ pack('N2', $xL, $xR));
} else {
list(, $xL, $xR) = unpack('N2', substr($ciphertext, $i, $block));
$fish->_decipher($xL, $xR);
$plaintext .= pack('N2', $xL, $xR);
}
}
Expand Down Expand Up @@ -484,4 +500,4 @@ class DefaultKey {
);
}

?>
?>
5 changes: 3 additions & 2 deletions readme.textile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
h1. PHP_Blowfish

PHP class which provides CBC and ECB Blowfish encryption without any external libraries. Tested using Eric Young's test vectors.
PHP class which provides CBC, CFB and ECB Blowfish encryption without any external libraries. Tested using Eric Young's test vectors.

h2. Dependencies

Expand All @@ -13,6 +13,7 @@ See the included example.php in the tests folder.
h2. The MIT License

Copyright (c) 2009 Matt Harris (http://themattharris.com)
Copyright (c) 2015 Jasper Olbrich (the CFB part)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -30,4 +31,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
10 changes: 7 additions & 3 deletions tests/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
$mode = Blowfish::BLOWFISH_MODE_CBC;
$vectors = file(dirname(__FILE__) . '/vectors_cbc.txt');
break;
case 'cfb':
$mode = Blowfish::BLOWFISH_MODE_CFB;
$vectors = file(dirname(__FILE__) . '/vectors_cfb.txt');
break;
case 'key':
$mode = Blowfish::BLOWFISH_MODE_EBC;
$vectors = file(dirname(__FILE__) . '/vectors_key.txt');
Expand All @@ -20,7 +24,7 @@
}

echo '<pre>';
if ($mode == Blowfish::BLOWFISH_MODE_CBC) {
if ($mode == Blowfish::BLOWFISH_MODE_CBC || $mode == Blowfish::BLOWFISH_MODE_CFB) {
echo sprintf('%-20s%-50s%-50s%-10s%s', 'Key/IV', 'Plain/Cipher In', 'Plain/Cipher Out', 'Result', PHP_EOL);
echo sprintf('%-20s%-50s%-50s%-10s%s', '------', '---------------', '----------------', '------', PHP_EOL);
} else {
Expand All @@ -30,7 +34,7 @@
foreach ($vectors as $v) {
$v = trim($v);
if ($v AND ($v[0] != '#')) {
if ($mode == Blowfish::BLOWFISH_MODE_CBC) {
if ($mode == Blowfish::BLOWFISH_MODE_CBC || $mode == Blowfish::BLOWFISH_MODE_CFB) {
list($key, $plaintext, $expected_ciphertext, $iv) = preg_split('/\s+/', $v);
} else {
list($key, $plaintext, $expected_ciphertext) = preg_split('/\s+/', $v);
Expand All @@ -40,7 +44,7 @@
$key = trim($key);
$key = pack('H' . strlen($key), $key);

if ($mode == Blowfish::BLOWFISH_MODE_CBC) {
if ($mode == Blowfish::BLOWFISH_MODE_CBC || $mode == Blowfish::BLOWFISH_MODE_CFB) {
$iv = trim($iv);
$iv = pack('H' . strlen($iv), $iv);
}
Expand Down
3 changes: 3 additions & 0 deletions tests/vectors_cfb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# CFB Test Vectors - in Hex
# Key Plain Text Cipher Text IV
0123456789ABCDEFF0E1D2C3B4A59687 37363534333231204E6F77206973207468652074696D6520666F722000 E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3 FEDCBA9876543210