merge master into mobile-style

This commit is contained in:
Jan-Christoph Borchardt 2014-01-29 10:55:44 +01:00
commit 13ed59c1cf
78 changed files with 15474 additions and 5141 deletions

View file

@ -26,7 +26,7 @@ RewriteRule ^.well-known/carddav /remote.php/carddav/ [R]
RewriteRule ^.well-known/caldav /remote.php/caldav/ [R] RewriteRule ^.well-known/caldav /remote.php/caldav/ [R]
RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L] RewriteRule ^apps/calendar/caldav.php remote.php/caldav/ [QSA,L]
RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L] RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L]
RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L] RewriteRule ^apps/([^/]*)/(.*\.(php))$ index.php?app=$1&getfile=$2 [QSA,L]
RewriteRule ^remote/(.*) remote.php [QSA,L] RewriteRule ^remote/(.*) remote.php [QSA,L]
</IfModule> </IfModule>
<IfModule mod_mime.c> <IfModule mod_mime.c>

View file

@ -52,6 +52,7 @@ $server->addPlugin(new OC_Connector_Sabre_FilesPlugin());
$server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin()); $server->addPlugin(new OC_Connector_Sabre_AbortedUploadDetectionPlugin());
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin()); $server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
$server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin()); $server->addPlugin(new OC_Connector_Sabre_MaintenancePlugin());
$server->addPlugin(new OC_Connector_Sabre_ExceptionLoggerPlugin('webdav'));
// And off we go! // And off we go!
$server->exec(); $server->exec();

View file

@ -3,7 +3,7 @@
See the COPYING-README file. */ See the COPYING-README file. */
/* FILE MENU */ /* FILE MENU */
.actions { padding:.3em; height:2em; width: 100%; } .actions { padding:5px; height:32px; width: 100%; }
.actions input, .actions button, .actions .button { margin:0; float:left; } .actions input, .actions button, .actions .button { margin:0; float:left; }
.actions .button a { color: #555; } .actions .button a { color: #555; }
.actions .button a:hover, .actions .button a:active { color: #333; } .actions .button a:hover, .actions .button a:active { color: #333; }
@ -33,9 +33,9 @@
#new>ul { #new>ul {
display: none; display: none;
position: fixed; position: fixed;
min-width: 7em; min-width: 112px;
z-index: 10; z-index: 10;
padding: .5em; padding: 8px;
padding-bottom: 0; padding-bottom: 0;
margin-top: 14px; margin-top: 14px;
margin-left: -1px; margin-left: -1px;
@ -46,7 +46,7 @@
border-top-left-radius: 0; border-top-left-radius: 0;
box-shadow:0 2px 7px rgba(170,170,170,.4); box-shadow:0 2px 7px rgba(170,170,170,.4);
} }
#new>ul>li { height:36px; margin:.3em; padding-left:3em; padding-bottom:0.1em; #new>ul>li { height:36px; margin:5px; padding-left:48px; padding-bottom:2px;
background-repeat:no-repeat; cursor:pointer; } background-repeat:no-repeat; cursor:pointer; }
#new>ul>li>p { cursor:pointer; padding-top: 7px; padding-bottom: 7px;} #new>ul>li>p { cursor:pointer; padding-top: 7px; padding-bottom: 7px;}
@ -73,7 +73,7 @@
min-width: 600px; min-width: 600px;
} }
#filestable tbody tr { background-color:#fff; height:2.5em; } #filestable tbody tr { background-color:#fff; height:40px; }
#filestable tbody tr:hover, tbody tr:active { #filestable tbody tr:hover, tbody tr:active {
background-color: rgb(240,240,240); background-color: rgb(240,240,240);
} }
@ -88,7 +88,7 @@ span.extension, span.uploading, td.date { color:#999; }
span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; } span.extension { text-transform:lowercase; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; filter:alpha(opacity=70); opacity:.7; -webkit-transition:opacity 300ms; -moz-transition:opacity 300ms; -o-transition:opacity 300ms; transition:opacity 300ms; }
tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; } tr:hover span.extension { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; filter:alpha(opacity=100); opacity:1; color:#777; }
table tr.mouseOver td { background-color:#eee; } table tr.mouseOver td { background-color:#eee; }
table th { height:2em; padding:0 .5em; color:#999; } table th { height:24px; padding:0 8px; color:#999; }
table th .name { table th .name {
position: absolute; position: absolute;
left: 55px; left: 55px;
@ -111,15 +111,15 @@ table th#headerName {
height: 50px; height: 50px;
} }
table th#headerSize, table td.filesize { table th#headerSize, table td.filesize {
min-width: 3em; min-width: 48px;
padding: 0 1em; padding: 0 16px;
text-align: right; text-align: right;
} }
table th#headerDate, table td.date { table th#headerDate, table td.date {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
position: relative; position: relative;
min-width: 11em; min-width: 176px;
} }
/* Multiselect bar */ /* Multiselect bar */
@ -147,7 +147,7 @@ table.multiselect #headerName {
position: relative; position: relative;
width: 9999px; /* when we use 100%, the styling breaks on mobile … table styling */ width: 9999px; /* when we use 100%, the styling breaks on mobile … table styling */
} }
table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; } table td.selection, table th.selection, table td.fileaction { width:32px; text-align:center; }
table td.filename a.name { table td.filename a.name {
position:relative; /* Firefox needs to explicitly have this default set … */ position:relative; /* Firefox needs to explicitly have this default set … */
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
@ -165,8 +165,8 @@ table td.filename input.filename {
margin-left: 2px; margin-left: 2px;
cursor: text; cursor: text;
} }
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:.2em .5em .5em .3em; } table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:3px 8px 8px 3px; }
table td.filename .nametext, .uploadtext, .modified { float:left; padding:.3em 0; } table td.filename .nametext, .uploadtext, .modified { float:left; padding:14px 0; }
#modified { #modified {
position: absolute; position: absolute;
@ -186,8 +186,8 @@ table td.filename .nametext {
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 800px; max-width: 800px;
} }
table td.filename .uploadtext { font-weight:normal; margin-left:.5em; } table td.filename .uploadtext { font-weight:normal; margin-left:8px; }
table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; } table td.filename form { font-size:14px; margin-left:48px; margin-right:48px; }
.ie8 input[type="checkbox"]{ .ie8 input[type="checkbox"]{
padding: 0; padding: 0;
@ -222,6 +222,11 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
width: 50px; width: 50px;
z-index: 5; z-index: 5;
} }
#fileList tr td.filename>input[type="checkbox"]{
/* sometimes checkbox height is bigger (KDE/Qt), so setting to absolute
* to prevent it to increase the height */
position: absolute;
}
#fileList tr td.filename>input[type="checkbox"] + label { #fileList tr td.filename>input[type="checkbox"] + label {
left: 0; left: 0;
} }
@ -255,11 +260,11 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
right: 0; right: 0;
} }
#fileList img.move2trash { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; float:right; } #fileList img.move2trash { display:inline; margin:-8px 0; padding:16px 8px 16px 8px !important; float:right; }
#fileList a.action.delete { #fileList a.action.delete {
position: absolute; position: absolute;
right: 0; right: 0;
padding: 9px 14px 19px !important; padding: 28px 14px 19px !important;
} }
a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
@ -277,13 +282,13 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; }
} }
.selectedActions a img { .selectedActions a img {
position:relative; position:relative;
top:.3em; top:5px;
} }
#fileList a.action { #fileList a.action {
display: inline; display: inline;
margin: -.5em 0; margin: -8px 0;
padding: 18px 8px !important; padding: 18px 8px !important;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0); filter: alpha(opacity=0);

View file

@ -5,7 +5,7 @@
height: 36px; height: 36px;
width: 39px; width: 39px;
padding: 0 !important; /* override default control bar button padding */ padding: 0 !important; /* override default control bar button padding */
margin-left: .2em; margin-left: 3px;
overflow: hidden; overflow: hidden;
vertical-align: top; vertical-align: top;
} }
@ -18,9 +18,6 @@
margin: -5px -3px; margin: -5px -3px;
cursor: pointer; cursor: pointer;
z-index: 10; z-index: 10;
background-image: url('%webroot%/core/img/actions/upload.svg');
background-repeat: no-repeat;
background-position: center;
opacity: .65; opacity: .65;
} }
.file_upload_target { display:none; } .file_upload_target { display:none; }
@ -33,7 +30,7 @@
height: 44px; height: 44px;
margin: -5px -3px; margin: -5px -3px;
padding: 0; padding: 0;
font-size: 1em; font-size: 16px;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0;
z-index: 20; z-index: 20;
cursor: pointer; cursor: pointer;
@ -119,11 +116,6 @@
.oc-dialog .fileexists .conflict input[type='checkbox'] { .oc-dialog .fileexists .conflict input[type='checkbox'] {
float: left; float: left;
} }
.oc-dialog .fileexists .toggle {
background-image: url('%webroot%/core/img/actions/triangle-e.png');
width: 16px;
height: 16px;
}
.oc-dialog .fileexists #allfileslabel { .oc-dialog .fileexists #allfileslabel {
float:right; float:right;
} }

View file

@ -63,7 +63,6 @@ $files = array();
$user = OC_User::getUser(); $user = OC_User::getUser();
if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache
$needUpgrade = true; $needUpgrade = true;
$freeSpace = 0;
} else { } else {
if ($isIE8){ if ($isIE8){
// after the redirect above, the URL will have a format // after the redirect above, the URL will have a format
@ -77,7 +76,6 @@ if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we ne
else{ else{
$files = \OCA\Files\Helper::getFiles($dir); $files = \OCA\Files\Helper::getFiles($dir);
} }
$freeSpace = \OC\Files\Filesystem::free_space($dir);
$needUpgrade = false; $needUpgrade = false;
} }

View file

@ -173,7 +173,10 @@ $(document).ready(function () {
FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () {
return OC.imagePath('core', 'actions/download'); return OC.imagePath('core', 'actions/download');
}, function (filename) { }, function (filename) {
window.location = OC.filePath('files', 'ajax', 'download.php') + '?files=' + encodeURIComponent(filename) + '&dir=' + encodeURIComponent($('#dir').val()); var url = FileList.getDownloadUrl(filename);
if (url) {
OC.redirect(url);
}
}); });
} }
$('#fileList tr').each(function () { $('#fileList tr').each(function () {

View file

@ -780,6 +780,20 @@ var FileList={
$('#fileList tr.searchresult').each(function(i,e) { $('#fileList tr.searchresult').each(function(i,e) {
$(e).removeClass("searchresult"); $(e).removeClass("searchresult");
}); });
},
/**
* Returns the download URL of the given file
* @param filename file name of the file
* @param dir optional directory in which the file name is, defaults to the current directory
*/
getDownloadUrl: function(filename, dir) {
var params = {
files: filename,
dir: dir || FileList.getCurrentDirectory(),
download: null
};
return OC.filePath('files', 'ajax', 'download.php') + '?' + OC.buildQueryString(params);
} }
}; };

View file

@ -493,7 +493,7 @@ var createDragShadow = function(event) {
var dir=$('#dir').val(); var dir=$('#dir').val();
$(selectedFiles).each(function(i,elem) { $(selectedFiles).each(function(i,elem) {
var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name); var newtr = $('<tr/>').attr('data-dir', dir).attr('data-filename', elem.name).attr('data-origin', elem.origin);
newtr.append($('<td/>').addClass('filename').text(elem.name)); newtr.append($('<td/>').addClass('filename').text(elem.name));
newtr.append($('<td/>').addClass('size').text(humanFileSize(elem.size))); newtr.append($('<td/>').addClass('size').text(humanFileSize(elem.size)));
tbody.append(newtr); tbody.append(newtr);
@ -511,13 +511,30 @@ var createDragShadow = function(event) {
}; };
//options for file drag/drop //options for file drag/drop
//start&stop handlers needs some cleaning up
var dragOptions={ var dragOptions={
revert: 'invalid', revertDuration: 300, revert: 'invalid', revertDuration: 300,
opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: 24, top: 18 }, opacity: 0.7, zIndex: 100, appendTo: 'body', cursorAt: { left: 24, top: 18 },
helper: createDragShadow, cursor: 'move', helper: createDragShadow, cursor: 'move',
stop: function(event, ui) { start: function(event, ui){
$('#fileList tr td.filename').addClass('ui-draggable'); var $selectedFiles = $('td.filename input:checkbox:checked');
} if($selectedFiles.length > 1){
$selectedFiles.parents('tr').fadeTo(250, 0.2);
}
else{
$(this).fadeTo(250, 0.2);
}
},
stop: function(event, ui) {
var $selectedFiles = $('td.filename input:checkbox:checked');
if($selectedFiles.length > 1){
$selectedFiles.parents('tr').fadeTo(250, 1);
}
else{
$(this).fadeTo(250, 1);
}
$('#fileList tr td.filename').addClass('ui-draggable');
}
}; };
// sane browsers support using the distance option // sane browsers support using the distance option
if ( $('html.ie').length === 0) { if ( $('html.ie').length === 0) {
@ -525,6 +542,7 @@ if ( $('html.ie').length === 0) {
} }
var folderDropOptions={ var folderDropOptions={
hoverClass: "canDrop",
drop: function( event, ui ) { drop: function( event, ui ) {
//don't allow moving a file into a selected folder //don't allow moving a file into a selected folder
if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) { if ($(event.target).parents('tr').find('td input:first').prop('checked') === true) {
@ -537,6 +555,11 @@ var folderDropOptions={
$(files).each(function(i,row) { $(files).each(function(i,row) {
var dir = $(row).data('dir'); var dir = $(row).data('dir');
var file = $(row).data('filename'); var file = $(row).data('filename');
//slapdash selector, tracking down our original element that the clone budded off of.
var origin = $('tr[data-id=' + $(row).data('origin') + ']');
var td = origin.children('td.filename');
var oldBackgroundImage = td.css('background-image');
td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
$.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: dir+'/'+target }, function(result) { $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: dir+'/'+target }, function(result) {
if (result) { if (result) {
if (result.status === 'success') { if (result.status === 'success') {
@ -559,6 +582,7 @@ var folderDropOptions={
} else { } else {
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
} }
td.css('background-image', oldBackgroundImage);
}); });
}); });
}, },
@ -583,6 +607,11 @@ var crumbDropOptions={
$(files).each(function(i,row) { $(files).each(function(i,row) {
var dir = $(row).data('dir'); var dir = $(row).data('dir');
var file = $(row).data('filename'); var file = $(row).data('filename');
//slapdash selector, tracking down our original element that the clone budded off of.
var origin = $('tr[data-id=' + $(row).data('origin') + ']');
var td = origin.children('td.filename');
var oldBackgroundImage = td.css('background-image');
td.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
$.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) { $.post(OC.filePath('files', 'ajax', 'move.php'), { dir: dir, file: file, target: target }, function(result) {
if (result) { if (result) {
if (result.status === 'success') { if (result.status === 'success') {
@ -597,6 +626,7 @@ var crumbDropOptions={
} else { } else {
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error')); OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
} }
td.css('background-image', oldBackgroundImage);
}); });
}); });
}, },
@ -663,7 +693,8 @@ function getSelectedFilesTrash(property) {
mime:$(element).data('mime'), mime:$(element).data('mime'),
type:$(element).data('type'), type:$(element).data('type'),
size:$(element).data('size'), size:$(element).data('size'),
etag:$(element).data('etag') etag:$(element).data('etag'),
origin: $(element).data('id')
}; };
if (property) { if (property) {
files.push(file[property]); files.push(file[property]);
@ -783,3 +814,4 @@ function onClickBreadcrumb(e) {
FileList.changeDirectory(decodeURIComponent($targetDir)); FileList.changeDirectory(decodeURIComponent($targetDir));
} }
} }

View file

@ -5,7 +5,7 @@
<h2><?php p($l->t('File handling')); ?></h2> <h2><?php p($l->t('File handling')); ?></h2>
<?php if($_['uploadChangable']):?> <?php if($_['uploadChangable']):?>
<label for="maxUploadSize"><?php p($l->t( 'Maximum upload size' )); ?> </label> <label for="maxUploadSize"><?php p($l->t( 'Maximum upload size' )); ?> </label>
<input name='maxUploadSize' id="maxUploadSize" value='<?php p($_['uploadMaxFilesize']) ?>'/> <input type="text" name='maxUploadSize' id="maxUploadSize" value='<?php p($_['uploadMaxFilesize']) ?>'/>
<?php if($_['displayMaxPossibleUploadSize']):?> <?php if($_['displayMaxPossibleUploadSize']):?>
(<?php p($l->t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>) (<?php p($l->t('max. possible: ')); p($_['maxPossibleUploadSize']) ?>)
<?php endif;?> <?php endif;?>

View file

@ -29,7 +29,7 @@
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir"> <input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
<input type="file" id="file_upload_start" name='files[]' <input type="file" id="file_upload_start" name='files[]'
data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" /> data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
<a href="#" class="svg"></a> <a href="#" class="svg icon icon-upload"></a>
</div> </div>
<?php if ($_['trash']): ?> <?php if ($_['trash']): ?>
<input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?> /> <input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?> />

View file

@ -0,0 +1,61 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('FileActions tests', function() {
beforeEach(function() {
// init horrible parameters
var $body = $('body');
$body.append('<input type="hidden" id="dir" value="/subdir"></input>');
$body.append('<input type="hidden" id="permissions" value="31"></input>');
// dummy files table
$filesTable = $body.append('<table id="filestable"></table>');
});
afterEach(function() {
$('#dir, #permissions, #filestable').remove();
});
it('calling display() sets file actions', function() {
// note: download_url is actually the link target, not the actual download URL...
var $tr = FileList.addFile('testName.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'});
// no actions before call
expect($tr.find('.action[data-action=Download]').length).toEqual(0);
expect($tr.find('.action[data-action=Rename]').length).toEqual(0);
expect($tr.find('.action.delete').length).toEqual(0);
FileActions.display($tr.find('td.filename'), true);
// actions defined after cal
expect($tr.find('.action[data-action=Download]').length).toEqual(1);
expect($tr.find('.action[data-action=Rename]').length).toEqual(1);
expect($tr.find('.action.delete').length).toEqual(1);
});
it('redirects to download URL when clicking download', function() {
var redirectStub = sinon.stub(OC, 'redirect');
// note: download_url is actually the link target, not the actual download URL...
var $tr = FileList.addFile('test download File.txt', 1234, new Date(), false, false, {download_url: 'test/download/url'});
FileActions.display($tr.find('td.filename'), true);
$tr.find('.action[data-action=Download]').click();
expect(redirectStub.calledOnce).toEqual(true);
expect(redirectStub.getCall(0).args[0]).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=test%20download%20File.txt&dir=%2Fsubdir&download');
redirectStub.restore();
});
});

View file

@ -0,0 +1,63 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('FileList tests', function() {
beforeEach(function() {
// init horrible parameters
var $body = $('body');
$body.append('<input type="hidden" id="dir" value="/subdir"></input>');
$body.append('<input type="hidden" id="permissions" value="31"></input>');
// dummy files table
$body.append('<table id="filestable"></table>');
});
afterEach(function() {
$('#dir, #permissions, #filestable').remove();
});
it('generates file element with correct attributes when calling addFile', function() {
var lastMod = new Date(10000);
// note: download_url is actually the link target, not the actual download URL...
var $tr = FileList.addFile('testName.txt', 1234, lastMod, false, false, {download_url: 'test/download/url'});
expect($tr).toBeDefined();
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
expect($tr.find('a:first').attr('href')).toEqual('test/download/url');
expect($tr.attr('data-type')).toEqual('file');
expect($tr.attr('data-file')).toEqual('testName.txt');
expect($tr.attr('data-size')).toEqual('1234');
expect($tr.attr('data-permissions')).toEqual('31');
//expect($tr.attr('data-mime')).toEqual('plain/text');
});
it('generates dir element with correct attributes when calling addDir', function() {
var lastMod = new Date(10000);
var $tr = FileList.addDir('testFolder', 1234, lastMod, false);
expect($tr).toBeDefined();
expect($tr[0].tagName.toLowerCase()).toEqual('tr');
expect($tr.attr('data-type')).toEqual('dir');
expect($tr.attr('data-file')).toEqual('testFolder');
expect($tr.attr('data-size')).toEqual('1234');
expect($tr.attr('data-permissions')).toEqual('31');
//expect($tr.attr('data-mime')).toEqual('httpd/unix-directory');
});
it('returns correct download URL', function() {
expect(FileList.getDownloadUrl('some file.txt')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fsubdir&download');
expect(FileList.getDownloadUrl('some file.txt', '/anotherpath/abc')).toEqual(OC.webroot + '/index.php/apps/files/ajax/download.php?files=some%20file.txt&dir=%2Fanotherpath%2Fabc&download');
});
});

View file

@ -0,0 +1,81 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('Files tests', function() {
describe('File name validation', function() {
it('Validates correct file names', function() {
var fileNames = [
'boringname',
'something.with.extension',
'now with spaces',
'.a',
'..a',
'.dotfile',
'single\'quote',
' spaces before',
'spaces after ',
'allowed chars including the crazy ones $%&_-^@!,()[]{}=;#',
'汉字也能用',
'und Ümläüte sind auch willkommen'
];
for ( var i = 0; i < fileNames.length; i++ ) {
try {
expect(Files.isFileNameValid(fileNames[i])).toEqual(true);
}
catch (e) {
fail();
}
}
});
it('Detects invalid file names', function() {
var fileNames = [
'',
' ',
'.',
'..',
'back\\slash',
'sl/ash',
'lt<lt',
'gt>gt',
'col:on',
'double"quote',
'pi|pe',
'dont?ask?questions?',
'super*star',
'new\nline',
' ..',
'.. ',
'. ',
' .'
];
for ( var i = 0; i < fileNames.length; i++ ) {
var threwException = false;
try {
Files.isFileNameValid(fileNames[i]);
fail();
}
catch (e) {
threwException = true;
}
expect(threwException).toEqual(true);
}
});
});
});

View file

@ -37,6 +37,7 @@ namespace OCA\Encryption;
class Proxy extends \OC_FileProxy { class Proxy extends \OC_FileProxy {
private static $blackList = null; //mimetypes blacklisted from encryption private static $blackList = null; //mimetypes blacklisted from encryption
private static $unencryptedSizes = array(); // remember unencrypted size
/** /**
* Check if a file requires encryption * Check if a file requires encryption
@ -114,14 +115,12 @@ class Proxy extends \OC_FileProxy {
// get encrypted content // get encrypted content
$data = $view->file_get_contents($tmpPath); $data = $view->file_get_contents($tmpPath);
// update file cache for target file // store new unenecrypted size so that it can be updated
// in the post proxy
$tmpFileInfo = $view->getFileInfo($tmpPath); $tmpFileInfo = $view->getFileInfo($tmpPath);
$fileInfo = $view->getFileInfo($path); if ( isset($tmpFileInfo['size']) ) {
if (is_array($fileInfo) && is_array($tmpFileInfo)) { self::$unencryptedSizes[\OC_Filesystem::normalizePath($path)] = $tmpFileInfo['size'];
$fileInfo['encrypted'] = true; }
$fileInfo['unencrypted_size'] = $tmpFileInfo['size'];
$view->putFileInfo($path, $fileInfo);
}
// remove our temp file // remove our temp file
$view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder); $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder);
@ -136,6 +135,24 @@ class Proxy extends \OC_FileProxy {
} }
/**
* @brief update file cache with the new unencrypted size after file was written
* @param string $path
* @param mixed $result
* @return mixed
*/
public function postFile_put_contents($path, $result) {
$normalizedPath = \OC_Filesystem::normalizePath($path);
if ( isset(self::$unencryptedSizes[$normalizedPath]) ) {
$view = new \OC_FilesystemView('/');
$view->putFileInfo($normalizedPath,
array('encrypted' => true, 'encrypted_size' => self::$unencryptedSizes[$normalizedPath]));
unset(self::$unencryptedSizes[$normalizedPath]);
}
return $result;
}
/** /**
* @param string $path Path of file from which has been read * @param string $path Path of file from which has been read
* @param string $data Data that has been read from file * @param string $data Data that has been read from file

View file

@ -2,9 +2,10 @@
/** /**
* ownCloud * ownCloud
* *
* @author Sam Tuke, Frank Karlitschek * @author Sam Tuke, Frank Karlitschek, Bjoern Schiessle
* @copyright 2012 Sam Tuke <samtuke@owncloud.com>, * @copyright 2012 Sam Tuke <samtuke@owncloud.com>,
* Frank Karlitschek <frank@owncloud.org> * Frank Karlitschek <frank@owncloud.org>,
* Bjoern Schiessle <schiessle@owncloud.com>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -1360,59 +1361,32 @@ class Util {
} }
} }
/** /**
* @brief go recursively through a dir and collect all files and sub files. * @brief go recursively through a dir and collect all files and sub files.
* @param string $dir relative to the users files folder * @param string $dir relative to the users files folder
* @return array with list of files relative to the users files folder * @return array with list of files relative to the users files folder
*/ */
public function getAllFiles($dir) { public function getAllFiles($dir) {
$result = array(); $result = array();
$dirList = array($dir);
$content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath( while ($dirList) {
$this->userFilesDir . '/' . $dir)); $dir = array_pop($dirList);
$content = $this->view->getDirectoryContent(\OC\Files\Filesystem::normalizePath(
// handling for re shared folders $this->userFilesDir . '/' . $dir));
$pathSplit = explode('/', $dir);
foreach ($content as $c) {
$sharedPart = $pathSplit[sizeof($pathSplit) - 1];
$targetPathSplit = array_reverse(explode('/', $c['path']));
$path = '';
// rebuild path
foreach ($targetPathSplit as $pathPart) {
if ($pathPart !== $sharedPart) {
$path = '/' . $pathPart . $path;
foreach ($content as $c) {
$usersPath = isset($c['usersPath']) ? $c['usersPath'] : $c['path'];
if ($c['type'] === 'dir') {
$dirList[] = substr($usersPath, strlen("files"));
} else { } else {
$result[] = substr($usersPath, strlen("files"));
break;
} }
} }
$path = $dir . $path;
if ($c['type'] === 'dir') {
$result = array_merge($result, $this->getAllFiles($path));
} else {
$result[] = $path;
}
} }
return $result; return $result;
} }
/** /**

View file

@ -1,3 +1,5 @@
phpseclib Lead Developer: TerraFrost (Jim Wigginton) phpseclib Lead Developer: TerraFrost (Jim Wigginton)
phpseclib Developers: monnerat (Patrick Monnerat) phpseclib Developers: monnerat (Patrick Monnerat)
bantu (Andreas Fischer)
petrich (Hans-Jürgen Petrich)

View file

@ -4,9 +4,9 @@
MIT-licensed pure-PHP implementations of an arbitrary-precision integer MIT-licensed pure-PHP implementations of an arbitrary-precision integer
arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael, arithmetic library, fully PKCS#1 (v2.1) compliant RSA, DES, 3DES, RC4, Rijndael,
AES, SSH-1, SSH-2, SFTP, and X.509 AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* [Download (0.3.1)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.1.zip/download) * [Download (0.3.5)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.5.zip/download)
* [Browse Git](https://github.com/phpseclib/phpseclib) * [Browse Git](https://github.com/phpseclib/phpseclib)
* [Documentation](http://phpseclib.sourceforge.net/) * [Documentation](http://phpseclib.sourceforge.net/)
* [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46) * [Support](http://www.frostjedi.com/phpbb/viewforum.php?f=46)

View file

@ -43,6 +43,14 @@
"File": "phpseclib/", "File": "phpseclib/",
"Math": "phpseclib/", "Math": "phpseclib/",
"Net": "phpseclib/" "Net": "phpseclib/"
},
"files": [
"phpseclib/Crypt/Random.php"
]
},
"extra": {
"branch-alias": {
"dev-master": "0.3-dev"
} }
} }
} }

View file

@ -4,13 +4,13 @@
/** /**
* Pure-PHP implementation of AES. * Pure-PHP implementation of AES.
* *
* Uses mcrypt, if available, and an internal implementation, otherwise. * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
* *
* PHP versions 4 and 5 * PHP versions 4 and 5
* *
* If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from * If {@link Crypt_AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
* {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits * {@link Crypt_AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits
* it'll be null-padded to 160-bits and 160 bits will be the key length until {@link Crypt_Rijndael::setKey() setKey()} * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link Crypt_AES::setKey() setKey()}
* is called, again, at which point, it'll be recalculated. * is called, again, at which point, it'll be recalculated.
* *
* Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't * Since Crypt_AES extends Crypt_Rijndael, some functions are available to be called that, in the context of AES, don't
@ -42,10 +42,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -59,7 +59,6 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVIII Jim Wigginton * @copyright MMVIII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: AES.php,v 1.7 2010/02/09 06:10:25 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -67,7 +66,7 @@
* Include Crypt_Rijndael * Include Crypt_Rijndael
*/ */
if (!class_exists('Crypt_Rijndael')) { if (!class_exists('Crypt_Rijndael')) {
require_once 'Rijndael.php'; require_once('Rijndael.php');
} }
/**#@+ /**#@+
@ -82,31 +81,31 @@ if (!class_exists('Crypt_Rijndael')) {
* *
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/ */
define('CRYPT_AES_MODE_CTR', -1); define('CRYPT_AES_MODE_CTR', CRYPT_MODE_CTR);
/** /**
* Encrypt / decrypt using the Electronic Code Book mode. * Encrypt / decrypt using the Electronic Code Book mode.
* *
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/ */
define('CRYPT_AES_MODE_ECB', 1); define('CRYPT_AES_MODE_ECB', CRYPT_MODE_ECB);
/** /**
* Encrypt / decrypt using the Code Book Chaining mode. * Encrypt / decrypt using the Code Book Chaining mode.
* *
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/ */
define('CRYPT_AES_MODE_CBC', 2); define('CRYPT_AES_MODE_CBC', CRYPT_MODE_CBC);
/** /**
* Encrypt / decrypt using the Cipher Feedback mode. * Encrypt / decrypt using the Cipher Feedback mode.
* *
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/ */
define('CRYPT_AES_MODE_CFB', 3); define('CRYPT_AES_MODE_CFB', CRYPT_MODE_CFB);
/** /**
* Encrypt / decrypt using the Cipher Feedback mode. * Encrypt / decrypt using the Cipher Feedback mode.
* *
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29 * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/ */
define('CRYPT_AES_MODE_OFB', 4); define('CRYPT_AES_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/ /**#@-*/
/**#@+ /**#@+
@ -116,11 +115,11 @@ define('CRYPT_AES_MODE_OFB', 4);
/** /**
* Toggles the internal implementation * Toggles the internal implementation
*/ */
define('CRYPT_AES_MODE_INTERNAL', 1); define('CRYPT_AES_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/** /**
* Toggles the mcrypt implementation * Toggles the mcrypt implementation
*/ */
define('CRYPT_AES_MODE_MCRYPT', 2); define('CRYPT_AES_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/ /**#@-*/
/** /**
@ -133,195 +132,41 @@ define('CRYPT_AES_MODE_MCRYPT', 2);
*/ */
class Crypt_AES extends Crypt_Rijndael { class Crypt_AES extends Crypt_Rijndael {
/** /**
* mcrypt resource for encryption * The namespace used by the cipher for its constants.
* *
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once. * @see Crypt_Base::const_namespace
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see Crypt_AES::encrypt()
* @var String * @var String
* @access private * @access private
*/ */
var $enmcrypt; var $const_namespace = 'AES';
/**
* mcrypt resource for decryption
*
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
*
* @see Crypt_AES::decrypt()
* @var String
* @access private
*/
var $demcrypt;
/**
* mcrypt resource for CFB mode
*
* @see Crypt_AES::encrypt()
* @see Crypt_AES::decrypt()
* @var String
* @access private
*/
var $ecb;
/**
* The SubByte S-Box
*
* @see Crypt_AES::_encryptBlock()
* @var Array
* @access intern
*/
var $sbox = array(
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
);
/**
* The inverse SubByte S-Box
*
* @see Crypt_AES::_decryptBlock()
* @var Array
* @access intern
*/
var $isbox = array(
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
);
/** /**
* Default Constructor. * Default Constructor.
* *
* Determines whether or not the mcrypt extension should be used. $mode should only, at present, be * Determines whether or not the mcrypt extension should be used.
* CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
* *
* $mode could be:
*
* - CRYPT_AES_MODE_ECB
*
* - CRYPT_AES_MODE_CBC
*
* - CRYPT_AES_MODE_CTR
*
* - CRYPT_AES_MODE_CFB
*
* - CRYPT_AES_MODE_OFB
*
* If not explictly set, CRYPT_AES_MODE_CBC will be used.
*
* @see Crypt_Rijndael::Crypt_Rijndael()
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode * @param optional Integer $mode
* @return Crypt_AES
* @access public * @access public
*/ */
function Crypt_AES($mode = CRYPT_AES_MODE_CBC) function Crypt_AES($mode = CRYPT_AES_MODE_CBC)
{ {
if ( !defined('CRYPT_AES_MODE') ) { parent::Crypt_Rijndael($mode);
switch (true) {
case extension_loaded('mcrypt') && in_array('rijndael-128', mcrypt_list_algorithms()):
define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
break;
default:
define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
}
}
switch ( CRYPT_AES_MODE ) {
case CRYPT_AES_MODE_MCRYPT:
switch ($mode) {
case CRYPT_AES_MODE_ECB:
$this->paddable = true;
$this->mode = MCRYPT_MODE_ECB;
break;
case CRYPT_AES_MODE_CTR:
// ctr doesn't have a constant associated with it even though it appears to be fairly widely
// supported. in lieu of knowing just how widely supported it is, i've, for now, opted not to
// include a compatibility layer. the layer has been implemented but, for now, is commented out.
$this->mode = 'ctr';
//$this->mode = in_array('ctr', mcrypt_list_modes()) ? 'ctr' : CRYPT_AES_MODE_CTR;
break;
case CRYPT_AES_MODE_CFB:
$this->mode = 'ncfb';
break;
case CRYPT_AES_MODE_OFB:
$this->mode = MCRYPT_MODE_NOFB;
break;
case CRYPT_AES_MODE_CBC:
default:
$this->paddable = true;
$this->mode = MCRYPT_MODE_CBC;
}
break;
default:
switch ($mode) {
case CRYPT_AES_MODE_ECB:
$this->paddable = true;
$this->mode = CRYPT_RIJNDAEL_MODE_ECB;
break;
case CRYPT_AES_MODE_CTR:
$this->mode = CRYPT_RIJNDAEL_MODE_CTR;
break;
case CRYPT_AES_MODE_CFB:
$this->mode = CRYPT_RIJNDAEL_MODE_CFB;
break;
case CRYPT_AES_MODE_OFB:
$this->mode = CRYPT_RIJNDAEL_MODE_OFB;
break;
case CRYPT_AES_MODE_CBC:
default:
$this->paddable = true;
$this->mode = CRYPT_RIJNDAEL_MODE_CBC;
}
}
if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL) {
parent::Crypt_Rijndael($this->mode);
}
}
/**
* Extended Crypt_Rijndael::_setup()
*
* Optimizing the key schedule arrays ($w, $dw) for _encryptBlock() and _decryptBlock() after Crypt_Rijndael::_setup()
*
* @see Crypt_Rijndael::_setup()
* @access private
*/
function _setup()
{
if (!$this->changed) {
return;
}
$this->w = $this->dw = array();
parent::_setup();
$this->dw = array_reverse($this->dw);
$w = array_pop($this->w);
$dw = array_pop($this->dw);
foreach ($this->w as $r => $wr) {
foreach ($wr as $c => $wc) {
$w[] = $wc;
$dw[] = $this->dw[$r][$c];
}
}
$this->w = $w;
$this->dw = $dw;
} }
/** /**
@ -329,6 +174,7 @@ class Crypt_AES extends Crypt_Rijndael {
* *
* Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything. * Since Crypt_AES extends Crypt_Rijndael, this function is, technically, available, but it doesn't do anything.
* *
* @see Crypt_Rijndael::setBlockLength()
* @access public * @access public
* @param Integer $length * @param Integer $length
*/ */
@ -336,610 +182,6 @@ class Crypt_AES extends Crypt_Rijndael {
{ {
return; return;
} }
/**
* Sets the initialization vector. (optional)
*
* SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
* to be all zero's.
*
* @access public
* @param String $iv
*/
function setIV($iv)
{
parent::setIV($iv);
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
$this->changed = true;
}
}
/**
* Encrypts a message.
*
* $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
* same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
* URL:
*
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
*
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
* strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
* length.
*
* @see Crypt_AES::decrypt()
* @access public
* @param String $plaintext
*/
function encrypt($plaintext)
{
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
$this->_mcryptSetup();
// re: http://phpseclib.sourceforge.net/cfb-demo.phps
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
// rewritten CFB implementation the above outputs the same thing twice.
if ($this->mode == 'ncfb' && $this->continuousBuffer) {
$iv = &$this->encryptIV;
$pos = &$this->enbuffer['pos'];
$len = strlen($plaintext);
$ciphertext = '';
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = 16 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
$this->enbuffer['enmcrypt_init'] = true;
}
if ($len >= 16) {
if ($this->enbuffer['enmcrypt_init'] === false || $len > 280) {
if ($this->enbuffer['enmcrypt_init'] === true) {
mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
$this->enbuffer['enmcrypt_init'] = false;
}
$ciphertext.= mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % 16));
$iv = substr($ciphertext, -16);
$len%= 16;
} else {
while ($len >= 16) {
$iv = mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, 16);
$ciphertext.= $iv;
$len-= 16;
$i+= 16;
}
}
}
if ($len) {
$iv = mcrypt_generic($this->ecb, $iv);
$block = $iv ^ substr($plaintext, -$len);
$iv = substr_replace($iv, $block, 0, $len);
$ciphertext.= $block;
$pos = $len;
}
return $ciphertext;
}
if ($this->paddable) {
$plaintext = $this->_pad($plaintext);
}
$ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
}
return $ciphertext;
}
return parent::encrypt($plaintext);
}
/**
* Decrypts a message.
*
* If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
*
* @see Crypt_AES::encrypt()
* @access public
* @param String $ciphertext
*/
function decrypt($ciphertext)
{
if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT ) {
$this->_mcryptSetup();
if ($this->mode == 'ncfb' && $this->continuousBuffer) {
$iv = &$this->decryptIV;
$pos = &$this->debuffer['pos'];
$len = strlen($ciphertext);
$plaintext = '';
$i = 0;
if ($pos) {
$orig_pos = $pos;
$max = 16 - $pos;
if ($len >= $max) {
$i = $max;
$len-= $max;
$pos = 0;
} else {
$i = $len;
$pos+= $len;
$len = 0;
}
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
}
if ($len >= 16) {
$cb = substr($ciphertext, $i, $len - $len % 16);
$plaintext.= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
$iv = substr($cb, -16);
$len%= 16;
}
if ($len) {
$iv = mcrypt_generic($this->ecb, $iv);
$plaintext.= $iv ^ substr($ciphertext, -$len);
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
$pos = $len;
}
return $plaintext;
}
if ($this->paddable) {
// we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
$ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
}
$plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
}
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
}
return parent::decrypt($ciphertext);
}
/**
* Setup mcrypt
*
* Validates all the variables.
*
* @access private
*/
function _mcryptSetup()
{
if (!$this->changed) {
return;
}
if (!$this->explicit_key_length) {
// this just copied from Crypt_Rijndael::_setup()
$length = strlen($this->key) >> 2;
if ($length > 8) {
$length = 8;
} else if ($length < 4) {
$length = 4;
}
$this->Nk = $length;
$this->key_size = $length << 2;
}
switch ($this->Nk) {
case 4: // 128
$this->key_size = 16;
break;
case 5: // 160
case 6: // 192
$this->key_size = 24;
break;
case 7: // 224
case 8: // 256
$this->key_size = 32;
}
$this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
$this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
if (!isset($this->enmcrypt)) {
$mode = $this->mode;
//$mode = $this->mode == CRYPT_AES_MODE_CTR ? MCRYPT_MODE_ECB : $this->mode;
$this->demcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
$this->enmcrypt = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', $mode, '');
if ($mode == 'ncfb') {
$this->ecb = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
}
} // else should mcrypt_generic_deinit be called?
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
if ($this->mode == 'ncfb') {
mcrypt_generic_init($this->ecb, $this->key, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
$this->changed = false;
}
/**
* Encrypts a block
*
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
*
* @see Crypt_Rijndael::_encryptBlock()
* @access private
* @param String $in
* @return String
*/
function _encryptBlock($in)
{
$state = unpack('N*', $in);
$sbox = $this->sbox;
$w = $this->w;
$t0 = $this->t0;
$t1 = $this->t1;
$t2 = $this->t2;
$t3 = $this->t3;
// addRoundKey
$s0 = $state[1] ^ $w[4];
$s1 = $state[2] ^ $w[5];
$s2 = $state[3] ^ $w[6];
$s3 = $state[4] ^ $w[7];
// shiftRows + subWord + mixColumns + addRoundKey
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[8];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[9];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[10];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[11];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[12];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[13];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[14];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[15];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[16];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[17];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[18];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[19];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[20];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[21];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[22];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[23];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[24];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[25];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[26];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[27];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[28];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[29];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[30];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[31];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[32];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[33];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[34];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[35];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[36];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[37];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[38];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[39];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[40];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[41];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[42];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[43];
switch ($this->Nr) {
case 10:
break;
case 14:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[56];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[57];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[58];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[59];
break;
case 12:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
break;
case 13:
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$s3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
$e0 = $t0[($s0 >> 24) & 0xff] ^ $t1[($s1 >> 16) & 0xff] ^ $t2[($s2 >> 8) & 0xff] ^ $t3[$s3 & 0xff] ^ $w[48];
$e1 = $t0[($s1 >> 24) & 0xff] ^ $t1[($s2 >> 16) & 0xff] ^ $t2[($s3 >> 8) & 0xff] ^ $t3[$s0 & 0xff] ^ $w[49];
$e2 = $t0[($s2 >> 24) & 0xff] ^ $t1[($s3 >> 16) & 0xff] ^ $t2[($s0 >> 8) & 0xff] ^ $t3[$s1 & 0xff] ^ $w[50];
$e3 = $t0[($s3 >> 24) & 0xff] ^ $t1[($s0 >> 16) & 0xff] ^ $t2[($s1 >> 8) & 0xff] ^ $t3[$s2 & 0xff] ^ $w[51];
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[52];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[53];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[54];
$e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[55];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
break;
default: // 11
$s0 = $t0[($e0 >> 24) & 0xff] ^ $t1[($e1 >> 16) & 0xff] ^ $t2[($e2 >> 8) & 0xff] ^ $t3[$e3 & 0xff] ^ $w[44];
$s1 = $t0[($e1 >> 24) & 0xff] ^ $t1[($e2 >> 16) & 0xff] ^ $t2[($e3 >> 8) & 0xff] ^ $t3[$e0 & 0xff] ^ $w[45];
$s2 = $t0[($e2 >> 24) & 0xff] ^ $t1[($e3 >> 16) & 0xff] ^ $t2[($e0 >> 8) & 0xff] ^ $t3[$e1 & 0xff] ^ $w[46];
$e3 = $t0[($e3 >> 24) & 0xff] ^ $t1[($e0 >> 16) & 0xff] ^ $t2[($e1 >> 8) & 0xff] ^ $t3[$e2 & 0xff] ^ $w[47];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
}
// subWord
$e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
$e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
$e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
$e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
// shiftRows + addRoundKey
return pack('N*',
($e0 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $w[0],
($e1 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $w[1],
($e2 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $w[2],
($e3 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $w[3]
);
}
/**
* Decrypts a block
*
* Optimized over Crypt_Rijndael's implementation by means of loop unrolling.
*
* @see Crypt_Rijndael::_decryptBlock()
* @access private
* @param String $in
* @return String
*/
function _decryptBlock($in)
{
$state = unpack('N*', $in);
$sbox = $this->isbox;
$dw = $this->dw;
$dt0 = $this->dt0;
$dt1 = $this->dt1;
$dt2 = $this->dt2;
$dt3 = $this->dt3;
// addRoundKey
$s0 = $state[1] ^ $dw[4];
$s1 = $state[2] ^ $dw[5];
$s2 = $state[3] ^ $dw[6];
$s3 = $state[4] ^ $dw[7];
// invShiftRows + invSubBytes + invMixColumns + addRoundKey
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[8];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[9];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[10];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[11];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[12];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[13];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[14];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[15];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[16];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[17];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[18];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[19];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[20];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[21];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[22];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[23];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[24];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[25];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[26];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[27];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[28];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[29];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[30];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[31];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[32];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[33];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[34];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[35];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[36];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[37];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[38];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[39];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[40];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[41];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[42];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[43];
switch ($this->Nr) {
case 10:
break;
case 14:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[56];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[57];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[58];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[59];
break;
case 12:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
break;
case 13:
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$s3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
$e0 = $dt0[($s0 >> 24) & 0xff] ^ $dt1[($s3 >> 16) & 0xff] ^ $dt2[($s2 >> 8) & 0xff] ^ $dt3[$s1 & 0xff] ^ $dw[48];
$e1 = $dt0[($s1 >> 24) & 0xff] ^ $dt1[($s0 >> 16) & 0xff] ^ $dt2[($s3 >> 8) & 0xff] ^ $dt3[$s2 & 0xff] ^ $dw[49];
$e2 = $dt0[($s2 >> 24) & 0xff] ^ $dt1[($s1 >> 16) & 0xff] ^ $dt2[($s0 >> 8) & 0xff] ^ $dt3[$s3 & 0xff] ^ $dw[50];
$e3 = $dt0[($s3 >> 24) & 0xff] ^ $dt1[($s2 >> 16) & 0xff] ^ $dt2[($s1 >> 8) & 0xff] ^ $dt3[$s0 & 0xff] ^ $dw[51];
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54];
$e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
break;
default: // 11
$s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44];
$s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45];
$s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46];
$e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47];
// Note: Here we skip $s3 but using $e3
$e0 = $s0;
$e1 = $s1;
$e2 = $s2;
// $e3 = $s3;
}
// invSubWord
$e0 = $sbox[$e0 & 0xff] | ($sbox[($e0 >> 8) & 0xff] << 8) | ($sbox[($e0 >> 16) & 0xff] << 16) | ($sbox[($e0 >> 24) & 0xff] << 24);
$e1 = $sbox[$e1 & 0xff] | ($sbox[($e1 >> 8) & 0xff] << 8) | ($sbox[($e1 >> 16) & 0xff] << 16) | ($sbox[($e1 >> 24) & 0xff] << 24);
$e2 = $sbox[$e2 & 0xff] | ($sbox[($e2 >> 8) & 0xff] << 8) | ($sbox[($e2 >> 16) & 0xff] << 16) | ($sbox[($e2 >> 24) & 0xff] << 24);
$e3 = $sbox[$e3 & 0xff] | ($sbox[($e3 >> 8) & 0xff] << 8) | ($sbox[($e3 >> 16) & 0xff] << 16) | ($sbox[($e3 >> 24) & 0xff] << 24);
// invShiftRows + addRoundKey
return pack('N*',
($e0 & 0xFF000000) ^ ($e3 & 0x00FF0000) ^ ($e2 & 0x0000FF00) ^ ($e1 & 0x000000FF) ^ $dw[0],
($e1 & 0xFF000000) ^ ($e0 & 0x00FF0000) ^ ($e3 & 0x0000FF00) ^ ($e2 & 0x000000FF) ^ $dw[1],
($e2 & 0xFF000000) ^ ($e1 & 0x00FF0000) ^ ($e0 & 0x0000FF00) ^ ($e3 & 0x000000FF) ^ $dw[2],
($e3 & 0xFF000000) ^ ($e2 & 0x00FF0000) ^ ($e1 & 0x0000FF00) ^ ($e0 & 0x000000FF) ^ $dw[3]
);
}
/**
* Treat consecutive "packets" as if they are a continuous buffer.
*
* The default behavior.
*
* @see Crypt_Rijndael::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
parent::enableContinuousBuffer();
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
$this->enbuffer['enmcrypt_init'] = true;
$this->debuffer['demcrypt_init'] = true;
}
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_Rijndael::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
parent::disableContinuousBuffer();
if (CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT) {
mcrypt_generic_init($this->enmcrypt, $this->key, $this->iv);
mcrypt_generic_init($this->demcrypt, $this->key, $this->iv);
}
}
} }
// vim: ts=4:sw=4:et: // vim: ts=4:sw=4:et:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,678 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of Blowfish.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/Blowfish.php');
*
* $blowfish = new Crypt_Blowfish();
*
* $blowfish->setKey('12345678901234567890123456789012');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $blowfish->decrypt($blowfish->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* 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.
*
* @category Crypt
* @package Crypt_Blowfish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
require_once('Base.php');
}
/**#@+
* @access public
* @see Crypt_Blowfish::encrypt()
* @see Crypt_Blowfish::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_BLOWFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_BLOWFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_BLOWFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_BLOWFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_BLOWFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Blowfish::Crypt_Blowfish()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_BLOWFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_BLOWFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**
* Pure-PHP implementation of Blowfish.
*
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @version 1.0
* @access public
* @package Crypt_Blowfish
*/
class Crypt_Blowfish extends Crypt_Base {
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var Integer
* @access private
*/
var $block_size = 8;
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 56;
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'BLOWFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @access private
*/
var $cipher_name_mcrypt = 'blowfish';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @access private
*/
var $cfb_init_len = 500;
/**
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
*
* S-Box 1
*
* @access private
* @var array
*/
var $sbox0 = array (
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
);
/**
* S-Box 1
*
* @access private
* @var array
*/
var $sbox1 = array(
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
);
/**
* S-Box 2
*
* @access private
* @var array
*/
var $sbox2 = array(
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
);
/**
* S-Box 3
*
* @access private
* @var array
*/
var $sbox3 = array(
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
);
/**
* P-Array consists of 18 32-bit subkeys
*
* @var array $parray
* @access private
*/
var $parray = array(
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
);
/**
* The BCTX-working Array
*
* Holds the expanded key [p] and the key-depended s-boxes [sb]
*
* @var array $bctx
* @access private
*/
var $bctx;
/**
* Holds the last used key
*
* @var Array
* @access private
*/
var $kl;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_BLOWFISH_MODE_ECB
*
* - CRYPT_BLOWFISH_MODE_CBC
*
* - CRYPT_BLOWFISH_MODE_CTR
*
* - CRYPT_BLOWFISH_MODE_CFB
*
* - CRYPT_BLOWFISH_MODE_OFB
*
* If not explictly set, CRYPT_BLOWFISH_MODE_CBC will be used.
*
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode
* @access public
*/
function Crypt_Blowfish($mode = CRYPT_BLOWFISH_MODE_CBC)
{
parent::Crypt_Base($mode);
}
/**
* Sets the key.
*
* Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long.
* If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible
* with mcrypt because mcrypt act this way with blowfish key's < 32 bits.
*
* If the key is more than 448-bits, we trim the excess bits.
*
* If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes.
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
*/
function setKey($key)
{
$keylength = strlen($key);
if (!$keylength) {
$key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
}
elseif ($keylength > 56) {
$key = substr($key, 0, 56);
}
parent::setKey($key);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key);
/* key-expanding p[] and S-Box building sb[] */
$this->bctx = array(
'p' => array(),
'sb' => array(
$this->sbox0,
$this->sbox1,
$this->sbox2,
$this->sbox3
)
);
// unpack binary string in unsigned chars
$key = array_values(unpack('C*', $this->key));
$keyl = count($key);
for ($j = 0, $i = 0; $i < 18; ++$i) {
// xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
for ($data = 0, $k = 0; $k < 4; ++$k) {
$data = ($data << 8) | $key[$j];
if (++$j >= $keyl) {
$j = 0;
}
}
$this->bctx['p'][] = $this->parray[$i] ^ $data;
}
// encrypt the zero-string, replace P1 and P2 with the encrypted data,
// encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
$data = "\0\0\0\0\0\0\0\0";
for ($i = 0; $i < 18; $i += 2) {
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
$this->bctx['p'][$i ] = $l;
$this->bctx['p'][$i + 1] = $r;
}
for ($i = 0; $i < 4; ++$i) {
for ($j = 0; $j < 256; $j += 2) {
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
$this->bctx['sb'][$i][$j ] = $l;
$this->bctx['sb'][$i][$j + 1] = $r;
}
}
}
/**
* Encrypts a block
*
* @access private
* @param String $in
* @return String
*/
function _encryptBlock($in)
{
$p = $this->bctx["p"];
// extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
$sb_0 = $this->bctx["sb"][0];
$sb_1 = $this->bctx["sb"][1];
$sb_2 = $this->bctx["sb"][2];
$sb_3 = $this->bctx["sb"][3];
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
}
/**
* Decrypts a block
*
* @access private
* @param String $in
* @return String
*/
function _decryptBlock($in)
{
$p = $this->bctx["p"];
$sb_0 = $this->bctx["sb"][0];
$sb_1 = $this->bctx["sb"][1];
$sb_2 = $this->bctx["sb"][2];
$sb_3 = $this->bctx["sb"][3];
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
for ($i = 17; $i > 2; $i-= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= $p[$i - 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
}
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Blowfish::_getLambdaFunctions();
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10);
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Crypt_Blowfish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Crypt_Blowfish, {$this->mode}";
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$p = $this->bctx['p'];
$init_crypt = '
static $sb_0, $sb_1, $sb_2, $sb_3;
if (!$sb_0) {
$sb_0 = $self->bctx["sb"][0];
$sb_1 = $self->bctx["sb"][1];
$sb_2 = $self->bctx["sb"][2];
$sb_3 = $self->bctx["sb"][3];
}
';
break;
default:
$p = array();
for ($i = 0; $i < 18; ++$i) {
$p[] = '$p_' . $i;
}
$init_crypt = '
list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
list(' . implode(',', $p) . ') = $self->bctx["p"];
';
}
// Generating encrypt code:
$encrypt_block = '
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
';
for ($i = 0; $i < 16; $i+= 2) {
$encrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= ' . $p[$i + 1] . ';
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
';
}
$encrypt_block.= '
$in = pack("N*",
$r ^ ' . $p[17] . ',
$l ^ ' . $p[16] . '
);
';
// Generating decrypt code:
$decrypt_block = '
$in = unpack("N*", $in);
$l = $in[1];
$r = $in[2];
';
for ($i = 17; $i > 2; $i-= 2) {
$decrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$r^= ' . $p[$i - 1] . ';
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
';
}
$decrypt_block.= '
$in = pack("N*",
$r ^ ' . $p[0] . ',
$l ^ ' . $p[1] . '
);
';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'init_encrypt' => '',
'init_decrypt' => '',
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
$this->inline_crypt = $lambda_functions[$code_hash];
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

File diff suppressed because it is too large Load diff

View file

@ -52,7 +52,6 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: Hash.php,v 1.6 2009/11/23 23:37:07 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
@ -83,6 +82,15 @@ define('CRYPT_HASH_MODE_HASH', 3);
* @package Crypt_Hash * @package Crypt_Hash
*/ */
class Crypt_Hash { class Crypt_Hash {
/**
* Hash Parameter
*
* @see Crypt_Hash::setHash()
* @var Integer
* @access private
*/
var $hashParam;
/** /**
* Byte-length of compression blocks / key (Internal HMAC) * Byte-length of compression blocks / key (Internal HMAC)
* *
@ -168,13 +176,26 @@ class Crypt_Hash {
* Keys can be of any length. * Keys can be of any length.
* *
* @access public * @access public
* @param String $key * @param optional String $key
*/ */
function setKey($key = false) function setKey($key = false)
{ {
$this->key = $key; $this->key = $key;
} }
/**
* Gets the hash function.
*
* As set by the constructor or by the setHash() method.
*
* @access public
* @return String
*/
function getHash()
{
return $this->hashParam;
}
/** /**
* Sets the hash function. * Sets the hash function.
* *
@ -183,7 +204,7 @@ class Crypt_Hash {
*/ */
function setHash($hash) function setHash($hash)
{ {
$hash = strtolower($hash); $this->hashParam = $hash = strtolower($hash);
switch ($hash) { switch ($hash) {
case 'md5-96': case 'md5-96':
case 'sha1-96': case 'sha1-96':
@ -350,7 +371,7 @@ class Crypt_Hash {
* Wrapper for MD5 * Wrapper for MD5
* *
* @access private * @access private
* @param String $text * @param String $m
*/ */
function _md5($m) function _md5($m)
{ {
@ -361,7 +382,7 @@ class Crypt_Hash {
* Wrapper for SHA1 * Wrapper for SHA1
* *
* @access private * @access private
* @param String $text * @param String $m
*/ */
function _sha1($m) function _sha1($m)
{ {
@ -374,7 +395,7 @@ class Crypt_Hash {
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}. * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
* *
* @access private * @access private
* @param String $text * @param String $m
*/ */
function _md2($m) function _md2($m)
{ {
@ -450,7 +471,7 @@ class Crypt_Hash {
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}. * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
* *
* @access private * @access private
* @param String $text * @param String $m
*/ */
function _sha256($m) function _sha256($m)
{ {
@ -555,7 +576,7 @@ class Crypt_Hash {
* Pure-PHP implementation of SHA384 and SHA512 * Pure-PHP implementation of SHA384 and SHA512
* *
* @access private * @access private
* @param String $text * @param String $m
*/ */
function _sha512($m) function _sha512($m)
{ {
@ -784,9 +805,8 @@ class Crypt_Hash {
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
* possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster. * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
* *
* @param String $string * @param Integer $...
* @param optional Integer $index * @return Integer
* @return String
* @see _sha256() * @see _sha256()
* @access private * @access private
*/ */

View file

@ -0,0 +1,656 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of RC2.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://tools.ietf.org/html/rfc2268}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/RC2.php');
*
* $rc2 = new Crypt_RC2();
*
* $rc2->setKey('abcdefgh');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $rc2->decrypt($rc2->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* 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.
*
* @category Crypt
* @package Crypt_RC2
* @author Patrick Monnerat <pm@datasphere.ch>
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
require_once('Base.php');
}
/**#@+
* @access public
* @see Crypt_RC2::encrypt()
* @see Crypt_RC2::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_RC2_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_RC2_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_RC2_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_RC2_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_RC2_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_RC2::Crypt_RC2()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_RC2_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_RC2_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**
* Pure-PHP implementation of RC2.
*
* @version 0.1.1
* @access public
* @package Crypt_RC2
*/
class Crypt_RC2 extends Crypt_Base {
/**
* Block Length of the cipher
*
* @see Crypt_Base::block_size
* @var Integer
* @access private
*/
var $block_size = 8;
/**
* The Key
*
* @see Crypt_Base::key
* @see setKey()
* @var String
* @access private
*/
var $key = "\0";
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 16; // = 128 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RC2';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @access private
*/
var $cipher_name_mcrypt = 'rc2';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @access private
*/
var $cfb_init_len = 500;
/**
* The key length in bits.
*
* @see Crypt_RC2::setKeyLength()
* @see Crypt_RC2::setKey()
* @var Integer
* @access private
* @internal Should be in range [1..1024].
* @internal Changing this value after setting the key has no effect.
*/
var $default_key_length = 1024;
/**
* The Key Schedule
*
* @see Crypt_RC2::_setupKey()
* @var Array
* @access private
*/
var $keys;
/**
* Key expansion randomization table.
* Twice the same 256-value sequence to save a modulus in key expansion.
*
* @see Crypt_RC2::setKey()
* @var Array
* @access private
*/
var $pitable = array(
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
);
/**
* Inverse key expansion randomization table.
*
* @see Crypt_RC2::setKey()
* @var Array
* @access private
*/
var $invpitable = array(
0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
);
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_RC2_MODE_ECB
*
* - CRYPT_RC2_MODE_CBC
*
* - CRYPT_RC2_MODE_CTR
*
* - CRYPT_RC2_MODE_CFB
*
* - CRYPT_RC2_MODE_OFB
*
* If not explictly set, CRYPT_RC2_MODE_CBC will be used.
*
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode
* @access public
*/
function Crypt_RC2($mode = CRYPT_RC2_MODE_CBC)
{
parent::Crypt_Base($mode);
$this->setKey('');
}
/**
* Sets the key length
*
* Valid key lengths are 1 to 1024.
* Calling this function after setting the key has no effect until the next
* Crypt_RC2::setKey() call.
*
* @access public
* @param Integer $length in bits
*/
function setKeyLength($length)
{
if ($length >= 1 && $length <= 1024) {
$this->default_key_length = $length;
}
}
/**
* Sets the key.
*
* Keys can be of any length. RC2, itself, uses 1 to 1024 bit keys (eg.
* strlen($key) <= 128), however, we only use the first 128 bytes if $key
* has more then 128 bytes in it, and set $key to a single null byte if
* it is empty.
*
* If the key is not explicitly set, it'll be assumed to be a single
* null byte.
*
* @see Crypt_Base::setKey()
* @access public
* @param String $key
* @param Integer $t1 optional Effective key length in bits.
*/
function setKey($key, $t1 = 0)
{
if ($t1 <= 0) {
$t1 = $this->default_key_length;
} else if ($t1 > 1024) {
$t1 = 1024;
}
// Key byte count should be 1..128.
$key = strlen($key) ? substr($key, 0, 128): "\x00";
$t = strlen($key);
// The mcrypt RC2 implementation only supports effective key length
// of 1024 bits. It is however possible to handle effective key
// lengths in range 1..1024 by expanding the key and applying
// inverse pitable mapping to the first byte before submitting it
// to mcrypt.
// Key expansion.
$l = array_values(unpack('C*', $key));
$t8 = ($t1 + 7) >> 3;
$tm = 0xFF >> (8 * $t8 - $t1);
// Expand key.
$pitable = $this->pitable;
for ($i = $t; $i < 128; $i++) {
$l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
}
$i = 128 - $t8;
$l[$i] = $pitable[$l[$i] & $tm];
while ($i--) {
$l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
}
// Prepare the key for mcrypt.
$l[0] = $this->invpitable[$l[0]];
array_unshift($l, 'C*');
parent::setKey(call_user_func_array('pack', $l));
}
/**
* Encrypts a block
*
* @see Crypt_Base::_encryptBlock()
* @see Crypt_Base::encrypt()
* @access private
* @param String $in
* @return String
*/
function _encryptBlock($in)
{
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
$keys = $this->keys;
$limit = 20;
$actions = array($limit => 44, 44 => 64);
$j = 0;
for (;;) {
// Mixing round.
$r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
$r0 |= $r0 >> 16;
$r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
$r1 |= $r1 >> 16;
$r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
$r2 |= $r2 >> 16;
$r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
$r3 |= $r3 >> 16;
if ($j == $limit) {
if ($limit == 64) {
break;
}
// Mashing round.
$r0 += $keys[$r3 & 0x3F];
$r1 += $keys[$r0 & 0x3F];
$r2 += $keys[$r1 & 0x3F];
$r3 += $keys[$r2 & 0x3F];
$limit = $actions[$limit];
}
}
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Decrypts a block
*
* @see Crypt_Base::_decryptBlock()
* @see Crypt_Base::decrypt()
* @access private
* @param String $in
* @return String
*/
function _decryptBlock($in)
{
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
$keys = $this->keys;
$limit = 44;
$actions = array($limit => 20, 20 => 0);
$j = 64;
for (;;) {
// R-mixing round.
$r3 = ($r3 | ($r3 << 16)) >> 5;
$r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
$r2 = ($r2 | ($r2 << 16)) >> 3;
$r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
$r1 = ($r1 | ($r1 << 16)) >> 2;
$r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
$r0 = ($r0 | ($r0 << 16)) >> 1;
$r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
if ($j == $limit) {
if (!$limit) {
break;
}
// R-mashing round.
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
$limit = $actions[$limit];
}
}
return pack('vvvv', $r0, $r1, $r2, $r3);
}
/**
* Creates the key schedule
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
// Key has already been expanded in Crypt_RC2::setKey():
// Only the first value must be altered.
$l = unpack('Ca/Cb/v*', $this->key);
array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
unset($l['a']);
unset($l['b']);
$this->keys = $l;
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions = &Crypt_RC2::_getLambdaFunctions();
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
// for the mixing rounds, for better inline crypt performance [~20% faster].
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
$keys = $this->keys;
if (count($lambda_functions) >= 10) {
foreach ($this->keys as $k => $v) {
$keys[$k] = '$keys[' . $k . ']';
}
}
$code_hash = md5(str_pad("Crypt_RC2, {$this->mode}, ", 32, "\0") . implode(',', $keys));
// Is there a re-usable $lambda_functions in there?
// If not, we have to create it.
if (!isset($lambda_functions[$code_hash])) {
// Init code for both, encrypt and decrypt.
$init_crypt = '$keys = $self->keys;';
// $in is the current 8 bytes block which has to be en/decrypt
$encrypt_block = $decrypt_block = '
$in = unpack("v4", $in);
$r0 = $in[1];
$r1 = $in[2];
$r2 = $in[3];
$r3 = $in[4];
';
// Create code for encryption.
$limit = 20;
$actions = array($limit => 44, 44 => 64);
$j = 0;
for (;;) {
// Mixing round.
$encrypt_block .= '
$r0 = (($r0 + ' . $keys[$j++] . ' +
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
$r0 |= $r0 >> 16;
$r1 = (($r1 + ' . $keys[$j++] . ' +
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
$r1 |= $r1 >> 16;
$r2 = (($r2 + ' . $keys[$j++] . ' +
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
$r2 |= $r2 >> 16;
$r3 = (($r3 + ' . $keys[$j++] . ' +
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
$r3 |= $r3 >> 16;';
if ($j == $limit) {
if ($limit == 64) {
break;
}
// Mashing round.
$encrypt_block .= '
$r0 += $keys[$r3 & 0x3F];
$r1 += $keys[$r0 & 0x3F];
$r2 += $keys[$r1 & 0x3F];
$r3 += $keys[$r2 & 0x3F];';
$limit = $actions[$limit];
}
}
$encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
// Create code for decryption.
$limit = 44;
$actions = array($limit => 20, 20 => 0);
$j = 64;
for (;;) {
// R-mixing round.
$decrypt_block .= '
$r3 = ($r3 | ($r3 << 16)) >> 5;
$r3 = ($r3 - ' . $keys[--$j] . ' -
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
$r2 = ($r2 | ($r2 << 16)) >> 3;
$r2 = ($r2 - ' . $keys[--$j] . ' -
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
$r1 = ($r1 | ($r1 << 16)) >> 2;
$r1 = ($r1 - ' . $keys[--$j] . ' -
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
$r0 = ($r0 | ($r0 << 16)) >> 1;
$r0 = ($r0 - ' . $keys[--$j] . ' -
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
if ($j == $limit) {
if (!$limit) {
break;
}
// R-mashing round.
$decrypt_block .= '
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
$limit = $actions[$limit];
}
}
$decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
// Creates the inline-crypt function
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
// Set the inline-crypt function as callback in: $this->inline_crypt
$this->inline_crypt = $lambda_functions[$code_hash];
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

View file

@ -14,7 +14,7 @@
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4} * - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
* *
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not * RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
* ARCFOUR or ARC4 because RC4 is how it is refered to in the SSH1 specification. * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
* *
* Here's a short example of how to use this library: * Here's a short example of how to use this library:
* <code> * <code>
@ -41,10 +41,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -58,10 +58,18 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: RC4.php,v 1.8 2009/06/09 04:00:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
require_once('Base.php');
}
/**#@+ /**#@+
* @access private * @access private
* @see Crypt_RC4::Crypt_RC4() * @see Crypt_RC4::Crypt_RC4()
@ -69,11 +77,11 @@
/** /**
* Toggles the internal implementation * Toggles the internal implementation
*/ */
define('CRYPT_RC4_MODE_INTERNAL', 1); define('CRYPT_RC4_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/** /**
* Toggles the mcrypt implementation * Toggles the mcrypt implementation
*/ */
define('CRYPT_RC4_MODE_MCRYPT', 2); define('CRYPT_RC4_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/ /**#@-*/
/**#@+ /**#@+
@ -92,7 +100,57 @@ define('CRYPT_RC4_DECRYPT', 1);
* @access public * @access public
* @package Crypt_RC4 * @package Crypt_RC4
*/ */
class Crypt_RC4 { class Crypt_RC4 extends Crypt_Base {
/**
* Block Length of the cipher
*
* RC4 is a stream cipher
* so we the block_size to 0
*
* @see Crypt_Base::block_size
* @var Integer
* @access private
*/
var $block_size = 0;
/**
* The default password key_size used by setPassword()
*
* @see Crypt_Base::password_key_size
* @see Crypt_Base::setPassword()
* @var Integer
* @access private
*/
var $password_key_size = 128; // = 1024 bits
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'RC4';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @access private
*/
var $cipher_name_mcrypt = 'arcfour';
/**
* Holds whether performance-optimized $inline_crypt() can/should be used.
*
* @see Crypt_Base::inline_crypt
* @var mixed
* @access private
*/
var $use_inline_crypt = false; // currently not available
/** /**
* The Key * The Key
* *
@ -103,190 +161,26 @@ class Crypt_RC4 {
var $key = "\0"; var $key = "\0";
/** /**
* The Key Stream for encryption * The Key Stream for decryption and encryption
*
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
* *
* @see Crypt_RC4::setKey() * @see Crypt_RC4::setKey()
* @var Array * @var Array
* @access private * @access private
*/ */
var $encryptStream = false; var $stream;
/**
* The Key Stream for decryption
*
* If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
*
* @see Crypt_RC4::setKey()
* @var Array
* @access private
*/
var $decryptStream = false;
/**
* The $i and $j indexes for encryption
*
* @see Crypt_RC4::_crypt()
* @var Integer
* @access private
*/
var $encryptIndex = 0;
/**
* The $i and $j indexes for decryption
*
* @see Crypt_RC4::_crypt()
* @var Integer
* @access private
*/
var $decryptIndex = 0;
/**
* The Encryption Algorithm
*
* Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
*
* @see Crypt_RC4::Crypt_RC4()
* @var Integer
* @access private
*/
var $mode;
/**
* Continuous Buffer status
*
* @see Crypt_RC4::enableContinuousBuffer()
* @var Boolean
* @access private
*/
var $continuousBuffer = false;
/** /**
* Default Constructor. * Default Constructor.
* *
* Determines whether or not the mcrypt extension should be used. * Determines whether or not the mcrypt extension should be used.
* *
* @see Crypt_Base::Crypt_Base()
* @return Crypt_RC4 * @return Crypt_RC4
* @access public * @access public
*/ */
function Crypt_RC4() function Crypt_RC4()
{ {
if ( !defined('CRYPT_RC4_MODE') ) { parent::Crypt_Base(CRYPT_MODE_STREAM);
switch (true) {
case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')) && in_array('arcfour', mcrypt_list_algorithms()):
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
break;
default:
define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
}
}
switch ( CRYPT_RC4_MODE ) {
case CRYPT_RC4_MODE_MCRYPT:
switch (true) {
case defined('MCRYPT_ARCFOUR'):
$this->mode = MCRYPT_ARCFOUR;
break;
case defined('MCRYPT_RC4');
$this->mode = MCRYPT_RC4;
}
$this->encryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
$this->decryptStream = mcrypt_module_open($this->mode, '', MCRYPT_MODE_STREAM, '');
}
}
/**
* Sets the key.
*
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
*
* @access public
* @param String $key
*/
function setKey($key)
{
$this->key = $key;
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
mcrypt_generic_init($this->encryptStream, $this->key, '');
mcrypt_generic_init($this->decryptStream, $this->key, '');
return;
}
$keyLength = strlen($key);
$keyStream = array();
for ($i = 0; $i < 256; $i++) {
$keyStream[$i] = $i;
}
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->encryptIndex = $this->decryptIndex = array(0, 0);
$this->encryptStream = $this->decryptStream = $keyStream;
}
/**
* Sets the password.
*
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2}:
* $hash, $salt, $count, $dkLen
*
* @param String $password
* @param optional String $method
* @access public
*/
function setPassword($password, $method = 'pbkdf2')
{
$key = '';
switch ($method) {
default: // 'pbkdf2'
list(, , $hash, $salt, $count) = func_get_args();
if (!isset($hash)) {
$hash = 'sha1';
}
// WPA and WPA2 use the SSID as the salt
if (!isset($salt)) {
$salt = 'phpseclib/salt';
}
// RFC2898#section-4.2 uses 1,000 iterations by default
// WPA and WPA2 use 4,096.
if (!isset($count)) {
$count = 1000;
}
if (!isset($dkLen)) {
$dkLen = 128;
}
if (!class_exists('Crypt_Hash')) {
require_once('Crypt/Hash.php');
}
$i = 1;
while (strlen($key) < $dkLen) {
//$dk.= $this->_pbkdf($password, $salt, $count, $i++);
$hmac = new Crypt_Hash();
$hmac->setHash($hash);
$hmac->setKey($password);
$f = $u = $hmac->hash($salt . pack('N', $i++));
for ($j = 2; $j <= $count; $j++) {
$u = $hmac->hash($u);
$f^= $u;
}
$key.= $f;
}
}
$this->setKey(substr($key, 0, $dkLen));
} }
/** /**
@ -312,15 +206,35 @@ class Crypt_RC4 {
{ {
} }
/**
* Sets the key.
*
* Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
* be used. If no key is explicitly set, it'll be assumed to be a single null byte.
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
*/
function setKey($key)
{
parent::setKey(substr($key, 0, 256));
}
/** /**
* Encrypts a message. * Encrypts a message.
* *
* @see Crypt_Base::decrypt()
* @see Crypt_RC4::_crypt() * @see Crypt_RC4::_crypt()
* @access public * @access public
* @param String $plaintext * @param String $plaintext
* @return String $ciphertext
*/ */
function encrypt($plaintext) function encrypt($plaintext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) {
return parent::encrypt($plaintext);
}
return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT); return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
} }
@ -330,15 +244,51 @@ class Crypt_RC4 {
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
* Atleast if the continuous buffer is disabled. * Atleast if the continuous buffer is disabled.
* *
* @see Crypt_Base::encrypt()
* @see Crypt_RC4::_crypt() * @see Crypt_RC4::_crypt()
* @access public * @access public
* @param String $ciphertext * @param String $ciphertext
* @return String $plaintext
*/ */
function decrypt($ciphertext) function decrypt($ciphertext)
{ {
if ($this->engine == CRYPT_MODE_MCRYPT) {
return parent::decrypt($ciphertext);
}
return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT); return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
} }
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
$key = $this->key;
$keyLength = strlen($key);
$keyStream = array();
for ($i = 0; $i < 256; $i++) {
$keyStream[$i] = $i;
}
$j = 0;
for ($i = 0; $i < 256; $i++) {
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
}
$this->stream = array();
$this->stream[CRYPT_RC4_DECRYPT] = $this->stream[CRYPT_RC4_ENCRYPT] = array(
0, // index $i
0, // index $j
$keyStream
);
}
/** /**
* Encrypts or decrypts a message. * Encrypts or decrypts a message.
* *
@ -347,173 +297,41 @@ class Crypt_RC4 {
* @access private * @access private
* @param String $text * @param String $text
* @param Integer $mode * @param Integer $mode
* @return String $text
*/ */
function _crypt($text, $mode) function _crypt($text, $mode)
{ {
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) { if ($this->changed) {
$keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream'; $this->_setup();
$this->changed = false;
if (!$this->continuousBuffer) {
mcrypt_generic_init($this->$keyStream, $this->key, '');
}
return mcrypt_generic($this->$keyStream, $text);
}
if ($this->encryptStream === false) {
$this->setKey($this->key);
}
switch ($mode) {
case CRYPT_RC4_ENCRYPT:
$keyStream = $this->encryptStream;
list($i, $j) = $this->encryptIndex;
break;
case CRYPT_RC4_DECRYPT:
$keyStream = $this->decryptStream;
list($i, $j) = $this->decryptIndex;
}
$newText = '';
for ($k = 0; $k < strlen($text); $k++) {
$i = ($i + 1) & 255;
$j = ($j + $keyStream[$i]) & 255;
$temp = $keyStream[$i];
$keyStream[$i] = $keyStream[$j];
$keyStream[$j] = $temp;
$temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
$newText.= chr(ord($text[$k]) ^ $temp);
} }
$stream = &$this->stream[$mode];
if ($this->continuousBuffer) { if ($this->continuousBuffer) {
switch ($mode) { $i = &$stream[0];
case CRYPT_RC4_ENCRYPT: $j = &$stream[1];
$this->encryptStream = $keyStream; $keyStream = &$stream[2];
$this->encryptIndex = array($i, $j); } else {
break; $i = $stream[0];
case CRYPT_RC4_DECRYPT: $j = $stream[1];
$this->decryptStream = $keyStream; $keyStream = $stream[2];
$this->decryptIndex = array($i, $j);
}
} }
return $newText; $len = strlen($text);
} for ($k = 0; $k < $len; ++$k) {
$i = ($i + 1) & 255;
$ksi = $keyStream[$i];
$j = ($j + $ksi) & 255;
$ksj = $keyStream[$j];
/** $keyStream[$i] = $ksj;
* Treat consecutive "packets" as if they are a continuous buffer. $keyStream[$j] = $ksi;
* $text[$k] = chr(ord($text[$k]) ^ $keyStream[($ksj + $ksi) & 255]);
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
* will yield different outputs:
*
* <code>
* echo $rc4->encrypt(substr($plaintext, 0, 8));
* echo $rc4->encrypt(substr($plaintext, 8, 8));
* </code>
* <code>
* echo $rc4->encrypt($plaintext);
* </code>
*
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
* another, as demonstrated with the following:
*
* <code>
* $rc4->encrypt(substr($plaintext, 0, 8));
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
* <code>
* echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
* </code>
*
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
*
* Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
* however, they are also less intuitive and more likely to cause you problems.
*
* @see Crypt_RC4::disableContinuousBuffer()
* @access public
*/
function enableContinuousBuffer()
{
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
mcrypt_generic_init($this->encryptStream, $this->key, '');
mcrypt_generic_init($this->decryptStream, $this->key, '');
} }
$this->continuousBuffer = true; return $text;
}
/**
* Treat consecutive packets as if they are a discontinuous buffer.
*
* The default behavior.
*
* @see Crypt_RC4::enableContinuousBuffer()
* @access public
*/
function disableContinuousBuffer()
{
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL ) {
$this->encryptIndex = $this->decryptIndex = array(0, 0);
$this->encryptStream = $this->decryptStream = false;
}
$this->continuousBuffer = false;
}
/**
* Dummy function.
*
* Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
* included is so that you can switch between a block cipher and a stream cipher transparently.
*
* @see Crypt_RC4::disablePadding()
* @access public
*/
function enablePadding()
{
}
/**
* Dummy function.
*
* @see Crypt_RC4::enablePadding()
* @access public
*/
function disablePadding()
{
}
/**
* Class destructor.
*
* Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
* needs to be called if mcrypt is being used.
*
* @access public
*/
function __destruct()
{
if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT ) {
$this->_closeMCrypt();
}
}
/**
* Properly close the MCrypt objects.
*
* @access prviate
*/
function _closeMCrypt()
{
mcrypt_module_close($this->encryptStream);
mcrypt_module_close($this->decryptStream);
} }
} }
// vim: ts=4:sw=4:et: // vim: ts=4:sw=4:et:
// vim6: fdl=1: // vim6: fdl=1:

View file

@ -65,17 +65,9 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMIX Jim Wigginton * @copyright MMIX Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: RSA.php,v 1.19 2010/09/12 21:58:54 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* Include Math_BigInteger
*/
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
/** /**
* Include Crypt_Random * Include Crypt_Random
*/ */
@ -83,15 +75,15 @@ if (!class_exists('Math_BigInteger')) {
// will trigger a call to __autoload() if you're wanting to auto-load classes // will trigger a call to __autoload() if you're wanting to auto-load classes
// call function_exists() a second time to stop the require_once from being called outside // call function_exists() a second time to stop the require_once from being called outside
// of the auto loader // of the auto loader
if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) { if (!function_exists('crypt_random_string')) {
require_once('Crypt/Random.php'); require_once('Random.php');
} }
/** /**
* Include Crypt_Hash * Include Crypt_Hash
*/ */
if (!class_exists('Crypt_Hash')) { if (!class_exists('Crypt_Hash')) {
require_once('Crypt/Hash.php'); require_once('Hash.php');
} }
/**#@+ /**#@+
@ -181,7 +173,6 @@ define('CRYPT_RSA_MODE_OPENSSL', 2);
*/ */
define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf'); define('CRYPT_RSA_OPENSSL_CONFIG', dirname(__FILE__) . '/../openssl.cnf');
/**#@+ /**#@+
* @access public * @access public
* @see Crypt_RSA::createKey() * @see Crypt_RSA::createKey()
@ -449,6 +440,14 @@ class Crypt_RSA {
*/ */
var $configFile; var $configFile;
/**
* Public key comment field.
*
* @var String
* @access private
*/
var $comment = 'phpseclib-generated-key';
/** /**
* The constructor * The constructor
* *
@ -461,22 +460,54 @@ class Crypt_RSA {
*/ */
function Crypt_RSA() function Crypt_RSA()
{ {
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
$this->configFile = CRYPT_RSA_OPENSSL_CONFIG; $this->configFile = CRYPT_RSA_OPENSSL_CONFIG;
if ( !defined('CRYPT_RSA_MODE') ) { if ( !defined('CRYPT_RSA_MODE') ) {
switch (true) { // Math/BigInteger's openssl requirements are a little less stringent than Crypt/RSA's. in particular,
case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>='): // Math/BigInteger doesn't require an openssl.cfg file whereas Crypt/RSA does. so if Math/BigInteger
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL); // can't use OpenSSL it can be pretty trivially assumed, then, that Crypt/RSA can't either.
if ( defined('MATH_BIGINTEGER_OPENSSL_DISABLE') ) {
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
}
switch ( !defined('CRYPT_RSA_MODE') ) { // ie. only run this if the above didn't set CRYPT_RSA_MODE already
case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile):
// some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
ob_start();
phpinfo();
$content = ob_get_contents();
ob_end_clean();
preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
$versions = array();
if (!empty($matches[1])) {
for ($i = 0; $i < count($matches[1]); $i++) {
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
}
}
// it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
switch (true) {
case !isset($versions['Header']):
case !isset($versions['Library']):
case $versions['Header'] == $versions['Library']:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_OPENSSL);
break;
default:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
}
break; break;
default: case true:
define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL); define('CRYPT_RSA_MODE', CRYPT_RSA_MODE_INTERNAL);
} }
} }
if (!defined('CRYPT_RSA_COMMENT')) {
define('CRYPT_RSA_COMMENT', 'phpseclib-generated-key');
}
$this->zero = new Math_BigInteger(); $this->zero = new Math_BigInteger();
$this->one = new Math_BigInteger(1); $this->one = new Math_BigInteger(1);
@ -642,12 +673,12 @@ class Crypt_RSA {
$exponents[$i] = $e->modInverse($temp); $exponents[$i] = $e->modInverse($temp);
} }
list($lcm) = $lcm['top']->divide($lcm['bottom']); list($temp) = $lcm['top']->divide($lcm['bottom']);
$gcd = $lcm->gcd($e); $gcd = $temp->gcd($e);
$i0 = 1; $i0 = 1;
} while (!$gcd->equals($this->one)); } while (!$gcd->equals($this->one));
$d = $e->modInverse($lcm); $d = $e->modInverse($temp);
$coefficients[2] = $primes[2]->modInverse($primes[1]); $coefficients[2] = $primes[2]->modInverse($primes[1]);
@ -720,16 +751,16 @@ class Crypt_RSA {
$key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: "; $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: ";
$encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none'; $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none';
$key.= $encryption; $key.= $encryption;
$key.= "\r\nComment: " . CRYPT_RSA_COMMENT . "\r\n"; $key.= "\r\nComment: " . $this->comment . "\r\n";
$public = pack('Na*Na*Na*', $public = pack('Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus'] strlen('ssh-rsa'), 'ssh-rsa', strlen($raw['publicExponent']), $raw['publicExponent'], strlen($raw['modulus']), $raw['modulus']
); );
$source = pack('Na*Na*Na*Na*', $source = pack('Na*Na*Na*Na*',
strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption, strlen('ssh-rsa'), 'ssh-rsa', strlen($encryption), $encryption,
strlen(CRYPT_RSA_COMMENT), CRYPT_RSA_COMMENT, strlen($public), $public strlen($this->comment), $this->comment, strlen($public), $public
); );
$public = base64_encode($public); $public = base64_encode($public);
$key.= "Public-Lines: " . ((strlen($public) + 32) >> 6) . "\r\n"; $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n";
$key.= chunk_split($public, 64); $key.= chunk_split($public, 64);
$private = pack('Na*Na*Na*Na*', $private = pack('Na*Na*Na*Na*',
strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'], strlen($raw['privateExponent']), $raw['privateExponent'], strlen($raw['prime1']), $raw['prime1'],
@ -760,7 +791,7 @@ class Crypt_RSA {
} }
$private = base64_encode($private); $private = base64_encode($private);
$key.= 'Private-Lines: ' . ((strlen($private) + 32) >> 6) . "\r\n"; $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n";
$key.= chunk_split($private, 64); $key.= chunk_split($private, 64);
if (!class_exists('Crypt_Hash')) { if (!class_exists('Crypt_Hash')) {
require_once('Crypt/Hash.php'); require_once('Crypt/Hash.php');
@ -853,7 +884,7 @@ class Crypt_RSA {
// mpint e // mpint e
// mpint n // mpint n
$RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus);
$RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . CRYPT_RSA_COMMENT; $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment;
return $RSAPublicKey; return $RSAPublicKey;
default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW or CRYPT_RSA_PUBLIC_FORMAT_PKCS1 default: // eg. CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW or CRYPT_RSA_PUBLIC_FORMAT_PKCS1
@ -960,13 +991,19 @@ class Crypt_RSA {
if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
$iv = pack('H*', trim($matches[2])); $iv = pack('H*', trim($matches[2]));
$symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key
$symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8)));
$ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-| #s', '', $key); $ciphertext = preg_replace('#.+(\r|\n|\r\n)\1|[\r\n]|-.+-| #s', '', $key);
$ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false; $ciphertext = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $ciphertext) ? base64_decode($ciphertext) : false;
if ($ciphertext === false) { if ($ciphertext === false) {
$ciphertext = $key; $ciphertext = $key;
} }
switch ($matches[1]) { switch ($matches[1]) {
case 'AES-256-CBC':
if (!class_exists('Crypt_AES')) {
require_once('Crypt/AES.php');
}
$crypto = new Crypt_AES();
break;
case 'AES-128-CBC': case 'AES-128-CBC':
if (!class_exists('Crypt_AES')) { if (!class_exists('Crypt_AES')) {
require_once('Crypt/AES.php'); require_once('Crypt/AES.php');
@ -984,6 +1021,7 @@ class Crypt_RSA {
if (!class_exists('Crypt_TripleDES')) { if (!class_exists('Crypt_TripleDES')) {
require_once('Crypt/TripleDES.php'); require_once('Crypt/TripleDES.php');
} }
$symkey = substr($symkey, 0, 24);
$crypto = new Crypt_TripleDES(); $crypto = new Crypt_TripleDES();
break; break;
case 'DES-CBC': case 'DES-CBC':
@ -1121,11 +1159,15 @@ class Crypt_RSA {
return $components; return $components;
case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH: case CRYPT_RSA_PUBLIC_FORMAT_OPENSSH:
$key = base64_decode(preg_replace('#^ssh-rsa | .+$#', '', $key)); $parts = explode(' ', $key, 3);
$key = isset($parts[1]) ? base64_decode($parts[1]) : false;
if ($key === false) { if ($key === false) {
return false; return false;
} }
$comment = isset($parts[2]) ? $parts[2] : false;
$cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa"; $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa";
if (strlen($key) <= 4) { if (strlen($key) <= 4) {
@ -1147,12 +1189,14 @@ class Crypt_RSA {
$realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256); $realModulus = new Math_BigInteger($this->_string_shift($key, $length), -256);
return strlen($key) ? false : array( return strlen($key) ? false : array(
'modulus' => $realModulus, 'modulus' => $realModulus,
'publicExponent' => $modulus 'publicExponent' => $modulus,
'comment' => $comment
); );
} else { } else {
return strlen($key) ? false : array( return strlen($key) ? false : array(
'modulus' => $modulus, 'modulus' => $modulus,
'publicExponent' => $publicExponent 'publicExponent' => $publicExponent,
'comment' => $comment
); );
} }
// http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
@ -1180,6 +1224,7 @@ class Crypt_RSA {
return false; return false;
} }
$encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
$comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
$publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3]));
$public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
@ -1297,9 +1342,6 @@ class Crypt_RSA {
break; break;
case 'D': case 'D':
$this->current = &$this->components['privateExponent']; $this->current = &$this->components['privateExponent'];
break;
default:
unset($this->current);
} }
$this->current = ''; $this->current = '';
} }
@ -1315,11 +1357,10 @@ class Crypt_RSA {
*/ */
function _stop_element_handler($parser, $name) function _stop_element_handler($parser, $name)
{ {
//$name = strtoupper($name); if (isset($this->current)) {
if ($name == 'RSAKEYVALUE') { $this->current = new Math_BigInteger(base64_decode($this->current), 256);
return; unset($this->current);
} }
$this->current = new Math_BigInteger(base64_decode($this->current), 256);
} }
/** /**
@ -1350,6 +1391,53 @@ class Crypt_RSA {
*/ */
function loadKey($key, $type = false) function loadKey($key, $type = false)
{ {
if (is_object($key) && strtolower(get_class($key)) == 'crypt_rsa') {
$this->privateKeyFormat = $key->privateKeyFormat;
$this->publicKeyFormat = $key->publicKeyFormat;
$this->k = $key->k;
$this->hLen = $key->hLen;
$this->sLen = $key->sLen;
$this->mgfHLen = $key->mgfHLen;
$this->encryptionMode = $key->encryptionMode;
$this->signatureMode = $key->signatureMode;
$this->password = $key->password;
$this->configFile = $key->configFile;
$this->comment = $key->comment;
if (is_object($key->hash)) {
$this->hash = new Crypt_Hash($key->hash->getHash());
}
if (is_object($key->mgfHash)) {
$this->mgfHash = new Crypt_Hash($key->mgfHash->getHash());
}
if (is_object($key->modulus)) {
$this->modulus = $key->modulus->copy();
}
if (is_object($key->exponent)) {
$this->exponent = $key->exponent->copy();
}
if (is_object($key->publicExponent)) {
$this->publicExponent = $key->publicExponent->copy();
}
$this->primes = array();
$this->exponents = array();
$this->coefficients = array();
foreach ($this->primes as $prime) {
$this->primes[] = $prime->copy();
}
foreach ($this->exponents as $exponent) {
$this->exponents[] = $exponent->copy();
}
foreach ($this->coefficients as $coefficient) {
$this->coefficients[] = $coefficient->copy();
}
return true;
}
if ($type === false) { if ($type === false) {
$types = array( $types = array(
CRYPT_RSA_PUBLIC_FORMAT_RAW, CRYPT_RSA_PUBLIC_FORMAT_RAW,
@ -1373,6 +1461,9 @@ class Crypt_RSA {
return false; return false;
} }
if (isset($components['comment']) && $components['comment'] !== false) {
$this->comment = $components['comment'];
}
$this->modulus = $components['modulus']; $this->modulus = $components['modulus'];
$this->k = strlen($this->modulus->toBytes()); $this->k = strlen($this->modulus->toBytes());
$this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent']; $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent'];
@ -1428,6 +1519,11 @@ class Crypt_RSA {
*/ */
function setPublicKey($key = false, $type = false) function setPublicKey($key = false, $type = false)
{ {
// if a public key has already been loaded return false
if (!empty($this->publicExponent)) {
return false;
}
if ($key === false && !empty($this->modulus)) { if ($key === false && !empty($this->modulus)) {
$this->publicExponent = $this->exponent; $this->publicExponent = $this->exponent;
return true; return true;
@ -1552,6 +1648,18 @@ class Crypt_RSA {
return $key !== false ? $key : ''; return $key !== false ? $key : '';
} }
/**
* __clone() magic method
*
* @access public
*/
function __clone()
{
$key = new Crypt_RSA();
$key->loadKey($this);
return $key;
}
/** /**
* Generates the smallest and largest numbers requiring $bits bits * Generates the smallest and largest numbers requiring $bits bits
* *
@ -1582,7 +1690,7 @@ class Crypt_RSA {
* DER-decode the length * DER-decode the length
* *
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 § 8.1.3} for more information. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
* *
* @access private * @access private
* @param String $string * @param String $string
@ -1603,7 +1711,7 @@ class Crypt_RSA {
* DER-encode the length * DER-encode the length
* *
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 § 8.1.3} for more information. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
* *
* @access private * @access private
* @param Integer $length * @param Integer $length
@ -1872,7 +1980,7 @@ class Crypt_RSA {
* *
* Protects against a particular type of timing attack described. * Protects against a particular type of timing attack described.
* *
* See {@link http://codahale.com/a-lesson-in-timing-attacks/ A Lesson In Timing Attacks (or, Dont use MessageDigest.isEquals)} * See {@link http://codahale.com/a-lesson-in-timing-attacks/ A Lesson In Timing Attacks (or, Don't use MessageDigest.isEquals)}
* *
* Thanks for the heads up singpolyma! * Thanks for the heads up singpolyma!
* *
@ -2135,6 +2243,7 @@ class Crypt_RSA {
} }
// EME-PKCS1-v1_5 encoding // EME-PKCS1-v1_5 encoding
$psLen = $this->k - $mLen - 3; $psLen = $this->k - $mLen - 3;
$ps = ''; $ps = '';
while (strlen($ps) != $psLen) { while (strlen($ps) != $psLen) {
@ -2142,7 +2251,14 @@ class Crypt_RSA {
$temp = str_replace("\x00", '', $temp); $temp = str_replace("\x00", '', $temp);
$ps.= $temp; $ps.= $temp;
} }
$em = chr(0) . chr(2) . $ps . chr(0) . $m; $type = 2;
// see the comments of _rsaes_pkcs1_v1_5_decrypt() to understand why this is being done
if (defined('CRYPT_RSA_PKCS15_COMPAT') && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) {
$type = 1;
// "The padding string PS shall consist of k-3-||D|| octets. ... for block type 01, they shall have value FF"
$ps = str_repeat("\xFF", $psLen);
}
$em = chr(0) . chr($type) . $ps . chr(0) . $m;
// RSA encryption // RSA encryption
$m = $this->_os2ip($em); $m = $this->_os2ip($em);
@ -2515,6 +2631,28 @@ class Crypt_RSA {
$this->signatureMode = $mode; $this->signatureMode = $mode;
} }
/**
* Set public key comment.
*
* @access public
* @param String $comment
*/
function setComment($comment)
{
$this->comment = $comment;
}
/**
* Get public key comment.
*
* @access public
* @return String
*/
function getComment()
{
return $this->comment;
}
/** /**
* Encryption * Encryption
* *

View file

@ -21,10 +21,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -38,10 +38,16 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: Random.php,v 1.9 2010/04/24 06:40:48 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* "Is Windows" test
*
* @access private
*/
define('CRYPT_RANDOM_IS_WINDOWS', strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
/** /**
* Generate a random string. * Generate a random string.
* *
@ -53,9 +59,9 @@
* @return String * @return String
* @access public * @access public
*/ */
function crypt_random_string($length) { function crypt_random_string($length)
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster {
if ((PHP_OS & "\xDF\xDF\xDF") === 'WIN') { if (CRYPT_RANDOM_IS_WINDOWS) {
// method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call.
// ie. class_alias is a function that was introduced in PHP 5.3 // ie. class_alias is a function that was introduced in PHP 5.3
if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) {
@ -143,7 +149,7 @@ function crypt_random_string($length) {
serialize($_POST) . serialize($_POST) .
serialize($_GET) . serialize($_GET) .
serialize($_COOKIE) . serialize($_COOKIE) .
serialize($_GLOBAL) . serialize($GLOBALS) .
serialize($_SESSION) . serialize($_SESSION) .
serialize($_OLD_SESSION) serialize($_OLD_SESSION)
)); ));

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,924 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of Twofish.
*
* Uses mcrypt, if available, and an internal implementation, otherwise.
*
* PHP versions 4 and 5
*
* Useful resources are as follows:
*
* - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Crypt/Twofish.php');
*
* $twofish = new Crypt_Twofish();
*
* $twofish->setKey('12345678901234567890123456789012');
*
* $plaintext = str_repeat('a', 1024);
*
* echo $twofish->decrypt($twofish->encrypt($plaintext));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* 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.
*
* @category Crypt
* @package Crypt_Twofish
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0
* @link http://phpseclib.sourceforge.net
*/
/**
* Include Crypt_Base
*
* Base cipher class
*/
if (!class_exists('Crypt_Base')) {
require_once('Base.php');
}
/**#@+
* @access public
* @see Crypt_Twofish::encrypt()
* @see Crypt_Twofish::decrypt()
*/
/**
* Encrypt / decrypt using the Counter mode.
*
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
*/
define('CRYPT_TWOFISH_MODE_CTR', CRYPT_MODE_CTR);
/**
* Encrypt / decrypt using the Electronic Code Book mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
*/
define('CRYPT_TWOFISH_MODE_ECB', CRYPT_MODE_ECB);
/**
* Encrypt / decrypt using the Code Book Chaining mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
*/
define('CRYPT_TWOFISH_MODE_CBC', CRYPT_MODE_CBC);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
*/
define('CRYPT_TWOFISH_MODE_CFB', CRYPT_MODE_CFB);
/**
* Encrypt / decrypt using the Cipher Feedback mode.
*
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
*/
define('CRYPT_TWOFISH_MODE_OFB', CRYPT_MODE_OFB);
/**#@-*/
/**#@+
* @access private
* @see Crypt_Twofish::Crypt_Twofish()
*/
/**
* Toggles the internal implementation
*/
define('CRYPT_TWOFISH_MODE_INTERNAL', CRYPT_MODE_INTERNAL);
/**
* Toggles the mcrypt implementation
*/
define('CRYPT_TWOFISH_MODE_MCRYPT', CRYPT_MODE_MCRYPT);
/**#@-*/
/**
* Pure-PHP implementation of Twofish.
*
* @author Jim Wigginton <terrafrost@php.net>
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
* @version 1.0
* @access public
* @package Crypt_Twofish
*/
class Crypt_Twofish extends Crypt_Base {
/**
* The namespace used by the cipher for its constants.
*
* @see Crypt_Base::const_namespace
* @var String
* @access private
*/
var $const_namespace = 'TWOFISH';
/**
* The mcrypt specific name of the cipher
*
* @see Crypt_Base::cipher_name_mcrypt
* @var String
* @access private
*/
var $cipher_name_mcrypt = 'twofish';
/**
* Optimizing value while CFB-encrypting
*
* @see Crypt_Base::cfb_init_len
* @var Integer
* @access private
*/
var $cfb_init_len = 800;
/**
* Q-Table
*
* @var Array
* @access private
*/
var $q0 = array (
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
);
/**
* Q-Table
*
* @var Array
* @access private
*/
var $q1 = array (
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
);
/**
* M-Table
*
* @var Array
* @access private
*/
var $m0 = array (
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
);
/**
* M-Table
*
* @var Array
* @access private
*/
var $m1 = array (
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
);
/**
* M-Table
*
* @var Array
* @access private
*/
var $m2 = array (
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
);
/**
* M-Table
*
* @var Array
* @access private
*/
var $m3 = array (
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
);
/**
* The Key Schedule Array
*
* @var Array
* @access private
*/
var $K = array();
/**
* The Key depended S-Table 0
*
* @var Array
* @access private
*/
var $S0 = array();
/**
* The Key depended S-Table 1
*
* @var Array
* @access private
*/
var $S1 = array();
/**
* The Key depended S-Table 2
*
* @var Array
* @access private
*/
var $S2 = array();
/**
* The Key depended S-Table 3
*
* @var Array
* @access private
*/
var $S3 = array();
/**
* Holds the last used key
*
* @var Array
* @access private
*/
var $kl;
/**
* Default Constructor.
*
* Determines whether or not the mcrypt extension should be used.
*
* $mode could be:
*
* - CRYPT_TWOFISH_MODE_ECB
*
* - CRYPT_TWOFISH_MODE_CBC
*
* - CRYPT_TWOFISH_MODE_CTR
*
* - CRYPT_TWOFISH_MODE_CFB
*
* - CRYPT_TWOFISH_MODE_OFB
*
* If not explictly set, CRYPT_TWOFISH_MODE_CBC will be used.
*
* @see Crypt_Base::Crypt_Base()
* @param optional Integer $mode
* @access public
*/
function Crypt_Twofish($mode = CRYPT_TWOFISH_MODE_CBC)
{
parent::Crypt_Base($mode);
}
/**
* Sets the key.
*
* Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long.
* If the key is less than 256-bits we round the length up to the closest valid key length,
* padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits.
*
* If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes.
*
* @access public
* @see Crypt_Base::setKey()
* @param String $key
*/
function setKey($key)
{
$keylength = strlen($key);
switch (true) {
case $keylength <= 16:
$key = str_pad($key, 16, "\0");
break;
case $keylength <= 24:
$key = str_pad($key, 24, "\0");
break;
case $keylength < 32:
$key = str_pad($key, 32, "\0");
break;
case $keylength > 32:
$key = substr($key, 0, 32);
}
parent::setKey($key);
}
/**
* Setup the key (expansion)
*
* @see Crypt_Base::_setupKey()
* @access private
*/
function _setupKey()
{
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
// already expanded
return;
}
$this->kl = array('key' => $this->key);
/* Key expanding and generating the key-depended s-boxes */
$le_longs = unpack('V*', $this->key);
$key = unpack('C*', $this->key);
$m0 = $this->m0;
$m1 = $this->m1;
$m2 = $this->m2;
$m3 = $this->m3;
$q0 = $this->q0;
$q1 = $this->q1;
$K = $S0 = $S1 = $S2 = $S3 = array();
switch (strlen($this->key)) {
case 16:
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) {
$A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
}
break;
case 24:
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
}
break;
default: // 32
list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
$A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
$m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
$m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
$m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
$B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
$m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
$m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
$S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
$S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
$S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
}
}
$this->K = $K;
$this->S0 = $S0;
$this->S1 = $S1;
$this->S2 = $S2;
$this->S3 = $S3;
}
/**
* _mdsrem function using by the twofish cipher algorithm
*
* @access private
* @param String $A
* @param String $B
* @return Array
*/
function _mdsrem($A, $B)
{
// No gain by unrolling this loop.
for ($i = 0; $i < 8; ++$i) {
// Get most significant coefficient.
$t = 0xff & ($B >> 24);
// Shift the others up.
$B = ($B << 8) | (0xff & ($A >> 24));
$A<<= 8;
$u = $t << 1;
// Subtract the modular polynomial on overflow.
if ($t & 0x80) {
$u^= 0x14d;
}
// Remove t * (a * x^2 + 1).
$B ^= $t ^ ($u << 16);
// Form u = a*t + t/a = t*(a + 1/a).
$u^= 0x7fffffff & ($t >> 1);
// Add the modular polynomial on underflow.
if ($t & 0x01) $u^= 0xa6 ;
// Remove t * (a + 1/a) * (x^3 + x).
$B^= ($u << 24) | ($u << 8);
}
return array(
0xff & $B >> 24,
0xff & $B >> 16,
0xff & $B >> 8,
0xff & $B);
}
/**
* Encrypts a block
*
* @access private
* @param String $in
* @return String
*/
function _encryptBlock($in)
{
$S0 = $this->S0;
$S1 = $this->S1;
$S2 = $this->S2;
$S3 = $this->S3;
$K = $this->K;
$in = unpack("V4", $in);
$R0 = $K[0] ^ $in[1];
$R1 = $K[1] ^ $in[2];
$R2 = $K[2] ^ $in[3];
$R3 = $K[3] ^ $in[4];
$ki = 7;
while ($ki < 39) {
$t0 = $S0[ $R0 & 0xff] ^
$S1[($R0 >> 8) & 0xff] ^
$S2[($R0 >> 16) & 0xff] ^
$S3[($R0 >> 24) & 0xff];
$t1 = $S0[($R1 >> 24) & 0xff] ^
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= $t0 + $t1 + $K[++$ki];
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
$S2[($R2 >> 16) & 0xff] ^
$S3[($R2 >> 24) & 0xff];
$t1 = $S0[($R3 >> 24) & 0xff] ^
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + $K[++$ki]);
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
}
return pack("V4", $K[4] ^ $R2,
$K[5] ^ $R3,
$K[6] ^ $R0,
$K[7] ^ $R1);
}
/**
* Decrypts a block
*
* @access private
* @param String $in
* @return String
*/
function _decryptBlock($in)
{
$S0 = $this->S0;
$S1 = $this->S1;
$S2 = $this->S2;
$S3 = $this->S3;
$K = $this->K;
$in = unpack("V4", $in);
$R0 = $K[4] ^ $in[1];
$R1 = $K[5] ^ $in[2];
$R2 = $K[6] ^ $in[3];
$R3 = $K[7] ^ $in[4];
$ki = 40;
while ($ki > 8) {
$t0 = $S0[$R0 & 0xff] ^
$S1[$R0 >> 8 & 0xff] ^
$S2[$R0 >> 16 & 0xff] ^
$S3[$R0 >> 24 & 0xff];
$t1 = $S0[$R1 >> 24 & 0xff] ^
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + $K[--$ki];
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
$S2[$R2 >> 16 & 0xff] ^
$S3[$R2 >> 24 & 0xff];
$t1 = $S0[$R3 >> 24 & 0xff] ^
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + $K[--$ki];
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
}
return pack("V4", $K[0] ^ $R2,
$K[1] ^ $R3,
$K[2] ^ $R0,
$K[3] ^ $R1);
}
/**
* Setup the performance-optimized function for de/encrypt()
*
* @see Crypt_Base::_setupInlineCrypt()
* @access private
*/
function _setupInlineCrypt()
{
$lambda_functions =& Crypt_Twofish::_getLambdaFunctions();
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
switch (true) {
case $gen_hi_opt_code:
$code_hash = md5(str_pad("Crypt_Twofish, {$this->mode}, ", 32, "\0") . $this->key);
break;
default:
$code_hash = "Crypt_Twofish, {$this->mode}";
}
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
$K = $this->K;
$init_crypt = '
static $S0, $S1, $S2, $S3;
if (!$S0) {
for ($i = 0; $i < 256; ++$i) {
$S0[] = (int)$self->S0[$i];
$S1[] = (int)$self->S1[$i];
$S2[] = (int)$self->S2[$i];
$S3[] = (int)$self->S3[$i];
}
}
';
break;
default:
$K = array();
for ($i = 0; $i < 40; ++$i) {
$K[] = '$K_' . $i;
}
$init_crypt = '
$S0 = $self->S0;
$S1 = $self->S1;
$S2 = $self->S2;
$S3 = $self->S3;
list(' . implode(',', $K) . ') = $self->K;
';
}
// Generating encrypt code:
$encrypt_block = '
$in = unpack("V4", $in);
$R0 = '.$K[0].' ^ $in[1];
$R1 = '.$K[1].' ^ $in[2];
$R2 = '.$K[2].' ^ $in[3];
$R3 = '.$K[3].' ^ $in[4];
';
for ($ki = 7, $i = 0; $i < 8; ++$i) {
$encrypt_block.= '
$t0 = $S0[ $R0 & 0xff] ^
$S1[($R0 >> 8) & 0xff] ^
$S2[($R0 >> 16) & 0xff] ^
$S3[($R0 >> 24) & 0xff];
$t1 = $S0[($R1 >> 24) & 0xff] ^
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= ($t0 + $t1 + '.$K[++$ki].');
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
$S2[($R2 >> 16) & 0xff] ^
$S3[($R2 >> 24) & 0xff];
$t1 = $S0[($R3 >> 24) & 0xff] ^
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + '.$K[++$ki].');
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
';
}
$encrypt_block.= '
$in = pack("V4", '.$K[4].' ^ $R2,
'.$K[5].' ^ $R3,
'.$K[6].' ^ $R0,
'.$K[7].' ^ $R1);
';
// Generating decrypt code:
$decrypt_block = '
$in = unpack("V4", $in);
$R0 = '.$K[4].' ^ $in[1];
$R1 = '.$K[5].' ^ $in[2];
$R2 = '.$K[6].' ^ $in[3];
$R3 = '.$K[7].' ^ $in[4];
';
for ($ki = 40, $i = 0; $i < 8; ++$i) {
$decrypt_block.= '
$t0 = $S0[$R0 & 0xff] ^
$S1[$R0 >> 8 & 0xff] ^
$S2[$R0 >> 16 & 0xff] ^
$S3[$R0 >> 24 & 0xff];
$t1 = $S0[$R1 >> 24 & 0xff] ^
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
$S2[$R2 >> 16 & 0xff] ^
$S3[$R2 >> 24 & 0xff];
$t1 = $S0[$R3 >> 24 & 0xff] ^
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
';
}
$decrypt_block.= '
$in = pack("V4", '.$K[0].' ^ $R2,
'.$K[1].' ^ $R3,
'.$K[2].' ^ $R0,
'.$K[3].' ^ $R1);
';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
array(
'init_crypt' => $init_crypt,
'init_encrypt' => '',
'init_decrypt' => '',
'encrypt_block' => $encrypt_block,
'decrypt_block' => $decrypt_block
)
);
}
$this->inline_crypt = $lambda_functions[$code_hash];
}
}
// vim: ts=4:sw=4:et:
// vim6: fdl=1:

View file

@ -34,8 +34,7 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright MMXII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id$ * @link http://phpseclib.sourceforge.net
* @link htp://phpseclib.sourceforge.net
*/ */
/** /**
@ -298,12 +297,12 @@ class File_ANSI {
} }
// http://ascii-table.com/ansi-escape-sequences-vt-100.php // http://ascii-table.com/ansi-escape-sequences-vt-100.php
switch ($this->ansi) { switch ($this->ansi) {
case "\x1B[H": case "\x1B[H": // Move cursor to upper left corner
$this->old_x = $this->x; $this->old_x = $this->x;
$this->old_y = $this->y; $this->old_y = $this->y;
$this->x = $this->y = 0; $this->x = $this->y = 0;
break; break;
case "\x1B[J": case "\x1B[J": // Clear screen from cursor down
$this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y)); $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
$this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, '')); $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
@ -314,36 +313,45 @@ class File_ANSI {
array_shift($this->history); array_shift($this->history);
array_shift($this->history_attrs); array_shift($this->history_attrs);
} }
case "\x1B[K": case "\x1B[K": // Clear screen from cursor right
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
array_splice($this->attrs[$this->y], $this->x + 1); array_splice($this->attrs[$this->y], $this->x + 1);
break; break;
case "\x1B[2K": // Clear entire line
$this->screen[$this->y] = str_repeat(' ', $this->x);
$this->attrs[$this->y] = $this->attr_row;
break;
case "\x1B[?1h": // set cursor key to application case "\x1B[?1h": // set cursor key to application
case "\x1B[?25h": // show the cursor
break;
case "\x1BE": // Move to next line
$this->_newLine();
$this->x = 0;
break; break;
default: default:
switch (true) { switch (true) {
case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
$this->old_x = $this->x; $this->old_x = $this->x;
$this->old_y = $this->y; $this->old_y = $this->y;
$this->x = $match[2] - 1; $this->x = $match[2] - 1;
$this->y = $match[1] - 1; $this->y = $match[1] - 1;
break; break;
case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
$this->old_x = $this->x; $this->old_x = $this->x;
$x = $match[1] - 1; $x = $match[1] - 1;
break; break;
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
break; break;
case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
$mods = explode(';', $match[1]); $mods = explode(';', $match[1]);
foreach ($mods as $mod) { foreach ($mods as $mod) {
switch ($mod) { switch ($mod) {
case 0: case 0: // Turn off character attributes
$this->attrs[$this->y][$this->x] = ''; $this->attrs[$this->y][$this->x] = '';
if ($this->bold) $this->attrs[$this->y][$this->x].= '</b>'; if ($this->bold) $this->attrs[$this->y][$this->x].= '</b>';
if ($this->underline) $this->attrs[$this->y][$this->x].= '</underline>'; if ($this->underline) $this->attrs[$this->y][$this->x].= '</u>';
if ($this->blink) $this->attrs[$this->y][$this->x].= '</blink>'; if ($this->blink) $this->attrs[$this->y][$this->x].= '</blink>';
if ($this->color) $this->attrs[$this->y][$this->x].= '</span>'; if ($this->color) $this->attrs[$this->y][$this->x].= '</span>';
@ -355,25 +363,25 @@ class File_ANSI {
$this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false; $this->bold = $this->underline = $this->blink = $this->color = $this->reverse = false;
break; break;
case 1: case 1: // Turn bold mode on
if (!$this->bold) { if (!$this->bold) {
$this->attrs[$this->y][$this->x] = '<b>'; $this->attrs[$this->y][$this->x] = '<b>';
$this->bold = true; $this->bold = true;
} }
break; break;
case 4: case 4: // Turn underline mode on
if (!$this->underline) { if (!$this->underline) {
$this->attrs[$this->y][$this->x] = '<u>'; $this->attrs[$this->y][$this->x] = '<u>';
$this->underline = true; $this->underline = true;
} }
break; break;
case 5: case 5: // Turn blinking mode on
if (!$this->blink) { if (!$this->blink) {
$this->attrs[$this->y][$this->x] = '<blink>'; $this->attrs[$this->y][$this->x] = '<blink>';
$this->blink = true; $this->blink = true;
} }
break; break;
case 7: case 7: // Turn reverse video on
$this->reverse = !$this->reverse; $this->reverse = !$this->reverse;
$temp = $this->background; $temp = $this->background;
$this->background = $this->foreground; $this->background = $this->foreground;
@ -384,7 +392,7 @@ class File_ANSI {
} }
$this->color = true; $this->color = true;
break; break;
default: default: // set colors
//$front = $this->reverse ? &$this->background : &$this->foreground; //$front = $this->reverse ? &$this->background : &$this->foreground;
$front = &$this->{ $this->reverse ? 'background' : 'foreground' }; $front = &$this->{ $this->reverse ? 'background' : 'foreground' };
//$back = $this->reverse ? &$this->foreground : &$this->background; //$back = $this->reverse ? &$this->foreground : &$this->background;
@ -424,7 +432,7 @@ class File_ANSI {
} }
break; break;
default: default:
echo "{$this->ansi} unsupported\r\n"; user_error("{$this->ansi} unsupported\r\n");
} }
} }
$this->ansi = ''; $this->ansi = '';
@ -436,25 +444,7 @@ class File_ANSI {
$this->x = 0; $this->x = 0;
break; break;
case "\n": case "\n":
//if ($this->y < $this->max_y) { $this->_newLine();
// $this->y++;
//}
while ($this->y >= $this->max_y) {
$this->history = array_merge($this->history, array(array_shift($this->screen)));
$this->screen[] = '';
$this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
$this->attrs[] = $this->attr_row;
if (count($this->history) >= $this->max_history) {
array_shift($this->history);
array_shift($this->history_attrs);
}
$this->y--;
}
$this->y++;
break; break;
case "\x0F": // shift case "\x0F": // shift
break; break;
@ -479,6 +469,36 @@ class File_ANSI {
} }
} }
/**
* Add a new line
*
* Also update the $this->screen and $this->history buffers
*
* @access private
*/
function _newLine()
{
//if ($this->y < $this->max_y) {
// $this->y++;
//}
while ($this->y >= $this->max_y) {
$this->history = array_merge($this->history, array(array_shift($this->screen)));
$this->screen[] = '';
$this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
$this->attrs[] = $this->attr_row;
if (count($this->history) >= $this->max_history) {
array_shift($this->history);
array_shift($this->history_attrs);
}
$this->y--;
}
$this->y++;
}
/** /**
* Returns the current screen without preformating * Returns the current screen without preformating
* *
@ -537,4 +557,4 @@ class File_ANSI {
return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>'; return '<pre style="color: white; background: black" width="' . ($this->max_x + 1) . '">' . $scrollback . '</pre>';
} }
} }

View file

@ -37,17 +37,9 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright MMXII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id$
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* Include Math_BigInteger
*/
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
/**#@+ /**#@+
* Tag Classes * Tag Classes
* *
@ -249,6 +241,22 @@ class File_ASN1 {
FILE_ASN1_TYPE_VISIBLE_STRING => 1, FILE_ASN1_TYPE_VISIBLE_STRING => 1,
); );
/**
* Default Constructor.
*
* @access public
*/
function File_ASN1()
{
static $static_init = null;
if (!$static_init) {
$static_init = true;
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
}
}
/** /**
* Parse BER-encoding * Parse BER-encoding
* *
@ -304,12 +312,12 @@ class File_ASN1 {
} while ( $loop ); } while ( $loop );
} }
// Length, as discussed in § 8.1.3 of X.690-0207.pdf#page=13 // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
$length = ord($this->_string_shift($encoded)); $length = ord($this->_string_shift($encoded));
$start++; $start++;
if ( $length == 0x80 ) { // indefinite length if ( $length == 0x80 ) { // indefinite length
// "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
// immediately available." -- § 8.1.3.2.c // immediately available." -- paragraph 8.1.3.2.c
//if ( !$constructed ) { //if ( !$constructed ) {
// return false; // return false;
//} //}
@ -319,11 +327,15 @@ class File_ASN1 {
// support it up to four. // support it up to four.
$length&= 0x7F; $length&= 0x7F;
$temp = $this->_string_shift($encoded, $length); $temp = $this->_string_shift($encoded, $length);
// tags of indefinite length don't really have a header length; this length includes the tag
$current+= array('headerlength' => $length + 2);
$start+= $length; $start+= $length;
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4))); extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
} else {
$current+= array('headerlength' => 2);
} }
// End-of-content, see §§ 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2 // End-of-content, see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
if (!$type && !$length) { if (!$type && !$length) {
return $decoded; return $decoded;
} }
@ -349,6 +361,7 @@ class File_ASN1 {
'content' => $constructed ? $this->_decode_ber($content, $start) : $content, 'content' => $constructed ? $this->_decode_ber($content, $start) : $content,
'length' => $length + $start - $current['start'] 'length' => $length + $start - $current['start']
) + $current; ) + $current;
$start+= $length;
continue 2; continue 2;
} }
@ -357,7 +370,7 @@ class File_ASN1 {
// decode UNIVERSAL tags // decode UNIVERSAL tags
switch ($tag) { switch ($tag) {
case FILE_ASN1_TYPE_BOOLEAN: case FILE_ASN1_TYPE_BOOLEAN:
// "The contents octets shall consist of a single octet." -- § 8.2.1 // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
//if (strlen($content) != 1) { //if (strlen($content) != 1) {
// return false; // return false;
//} //}
@ -410,7 +423,7 @@ class File_ASN1 {
} }
break; break;
case FILE_ASN1_TYPE_NULL: case FILE_ASN1_TYPE_NULL:
// "The contents octets shall not contain any octets." -- § 8.8.2 // "The contents octets shall not contain any octets." -- paragraph 8.8.2
//if (strlen($content)) { //if (strlen($content)) {
// return false; // return false;
//} //}
@ -441,7 +454,7 @@ class File_ASN1 {
/* Each character string type shall be encoded as if it had been declared: /* Each character string type shall be encoded as if it had been declared:
[UNIVERSAL x] IMPLICIT OCTET STRING [UNIVERSAL x] IMPLICIT OCTET STRING
-- X.690-0207.pdf#page=23 (§ 8.21.3) -- X.690-0207.pdf#page=23 (paragraph 8.21.3)
Per that, we're not going to do any validation. If there are any illegal characters in the string, Per that, we're not going to do any validation. If there are any illegal characters in the string,
we don't really care */ we don't really care */
@ -487,12 +500,15 @@ class File_ASN1 {
* *
* Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format. * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
* *
* "Special" mappings may be applied on a per tag-name basis via $special.
*
* @param Array $decoded * @param Array $decoded
* @param Array $mapping * @param Array $mapping
* @param Array $special
* @return Array * @return Array
* @access public * @access public
*/ */
function asn1map($decoded, $mapping) function asn1map($decoded, $mapping, $special = array())
{ {
if (isset($mapping['explicit'])) { if (isset($mapping['explicit'])) {
$decoded = $decoded['content'][0]; $decoded = $decoded['content'][0];
@ -506,7 +522,7 @@ class File_ASN1 {
} }
$inmap = $this->ANYmap[$intype]; $inmap = $this->ANYmap[$intype];
if (is_string($inmap)) { if (is_string($inmap)) {
return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping)); return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping, $special));
} }
break; break;
case $mapping['type'] == FILE_ASN1_TYPE_CHOICE: case $mapping['type'] == FILE_ASN1_TYPE_CHOICE:
@ -514,15 +530,18 @@ class File_ASN1 {
switch (true) { switch (true) {
case isset($option['constant']) && $option['constant'] == $decoded['constant']: case isset($option['constant']) && $option['constant'] == $decoded['constant']:
case !isset($option['constant']) && $option['type'] == $decoded['type']: case !isset($option['constant']) && $option['type'] == $decoded['type']:
$value = $this->asn1map($decoded, $option); $value = $this->asn1map($decoded, $option, $special);
break; break;
case !isset($option['constant']) && $option['type'] == FILE_ASN1_TYPE_CHOICE: case !isset($option['constant']) && $option['type'] == FILE_ASN1_TYPE_CHOICE:
$v = $this->asn1map($decoded, $option); $v = $this->asn1map($decoded, $option, $special);
if (isset($v)) { if (isset($v)) {
$value = $v; $value = $v;
} }
} }
if (isset($value)) { if (isset($value)) {
if (isset($special[$key])) {
$value = call_user_func($special[$key], $value);
}
return array($key => $value); return array($key => $value);
} }
} }
@ -547,7 +566,7 @@ class File_ASN1 {
if (isset($mapping['min']) && isset($mapping['max'])) { if (isset($mapping['min']) && isset($mapping['max'])) {
$child = $mapping['children']; $child = $mapping['children'];
foreach ($decoded['content'] as $content) { foreach ($decoded['content'] as $content) {
if (($map[] = $this->asn1map($content, $child)) === NULL) { if (($map[] = $this->asn1map($content, $child, $special)) === NULL) {
return NULL; return NULL;
} }
} }
@ -591,12 +610,15 @@ class File_ASN1 {
if ($maymatch) { if ($maymatch) {
// Attempt submapping. // Attempt submapping.
$candidate = $this->asn1map($temp, $child); $candidate = $this->asn1map($temp, $child, $special);
$maymatch = $candidate !== NULL; $maymatch = $candidate !== NULL;
} }
if ($maymatch) { if ($maymatch) {
// Got the match: use it. // Got the match: use it.
if (isset($special[$key])) {
$candidate = call_user_func($special[$key], $candidate);
}
$map[$key] = $candidate; $map[$key] = $candidate;
$i++; $i++;
} elseif (isset($child['default'])) { } elseif (isset($child['default'])) {
@ -617,7 +639,7 @@ class File_ASN1 {
if (isset($mapping['min']) && isset($mapping['max'])) { if (isset($mapping['min']) && isset($mapping['max'])) {
$child = $mapping['children']; $child = $mapping['children'];
foreach ($decoded['content'] as $content) { foreach ($decoded['content'] as $content) {
if (($map[] = $this->asn1map($content, $child)) === NULL) { if (($map[] = $this->asn1map($content, $child, $special)) === NULL) {
return NULL; return NULL;
} }
} }
@ -660,7 +682,7 @@ class File_ASN1 {
if ($maymatch) { if ($maymatch) {
// Attempt submapping. // Attempt submapping.
$candidate = $this->asn1map($temp, $child); $candidate = $this->asn1map($temp, $child, $special);
$maymatch = $candidate !== NULL; $maymatch = $candidate !== NULL;
} }
@ -669,6 +691,9 @@ class File_ASN1 {
} }
// Got the match: use it. // Got the match: use it.
if (isset($special[$key])) {
$candidate = call_user_func($special[$key], $candidate);
}
$map[$key] = $candidate; $map[$key] = $candidate;
break; break;
} }
@ -761,18 +786,30 @@ class File_ASN1 {
* DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function * DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function
* an ASN.1 compiler. * an ASN.1 compiler.
* *
* "Special" mappings can be applied via $special.
*
* @param String $source * @param String $source
* @param String $mapping * @param String $mapping
* @param Integer $idx * @param Integer $idx
* @return String * @return String
* @access public * @access public
*/ */
function encodeDER($source, $mapping) function encodeDER($source, $mapping, $special = array())
{ {
$this->location = array(); $this->location = array();
return $this->_encode_der($source, $mapping); return $this->_encode_der($source, $mapping, NULL, $special);
} }
/**
* ASN.1 Encode (Helper function)
*
* @param String $source
* @param Array $mapping
* @param Integer $idx
* @param Array $special
* @return String
* @access private
*/
/** /**
* ASN.1 Encode (Helper function) * ASN.1 Encode (Helper function)
* *
@ -782,7 +819,7 @@ class File_ASN1 {
* @return String * @return String
* @access private * @access private
*/ */
function _encode_der($source, $mapping, $idx = NULL) function _encode_der($source, $mapping, $idx = NULL, $special = array())
{ {
if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') { if (is_object($source) && strtolower(get_class($source)) == 'file_asn1_element') {
return $source->element; return $source->element;
@ -794,6 +831,9 @@ class File_ASN1 {
} }
if (isset($idx)) { if (isset($idx)) {
if (isset($special[$idx])) {
$source = call_user_func($special[$idx], $source);
}
$this->location[] = $idx; $this->location[] = $idx;
} }
@ -810,7 +850,7 @@ class File_ASN1 {
$child = $mapping['children']; $child = $mapping['children'];
foreach ($source as $content) { foreach ($source as $content) {
$temp = $this->_encode_der($content, $child); $temp = $this->_encode_der($content, $child, NULL, $special);
if ($temp === false) { if ($temp === false) {
return false; return false;
} }
@ -827,7 +867,7 @@ class File_ASN1 {
continue; continue;
} }
$temp = $this->_encode_der($source[$key], $child, $key); $temp = $this->_encode_der($source[$key], $child, $key, $special);
if ($temp === false) { if ($temp === false) {
return false; return false;
} }
@ -868,7 +908,7 @@ class File_ASN1 {
continue; continue;
} }
$temp = $this->_encode_der($source[$key], $child, $key); $temp = $this->_encode_der($source[$key], $child, $key, $special);
if ($temp === false) { if ($temp === false) {
return false; return false;
} }
@ -914,6 +954,9 @@ class File_ASN1 {
$value = new Math_BigInteger($value); $value = new Math_BigInteger($value);
$value = $value->toBytes(true); $value = $value->toBytes(true);
} }
if (!strlen($value)) {
$value = chr(0);
}
break; break;
case FILE_ASN1_TYPE_UTC_TIME: case FILE_ASN1_TYPE_UTC_TIME:
case FILE_ASN1_TYPE_GENERALIZED_TIME: case FILE_ASN1_TYPE_GENERALIZED_TIME:
@ -987,19 +1030,19 @@ class File_ASN1 {
switch (true) { switch (true) {
case !isset($source): case !isset($source):
return $this->_encode_der(NULL, array('type' => FILE_ASN1_TYPE_NULL) + $mapping); return $this->_encode_der(NULL, array('type' => FILE_ASN1_TYPE_NULL) + $mapping, NULL, $special);
case is_int($source): case is_int($source):
case is_object($source) && strtolower(get_class($source)) == 'math_biginteger': case is_object($source) && strtolower(get_class($source)) == 'math_biginteger':
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping); return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_INTEGER) + $mapping, NULL, $special);
case is_float($source): case is_float($source):
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping); return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_REAL) + $mapping, NULL, $special);
case is_bool($source): case is_bool($source):
return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping); return $this->_encode_der($source, array('type' => FILE_ASN1_TYPE_BOOLEAN) + $mapping, NULL, $special);
case is_array($source) && count($source) == 1: case is_array($source) && count($source) == 1:
$typename = implode('', array_keys($source)); $typename = implode('', array_keys($source));
$outtype = array_search($typename, $this->ANYmap, true); $outtype = array_search($typename, $this->ANYmap, true);
if ($outtype !== false) { if ($outtype !== false) {
return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping); return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, NULL, $special);
} }
} }
@ -1015,7 +1058,7 @@ class File_ASN1 {
user_error('No filters defined for ' . implode('/', $loc)); user_error('No filters defined for ' . implode('/', $loc));
return false; return false;
} }
return $this->_encode_der($source, $filters + $mapping); return $this->_encode_der($source, $filters + $mapping, NULL, $special);
case FILE_ASN1_TYPE_NULL: case FILE_ASN1_TYPE_NULL:
$value = ''; $value = '';
break; break;
@ -1055,7 +1098,7 @@ class File_ASN1 {
* DER-encode the length * DER-encode the length
* *
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 § 8.1.3} for more information. * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
* *
* @access private * @access private
* @param Integer $length * @param Integer $length

View file

@ -40,22 +40,22 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXII Jim Wigginton * @copyright MMXII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id$ * @link http://phpseclib.sourceforge.net
* @link htp://phpseclib.sourceforge.net
*/ */
/** /**
* Include File_ASN1 * Include File_ASN1
*/ */
if (!class_exists('File_ASN1')) { if (!class_exists('File_ASN1')) {
require_once('File/ASN1.php'); require_once('ASN1.php');
} }
/** /**
* Flag to only accept signatures signed by certificate authorities * Flag to only accept signatures signed by certificate authorities
* *
* Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
*
* @access public * @access public
* @see File_X509::validateSignature()
*/ */
define('FILE_X509_VALIDATE_SIGNATURE_BY_CA', 1); define('FILE_X509_VALIDATE_SIGNATURE_BY_CA', 1);
@ -306,6 +306,10 @@ class File_X509 {
*/ */
function File_X509() function File_X509()
{ {
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
// Explicitly Tagged Module, 1988 Syntax // Explicitly Tagged Module, 1988 Syntax
// http://tools.ietf.org/html/rfc5280#appendix-A.1 // http://tools.ietf.org/html/rfc5280#appendix-A.1
@ -1436,18 +1440,7 @@ class File_X509 {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
/* $cert = $this->_extractBER($cert);
X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them above and beyond the ceritificate. ie.
some may have the following preceeding the -----BEGIN CERTIFICATE----- line:
subject=/O=organization/OU=org unit/CN=common name
issuer=/O=organization/CN=common name
*/
$temp = preg_replace('#^(?:[^-].+[\r\n]+)+|-.+-|[\r\n]| #', '', $cert);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
if ($temp != false) {
$cert = $temp;
}
if ($cert === false) { if ($cert === false) {
$this->currentCert = false; $this->currentCert = false;
@ -1569,7 +1562,7 @@ class File_X509 {
corresponding to the extension type identified by extnID */ corresponding to the extension type identified by extnID */
$map = $this->_getMapping($id); $map = $this->_getMapping($id);
if (!is_bool($map)) { if (!is_bool($map)) {
$mapped = $asn1->asn1map($decoded[0], $map); $mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP')));
$value = $mapped === false ? $decoded[0] : $mapped; $value = $mapped === false ? $decoded[0] : $mapped;
if ($id == 'id-ce-certificatePolicies') { if ($id == 'id-ce-certificatePolicies') {
@ -1651,7 +1644,7 @@ class File_X509 {
unset($extensions[$i]); unset($extensions[$i]);
} }
} else { } else {
$temp = $asn1->encodeDER($value, $map); $temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
$value = base64_encode($temp); $value = base64_encode($temp);
} }
} }
@ -2001,16 +1994,19 @@ class File_X509 {
* Works on X.509 certs, CSR's and CRL's. * Works on X.509 certs, CSR's and CRL's.
* Returns true if the signature is verified, false if it is not correct or NULL on error * Returns true if the signature is verified, false if it is not correct or NULL on error
* *
* By default returns false for self-signed certs. Call validateSignature(false) to make this support
* self-signed.
*
* The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}. * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
* *
* @param Integer $options optional * @param Boolean $caonly optional
* @access public * @access public
* @return Mixed * @return Mixed
*/ */
function validateSignature($options = 0) function validateSignature($caonly = true)
{ {
if (!is_array($this->currentCert) || !isset($this->signatureSubject)) { if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
return 0; return NULL;
} }
/* TODO: /* TODO:
@ -2048,10 +2044,10 @@ class File_X509 {
} }
} }
} }
if (count($this->CAs) == $i && ($options & FILE_X509_VALIDATE_SIGNATURE_BY_CA)) { if (count($this->CAs) == $i && $caonly) {
return false; return false;
} }
} elseif (!isset($signingCert) || ($options & FILE_X509_VALIDATE_SIGNATURE_BY_CA)) { } elseif (!isset($signingCert) || $caonly) {
return false; return false;
} }
return $this->_validateSignature( return $this->_validateSignature(
@ -2182,6 +2178,36 @@ class File_X509 {
} }
} }
/**
* Decodes an IP address
*
* Takes in a base64 encoded "blob" and returns a human readable IP address
*
* @param String $ip
* @access private
* @return String
*/
function _decodeIP($ip)
{
$ip = base64_decode($ip);
list(, $ip) = unpack('N', $ip);
return long2ip($ip);
}
/**
* Encodes an IP address
*
* Takes a human readable IP address into a base64-encoded "blob"
*
* @param String $ip
* @access private
* @return String
*/
function _encodeIP($ip)
{
return base64_encode(pack('N', ip2long($ip)));
}
/** /**
* "Normalizes" a Distinguished Name property * "Normalizes" a Distinguished Name property
* *
@ -2207,7 +2233,7 @@ class File_X509 {
case 'commonname': case 'commonname':
case 'cn': case 'cn':
return 'id-at-commonName'; return 'id-at-commonName';
case 'id-at-stateorprovinceName': case 'id-at-stateorprovincename':
case 'stateorprovincename': case 'stateorprovincename':
case 'state': case 'state':
case 'province': case 'province':
@ -2630,9 +2656,9 @@ class File_X509 {
case !isset($this->currentCert) || !is_array($this->currentCert): case !isset($this->currentCert) || !is_array($this->currentCert):
break; break;
case isset($this->currentCert['tbsCertificate']): case isset($this->currentCert['tbsCertificate']):
return $this->getDNProp($propname, $this->currentCert['tbsCertificate']['issuer'], $withType); return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
case isset($this->currentCert['tbsCertList']): case isset($this->currentCert['tbsCertList']):
return $this->getDNProp($propname, $this->currentCert['tbsCertList']['issuer'], $withType); return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
} }
return false; return false;
@ -2656,7 +2682,7 @@ class File_X509 {
case isset($this->currentCert['tbsCertificate']): case isset($this->currentCert['tbsCertificate']):
return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType); return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
case isset($this->currentCert['certificationRequestInfo']): case isset($this->currentCert['certificationRequestInfo']):
return $this->getDNProp($propname, $this->currentCert['certificationRequestInfo']['subject'], $withType); return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
} }
return false; return false;
@ -2718,6 +2744,7 @@ class File_X509 {
*/ */
function setPublicKey($key) function setPublicKey($key)
{ {
$key->setPublicKey();
$this->publicKey = $key; $this->publicKey = $key;
} }
@ -2804,11 +2831,7 @@ class File_X509 {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
$temp = preg_replace('#^(?:[^-].+[\r\n]+)+|-.+-|[\r\n]| #', '', $csr); $csr = $this->_extractBER($csr);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
if ($temp != false) {
$csr = $temp;
}
$orig = $csr; $orig = $csr;
if ($csr === false) { if ($csr === false) {
@ -2917,51 +2940,51 @@ class File_X509 {
* @access public * @access public
* @return Mixed * @return Mixed
*/ */
function loadSPKAC($csr) function loadSPKAC($spkac)
{ {
if (is_array($csr) && isset($csr['publicKeyAndChallenge'])) { if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
unset($this->currentCert); unset($this->currentCert);
unset($this->currentKeyIdentifier); unset($this->currentKeyIdentifier);
unset($this->signatureSubject); unset($this->signatureSubject);
$this->currentCert = $csr; $this->currentCert = $spkac;
return $csr; return $spkac;
} }
// see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
$temp = preg_replace('#(?:^[^=]+=)|[\r\n\\\]#', '', $csr); $temp = preg_replace('#(?:^[^=]+=)|[\r\n\\\]#', '', $spkac);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
if ($temp != false) { if ($temp != false) {
$csr = $temp; $spkac = $temp;
} }
$orig = $csr; $orig = $spkac;
if ($csr === false) { if ($spkac === false) {
$this->currentCert = false; $this->currentCert = false;
return false; return false;
} }
$asn1->loadOIDs($this->oids); $asn1->loadOIDs($this->oids);
$decoded = $asn1->decodeBER($csr); $decoded = $asn1->decodeBER($spkac);
if (empty($decoded)) { if (empty($decoded)) {
$this->currentCert = false; $this->currentCert = false;
return false; return false;
} }
$csr = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge); $spkac = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge);
if (!isset($csr) || $csr === false) { if (!isset($spkac) || $spkac === false) {
$this->currentCert = false; $this->currentCert = false;
return false; return false;
} }
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
$algorithm = &$csr['publicKeyAndChallenge']['spki']['algorithm']['algorithm']; $algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm'];
$key = &$csr['publicKeyAndChallenge']['spki']['subjectPublicKey']; $key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'];
$key = $this->_reformatKey($algorithm, $key); $key = $this->_reformatKey($algorithm, $key);
switch ($algorithm) { switch ($algorithm) {
@ -2978,9 +3001,9 @@ class File_X509 {
} }
$this->currentKeyIdentifier = NULL; $this->currentKeyIdentifier = NULL;
$this->currentCert = $csr; $this->currentCert = $spkac;
return $csr; return $spkac;
} }
/** /**
@ -3000,11 +3023,7 @@ class File_X509 {
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
$temp = preg_replace('#^(?:[^-].+[\r\n]+)+|-.+-|[\r\n]| #', '', $crl); $crl = $this->_extractBER($crl);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
if ($temp != false) {
$crl = $temp;
}
$orig = $crl; $orig = $crl;
if ($crl === false) { if ($crl === false) {
@ -3209,9 +3228,29 @@ class File_X509 {
$this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier); $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
} }
$altName = array();
if (isset($subject->domains) && count($subject->domains) > 1) { if (isset($subject->domains) && count($subject->domains) > 1) {
$this->setExtension('id-ce-subjectAltName', $altName = array_map(array('File_X509', '_dnsName'), $subject->domains);
array_map(array('File_X509', '_dnsName'), $subject->domains)); }
if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
// should an IP address appear as the CN if no domain name is specified? idk
//$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
$ipAddresses = array();
foreach ($subject->ipAddresses as $ipAddress) {
$encoded = $subject->_ipAddress($ipAddress);
if ($encoded !== false) {
$ipAddresses[] = $encoded;
}
}
if (count($ipAddresses)) {
$altName = array_merge($altName, $ipAddresses);
}
}
if (!empty($altName)) {
$this->setExtension('id-ce-subjectAltName', $altName);
} }
if ($this->caFlag) { if ($this->caFlag) {
@ -4012,12 +4051,29 @@ class File_X509 {
case !is_object($key): case !is_object($key):
return false; return false;
case strtolower(get_class($key)) == 'file_asn1_element': case strtolower(get_class($key)) == 'file_asn1_element':
// Assume the element is a bitstring-packed key.
$asn1 = new File_ASN1(); $asn1 = new File_ASN1();
$decoded = $asn1->decodeBER($cert); $decoded = $asn1->decodeBER($key->element);
if (empty($decoded)) { if (empty($decoded)) {
return false; return false;
} }
$key = $asn1->asn1map($decoded[0], array('type' => FILE_ASN1_TYPE_BIT_STRING)); $raw = $asn1->asn1map($decoded[0], array('type' => FILE_ASN1_TYPE_BIT_STRING));
if (empty($raw)) {
return false;
}
$raw = base64_decode($raw);
// If the key is private, compute identifier from its corresponding public key.
if (!class_exists('Crypt_RSA')) {
require_once('Crypt/RSA.php');
}
$key = new Crypt_RSA();
if (!$key->loadKey($raw)) {
return false; // Not an unencrypted RSA key.
}
if ($key->getPrivateKey() !== false) { // If private.
return $this->computeKeyIdentifier($key, $method);
}
$key = $raw; // Is a public key.
break; break;
case strtolower(get_class($key)) == 'file_x509': case strtolower(get_class($key)) == 'file_x509':
if (isset($key->publicKey)) { if (isset($key->publicKey)) {
@ -4036,9 +4092,7 @@ class File_X509 {
} }
// If in PEM format, convert to binary. // If in PEM format, convert to binary.
if (preg_match('#^-----BEGIN #', $key)) { $key = $this->_extractBER($key);
$key = base64_decode(preg_replace('#-.+-|[\r\n]#', '', $key));
}
// Now we have the key string: compute its sha-1 sum. // Now we have the key string: compute its sha-1 sum.
if (!class_exists('Crypt_Hash')) { if (!class_exists('Crypt_Hash')) {
@ -4094,6 +4148,23 @@ class File_X509 {
$this->setDNProp('id-at-commonName', $this->domains[0]); $this->setDNProp('id-at-commonName', $this->domains[0]);
} }
/**
* Set the IP Addresses's which the cert is to be valid for
*
* @access public
* @param String $ipAddress optional
*/
function setIPAddress()
{
$this->ipAddresses = func_get_args();
/*
if (!isset($this->domains)) {
$this->removeDNProp('id-at-commonName');
$this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
}
*/
}
/** /**
* Helper function to build domain array * Helper function to build domain array
* *
@ -4106,6 +4177,20 @@ class File_X509 {
return array('dNSName' => $domain); return array('dNSName' => $domain);
} }
/**
* Helper function to build IP Address array
*
* (IPv6 is not currently supported)
*
* @access private
* @param String $address
* @return Array
*/
function _iPAddress($address)
{
return array('iPAddress' => $address);
}
/** /**
* Get the index of a revoked certificate. * Get the index of a revoked certificate.
* *
@ -4320,4 +4405,31 @@ class File_X509 {
return false; return false;
} }
/**
* Extract raw BER from Base64 encoding
*
* @access private
* @param String $str
* @return String
*/
function _extractBER($str)
{
/*
X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them above and beyond the ceritificate. ie.
some may have the following preceding the -----BEGIN CERTIFICATE----- line:
Bag Attributes
localKeyID: 01 00 00 00
subject=/O=organization/OU=org unit/CN=common name
issuer=/O=organization/CN=common name
*/
$temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1);
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
// remove new lines
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
return $temp != false ? $temp : $str;
}
} }

View file

@ -70,7 +70,6 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVI Jim Wigginton * @copyright MMVI Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: BigInteger.php,v 1.33 2010/03/22 22:32:03 terrafrost Exp $
* @link http://pear.php.net/package/Math_BigInteger * @link http://pear.php.net/package/Math_BigInteger
*/ */
@ -162,16 +161,6 @@ define('MATH_BIGINTEGER_MODE_BCMATH', 2);
define('MATH_BIGINTEGER_MODE_GMP', 3); define('MATH_BIGINTEGER_MODE_GMP', 3);
/**#@-*/ /**#@-*/
/**
* The largest digit that may be used in addition / subtraction
*
* (we do pow(2, 52) instead of using 4503599627370496, directly, because some PHP installations
* will truncate 4503599627370496)
*
* @access private
*/
define('MATH_BIGINTEGER_MAX_DIGIT52', pow(2, 52));
/** /**
* Karatsuba Cutoff * Karatsuba Cutoff
* *
@ -232,7 +221,7 @@ class Math_BigInteger {
var $bitmask = false; var $bitmask = false;
/** /**
* Mode independant value used for serialization. * Mode independent value used for serialization.
* *
* If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for * If the bcmath or gmp extensions are installed $this->value will be a non-serializable resource, hence the need for
* a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value,
@ -246,20 +235,20 @@ class Math_BigInteger {
var $hex; var $hex;
/** /**
* Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers. * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
* *
* If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
* two's compliment. The sole exception to this is -10, which is treated the same as 10 is. * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
* *
* Here's an example: * Here's an example:
* <code> * <code>
* <?php * &lt;?php
* include('Math/BigInteger.php'); * include('Math/BigInteger.php');
* *
* $a = new Math_BigInteger('0x32', 16); // 50 in base-16 * $a = new Math_BigInteger('0x32', 16); // 50 in base-16
* *
* echo $a->toString(); // outputs 50 * echo $a->toString(); // outputs 50
* ?> * ?&gt;
* </code> * </code>
* *
* @param optional $x base-10 number or base-$base number if $base set. * @param optional $x base-10 number or base-$base number if $base set.
@ -283,7 +272,64 @@ class Math_BigInteger {
} }
if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
define('MATH_BIGINTEGER_OPENSSL_ENABLED', true); // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work
ob_start();
phpinfo();
$content = ob_get_contents();
ob_end_clean();
preg_match_all('#OpenSSL (Header|Library) Version(.*)#im', $content, $matches);
$versions = array();
if (!empty($matches[1])) {
for ($i = 0; $i < count($matches[1]); $i++) {
$versions[$matches[1][$i]] = trim(str_replace('=>', '', strip_tags($matches[2][$i])));
}
}
// it doesn't appear that OpenSSL versions were reported upon until PHP 5.3+
switch (true) {
case !isset($versions['Header']):
case !isset($versions['Library']):
case $versions['Header'] == $versions['Library']:
define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
break;
default:
define('MATH_BIGINTEGER_OPENSSL_DISABLE', true);
}
}
if (!defined('PHP_INT_SIZE')) {
define('PHP_INT_SIZE', 4);
}
if (!defined('MATH_BIGINTEGER_BASE') && MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_INTERNAL) {
switch (PHP_INT_SIZE) {
case 8: // use 64-bit integers if int size is 8 bytes
define('MATH_BIGINTEGER_BASE', 31);
define('MATH_BIGINTEGER_BASE_FULL', 0x80000000);
define('MATH_BIGINTEGER_MAX_DIGIT', 0x7FFFFFFF);
define('MATH_BIGINTEGER_MSB', 0x40000000);
// 10**9 is the closest we can get to 2**31 without passing it
define('MATH_BIGINTEGER_MAX10', 1000000000);
define('MATH_BIGINTEGER_MAX10_LEN', 9);
// the largest digit that may be used in addition / subtraction
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 62));
break;
//case 4: // use 64-bit floats if int size is 4 bytes
default:
define('MATH_BIGINTEGER_BASE', 26);
define('MATH_BIGINTEGER_BASE_FULL', 0x4000000);
define('MATH_BIGINTEGER_MAX_DIGIT', 0x3FFFFFF);
define('MATH_BIGINTEGER_MSB', 0x2000000);
// 10**7 is the closest to 2**26 without passing it
define('MATH_BIGINTEGER_MAX10', 10000000);
define('MATH_BIGINTEGER_MAX10_LEN', 7);
// the largest digit that may be used in addition / subtraction
// we do pow(2, 52) instead of using 4503599627370496 directly because some
// PHP installations will truncate 4503599627370496.
define('MATH_BIGINTEGER_MAX_DIGIT2', pow(2, 52));
}
} }
switch ( MATH_BIGINTEGER_MODE ) { switch ( MATH_BIGINTEGER_MODE ) {
@ -338,7 +384,7 @@ class Math_BigInteger {
// converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb) // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
default: default:
while (strlen($x)) { while (strlen($x)) {
$this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26)); $this->value[] = $this->_bytes2int($this->_base256_rshift($x, MATH_BIGINTEGER_BASE));
} }
} }
@ -390,7 +436,10 @@ class Math_BigInteger {
break; break;
case 10: case 10:
case -10: case -10:
$x = preg_replace('#^(-?[0-9]*).*#', '$1', $x); // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
// (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
// [^-0-9].*: find any non-numeric characters and then any characters that follow that
$x = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
switch ( MATH_BIGINTEGER_MODE ) { switch ( MATH_BIGINTEGER_MODE ) {
case MATH_BIGINTEGER_MODE_GMP: case MATH_BIGINTEGER_MODE_GMP:
@ -399,26 +448,24 @@ class Math_BigInteger {
case MATH_BIGINTEGER_MODE_BCMATH: case MATH_BIGINTEGER_MODE_BCMATH:
// explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
// results then doing it on '-1' does (modInverse does $x[0]) // results then doing it on '-1' does (modInverse does $x[0])
$this->value = (string) $x; $this->value = $x === '-' ? '0' : (string) $x;
break; break;
default: default:
$temp = new Math_BigInteger(); $temp = new Math_BigInteger();
// array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it.
$multiplier = new Math_BigInteger(); $multiplier = new Math_BigInteger();
$multiplier->value = array(10000000); $multiplier->value = array(MATH_BIGINTEGER_MAX10);
if ($x[0] == '-') { if ($x[0] == '-') {
$this->is_negative = true; $this->is_negative = true;
$x = substr($x, 1); $x = substr($x, 1);
} }
$x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT); $x = str_pad($x, strlen($x) + ((MATH_BIGINTEGER_MAX10_LEN - 1) * strlen($x)) % MATH_BIGINTEGER_MAX10_LEN, 0, STR_PAD_LEFT);
while (strlen($x)) { while (strlen($x)) {
$temp = $temp->multiply($multiplier); $temp = $temp->multiply($multiplier);
$temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, 7)), 256)); $temp = $temp->add(new Math_BigInteger($this->_int2bytes(substr($x, 0, MATH_BIGINTEGER_MAX10_LEN)), 256));
$x = substr($x, 7); $x = substr($x, MATH_BIGINTEGER_MAX10_LEN);
} }
$this->value = $temp->value; $this->value = $temp->value;
@ -543,7 +590,7 @@ class Math_BigInteger {
$temp = $this->copy(); $temp = $this->copy();
for ($i = count($temp->value) - 2; $i >= 0; --$i) { for ($i = count($temp->value) - 2; $i >= 0; --$i) {
$temp->_base256_lshift($result, 26); $temp->_base256_lshift($result, MATH_BIGINTEGER_BASE);
$result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
} }
@ -659,11 +706,11 @@ class Math_BigInteger {
$temp->is_negative = false; $temp->is_negative = false;
$divisor = new Math_BigInteger(); $divisor = new Math_BigInteger();
$divisor->value = array(10000000); // eg. 10**7 $divisor->value = array(MATH_BIGINTEGER_MAX10);
$result = ''; $result = '';
while (count($temp->value)) { while (count($temp->value)) {
list($temp, $mod) = $temp->divide($divisor); list($temp, $mod) = $temp->divide($divisor);
$result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', 7, '0', STR_PAD_LEFT) . $result; $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', MATH_BIGINTEGER_MAX10_LEN, '0', STR_PAD_LEFT) . $result;
} }
$result = ltrim($result, '0'); $result = ltrim($result, '0');
if (empty($result)) { if (empty($result)) {
@ -874,25 +921,25 @@ class Math_BigInteger {
$carry = 0; $carry = 0;
for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) { for ($i = 0, $j = 1; $j < $size; $i+=2, $j+=2) {
$sum = $x_value[$j] * 0x4000000 + $x_value[$i] + $y_value[$j] * 0x4000000 + $y_value[$i] + $carry; $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] + $y_value[$j] * MATH_BIGINTEGER_BASE_FULL + $y_value[$i] + $carry;
$carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT52; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 $carry = $sum >= MATH_BIGINTEGER_MAX_DIGIT2; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
$sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT52 : $sum; $sum = $carry ? $sum - MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
$temp = (int) ($sum / 0x4000000); $temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
$value[$i] = (int) ($sum - 0x4000000 * $temp); // eg. a faster alternative to fmod($sum, 0x4000000) $value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp); // eg. a faster alternative to fmod($sum, 0x4000000)
$value[$j] = $temp; $value[$j] = $temp;
} }
if ($j == $size) { // ie. if $y_size is odd if ($j == $size) { // ie. if $y_size is odd
$sum = $x_value[$i] + $y_value[$i] + $carry; $sum = $x_value[$i] + $y_value[$i] + $carry;
$carry = $sum >= 0x4000000; $carry = $sum >= MATH_BIGINTEGER_BASE_FULL;
$value[$i] = $carry ? $sum - 0x4000000 : $sum; $value[$i] = $carry ? $sum - MATH_BIGINTEGER_BASE_FULL : $sum;
++$i; // ie. let $i = $j since we've just done $value[$i] ++$i; // ie. let $i = $j since we've just done $value[$i]
} }
if ($carry) { if ($carry) {
for (; $value[$i] == 0x3FFFFFF; ++$i) { for (; $value[$i] == MATH_BIGINTEGER_MAX_DIGIT; ++$i) {
$value[$i] = 0; $value[$i] = 0;
} }
++$value[$i]; ++$value[$i];
@ -1010,26 +1057,26 @@ class Math_BigInteger {
$carry = 0; $carry = 0;
for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) { for ($i = 0, $j = 1; $j < $y_size; $i+=2, $j+=2) {
$sum = $x_value[$j] * 0x4000000 + $x_value[$i] - $y_value[$j] * 0x4000000 - $y_value[$i] - $carry; $sum = $x_value[$j] * MATH_BIGINTEGER_BASE_FULL + $x_value[$i] - $y_value[$j] * MATH_BIGINTEGER_BASE_FULL - $y_value[$i] - $carry;
$carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1 $carry = $sum < 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
$sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT52 : $sum; $sum = $carry ? $sum + MATH_BIGINTEGER_MAX_DIGIT2 : $sum;
$temp = (int) ($sum / 0x4000000); $temp = (int) ($sum / MATH_BIGINTEGER_BASE_FULL);
$x_value[$i] = (int) ($sum - 0x4000000 * $temp); $x_value[$i] = (int) ($sum - MATH_BIGINTEGER_BASE_FULL * $temp);
$x_value[$j] = $temp; $x_value[$j] = $temp;
} }
if ($j == $y_size) { // ie. if $y_size is odd if ($j == $y_size) { // ie. if $y_size is odd
$sum = $x_value[$i] - $y_value[$i] - $carry; $sum = $x_value[$i] - $y_value[$i] - $carry;
$carry = $sum < 0; $carry = $sum < 0;
$x_value[$i] = $carry ? $sum + 0x4000000 : $sum; $x_value[$i] = $carry ? $sum + MATH_BIGINTEGER_BASE_FULL : $sum;
++$i; ++$i;
} }
if ($carry) { if ($carry) {
for (; !$x_value[$i]; ++$i) { for (; !$x_value[$i]; ++$i) {
$x_value[$i] = 0x3FFFFFF; $x_value[$i] = MATH_BIGINTEGER_MAX_DIGIT;
} }
--$x_value[$i]; --$x_value[$i];
} }
@ -1162,8 +1209,8 @@ class Math_BigInteger {
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0 for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$product_value[$j] = (int) ($temp - 0x4000000 * $carry); $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
} }
$product_value[$j] = $carry; $product_value[$j] = $carry;
@ -1175,8 +1222,8 @@ class Math_BigInteger {
for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) { for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$product_value[$k] = (int) ($temp - 0x4000000 * $carry); $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
} }
$product_value[$k] = $carry; $product_value[$k] = $carry;
@ -1263,14 +1310,14 @@ class Math_BigInteger {
$i2 = $i << 1; $i2 = $i << 1;
$temp = $square_value[$i2] + $value[$i] * $value[$i]; $temp = $square_value[$i2] + $value[$i] * $value[$i];
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$square_value[$i2] = (int) ($temp - 0x4000000 * $carry); $square_value[$i2] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
// note how we start from $i+1 instead of 0 as we do in multiplication. // note how we start from $i+1 instead of 0 as we do in multiplication.
for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) { for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
$temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry; $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$square_value[$k] = (int) ($temp - 0x4000000 * $carry); $square_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
} }
// the following line can yield values larger 2**15. at this point, PHP should switch // the following line can yield values larger 2**15. at this point, PHP should switch
@ -1418,7 +1465,7 @@ class Math_BigInteger {
// normalize $x and $y as described in HAC 14.23 / 14.24 // normalize $x and $y as described in HAC 14.23 / 14.24
$msb = $y->value[count($y->value) - 1]; $msb = $y->value[count($y->value) - 1];
for ($shift = 0; !($msb & 0x2000000); ++$shift) { for ($shift = 0; !($msb & MATH_BIGINTEGER_MSB); ++$shift) {
$msb <<= 1; $msb <<= 1;
} }
$x->_lshift($shift); $x->_lshift($shift);
@ -1465,10 +1512,10 @@ class Math_BigInteger {
$q_index = $i - $y_max - 1; $q_index = $i - $y_max - 1;
if ($x_window[0] == $y_window[0]) { if ($x_window[0] == $y_window[0]) {
$quotient_value[$q_index] = 0x3FFFFFF; $quotient_value[$q_index] = MATH_BIGINTEGER_MAX_DIGIT;
} else { } else {
$quotient_value[$q_index] = (int) ( $quotient_value[$q_index] = (int) (
($x_window[0] * 0x4000000 + $x_window[1]) ($x_window[0] * MATH_BIGINTEGER_BASE_FULL + $x_window[1])
/ /
$y_window[0] $y_window[0]
); );
@ -1536,7 +1583,7 @@ class Math_BigInteger {
$result = array(); $result = array();
for ($i = count($dividend) - 1; $i >= 0; --$i) { for ($i = count($dividend) - 1; $i >= 0; --$i) {
$temp = 0x4000000 * $carry + $dividend[$i]; $temp = MATH_BIGINTEGER_BASE_FULL * $carry + $dividend[$i];
$result[$i] = (int) ($temp / $divisor); $result[$i] = (int) ($temp / $divisor);
$carry = (int) ($temp - $divisor * $result[$i]); $carry = (int) ($temp - $divisor * $result[$i]);
} }
@ -1754,7 +1801,7 @@ class Math_BigInteger {
$e_length = count($e_value) - 1; $e_length = count($e_value) - 1;
$e_bits = decbin($e_value[$e_length]); $e_bits = decbin($e_value[$e_length]);
for ($i = $e_length - 1; $i >= 0; --$i) { for ($i = $e_length - 1; $i >= 0; --$i) {
$e_bits.= str_pad(decbin($e_value[$i]), 26, '0', STR_PAD_LEFT); $e_bits.= str_pad(decbin($e_value[$i]), MATH_BIGINTEGER_BASE, '0', STR_PAD_LEFT);
} }
$e_length = strlen($e_bits); $e_length = strlen($e_bits);
@ -2089,7 +2136,7 @@ class Math_BigInteger {
if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) { if ($this->_compare($result, false, $temp[MATH_BIGINTEGER_VALUE], $temp[MATH_BIGINTEGER_SIGN]) < 0) {
$corrector_value = $this->_array_repeat(0, $n_length + 1); $corrector_value = $this->_array_repeat(0, $n_length + 1);
$corrector_value[] = 1; $corrector_value[] = 1;
$result = $this->_add($result, false, $corrector, false); $result = $this->_add($result, false, $corrector_value, false);
$result = $result[MATH_BIGINTEGER_VALUE]; $result = $result[MATH_BIGINTEGER_VALUE];
} }
@ -2112,6 +2159,7 @@ class Math_BigInteger {
* @param Boolean $x_negative * @param Boolean $x_negative
* @param Array $y_value * @param Array $y_value
* @param Boolean $y_negative * @param Boolean $y_negative
* @param Integer $stop
* @return Array * @return Array
* @access private * @access private
*/ */
@ -2148,8 +2196,8 @@ class Math_BigInteger {
for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i for ($j = 0; $j < $x_length; ++$j) { // ie. $i = 0, $k = $i
$temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0 $temp = $x_value[$j] * $y_value[0] + $carry; // $product_value[$k] == 0
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$product_value[$j] = (int) ($temp - 0x4000000 * $carry); $product_value[$j] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
} }
if ($j < $stop) { if ($j < $stop) {
@ -2164,8 +2212,8 @@ class Math_BigInteger {
for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) { for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
$temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry; $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$product_value[$k] = (int) ($temp - 0x4000000 * $carry); $product_value[$k] = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * $carry);
} }
if ($k < $stop) { if ($k < $stop) {
@ -2213,7 +2261,7 @@ class Math_BigInteger {
for ($i = 0; $i < $k; ++$i) { for ($i = 0; $i < $k; ++$i) {
$temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = $result[MATH_BIGINTEGER_VALUE][$i] * $cache[MATH_BIGINTEGER_DATA][$key];
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
$temp = $this->_regularMultiply(array($temp), $n); $temp = $this->_regularMultiply(array($temp), $n);
$temp = array_merge($this->_array_repeat(0, $i), $temp); $temp = array_merge($this->_array_repeat(0, $i), $temp);
$result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false); $result = $this->_add($result[MATH_BIGINTEGER_VALUE], false, $temp, false);
@ -2265,9 +2313,9 @@ class Math_BigInteger {
$a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1)); $a = array(MATH_BIGINTEGER_VALUE => $this->_array_repeat(0, $n + 1));
for ($i = 0; $i < $n; ++$i) { for ($i = 0; $i < $n; ++$i) {
$temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0]; $temp = $a[MATH_BIGINTEGER_VALUE][0] + $x[$i] * $y[0];
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
$temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key]; $temp = $temp * $cache[MATH_BIGINTEGER_DATA][$key];
$temp = (int) ($temp - 0x4000000 * ((int) ($temp / 0x4000000))); $temp = (int) ($temp - MATH_BIGINTEGER_BASE_FULL * ((int) ($temp / MATH_BIGINTEGER_BASE_FULL)));
$temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false); $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false);
$a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false); $a = $this->_add($a[MATH_BIGINTEGER_VALUE], false, $temp[MATH_BIGINTEGER_VALUE], false);
$a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1); $a[MATH_BIGINTEGER_VALUE] = array_slice($a[MATH_BIGINTEGER_VALUE], 1);
@ -2325,15 +2373,15 @@ class Math_BigInteger {
* @param Array $x * @param Array $x
* @return Integer * @return Integer
*/ */
function _modInverse67108864($x) // 2**26 == 67108864 function _modInverse67108864($x) // 2**26 == 67,108,864
{ {
$x = -$x[0]; $x = -$x[0];
$result = $x & 0x3; // x**-1 mod 2**2 $result = $x & 0x3; // x**-1 mod 2**2
$result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4 $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
$result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8 $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
$result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16 $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
$result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26 $result = fmod($result * (2 - fmod($x * $result, MATH_BIGINTEGER_BASE_FULL)), MATH_BIGINTEGER_BASE_FULL); // x**-1 mod 2**26
return $result & 0x3FFFFFF; return $result & MATH_BIGINTEGER_MAX_DIGIT;
} }
/** /**
@ -2402,12 +2450,12 @@ class Math_BigInteger {
} }
/** /**
* Calculates the greatest common divisor and Bézout's identity. * Calculates the greatest common divisor and Bezout's identity.
* *
* Say you have 693 and 609. The GCD is 21. Bézout's identity states that there exist integers x and y such that * Say you have 693 and 609. The GCD is 21. Bezout's identity states that there exist integers x and y such that
* 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which * 693*x + 609*y == 21. In point of fact, there are actually an infinite number of x and y combinations and which
* combination is returned is dependant upon which mode is in use. See * combination is returned is dependant upon which mode is in use. See
* {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bézout's identity - Wikipedia} for more information. * {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
* *
* Here's an example: * Here's an example:
* <code> * <code>
@ -2604,8 +2652,8 @@ class Math_BigInteger {
* *
* Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y).
* *
* @param Math_BigInteger $x * @param Math_BigInteger $y
* @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal. * @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
* @access public * @access public
* @see equals() * @see equals()
* @internal Could return $this->subtract($x), but that's not as fast as what we do do. * @internal Could return $this->subtract($x), but that's not as fast as what we do do.
@ -2684,9 +2732,8 @@ class Math_BigInteger {
* Some bitwise operations give different results depending on the precision being used. Examples include left * Some bitwise operations give different results depending on the precision being used. Examples include left
* shift, not, and rotates. * shift, not, and rotates.
* *
* @param Math_BigInteger $x * @param Integer $bits
* @access public * @access public
* @return Math_BigInteger
*/ */
function setPrecision($bits) function setPrecision($bits)
{ {
@ -2736,7 +2783,7 @@ class Math_BigInteger {
$result->value = array_slice($result->value, 0, $length); $result->value = array_slice($result->value, 0, $length);
for ($i = 0; $i < $length; ++$i) { for ($i = 0; $i < $length; ++$i) {
$result->value[$i] = $result->value[$i] & $x->value[$i]; $result->value[$i]&= $x->value[$i];
} }
return $this->_normalize($result); return $this->_normalize($result);
@ -2772,11 +2819,11 @@ class Math_BigInteger {
$length = max(count($this->value), count($x->value)); $length = max(count($this->value), count($x->value));
$result = $this->copy(); $result = $this->copy();
$result->value = array_pad($result->value, 0, $length); $result->value = array_pad($result->value, $length, 0);
$x->value = array_pad($x->value, 0, $length); $x->value = array_pad($x->value, $length, 0);
for ($i = 0; $i < $length; ++$i) { for ($i = 0; $i < $length; ++$i) {
$result->value[$i] = $this->value[$i] | $x->value[$i]; $result->value[$i]|= $x->value[$i];
} }
return $this->_normalize($result); return $this->_normalize($result);
@ -2812,11 +2859,11 @@ class Math_BigInteger {
$length = max(count($this->value), count($x->value)); $length = max(count($this->value), count($x->value));
$result = $this->copy(); $result = $this->copy();
$result->value = array_pad($result->value, 0, $length); $result->value = array_pad($result->value, $length, 0);
$x->value = array_pad($x->value, 0, $length); $x->value = array_pad($x->value, $length, 0);
for ($i = 0; $i < $length; ++$i) { for ($i = 0; $i < $length; ++$i) {
$result->value[$i] = $this->value[$i] ^ $x->value[$i]; $result->value[$i]^= $x->value[$i];
} }
return $this->_normalize($result); return $this->_normalize($result);
@ -3004,6 +3051,37 @@ class Math_BigInteger {
{ {
} }
/**
* Generates a random BigInteger
*
* Byte length is equal to $length. Uses crypt_random if it's loaded and mt_rand if it's not.
*
* @param Integer $length
* @return Math_BigInteger
* @access private
*/
function _random_number_helper($size)
{
$crypt_random = function_exists('crypt_random_string') || (!class_exists('Crypt_Random') && function_exists('crypt_random_string'));
if ($crypt_random) {
$random = crypt_random_string($size);
} else {
$random = '';
if ($size & 1) {
$random.= chr(mt_rand(0, 255));
}
$blocks = $size >> 1;
for ($i = 0; $i < $blocks; ++$i) {
// mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
$random.= pack('n', mt_rand(0, 0xFFFF));
}
}
return new Math_BigInteger($random, 256);
}
/** /**
* Generate a random number * Generate a random number
* *
@ -3033,48 +3111,45 @@ class Math_BigInteger {
$min = $temp; $min = $temp;
} }
$generator = $this->generator; static $one;
if (!isset($one)) {
$max = $max->subtract($min); $one = new Math_BigInteger(1);
$max = ltrim($max->toBytes(), chr(0));
$size = strlen($max) - 1;
$crypt_random = function_exists('crypt_random_string') || (!class_exists('Crypt_Random') && function_exists('crypt_random_string'));
if ($crypt_random) {
$random = crypt_random_string($size);
} else {
$random = '';
if ($size & 1) {
$random.= chr(mt_rand(0, 255));
}
$blocks = $size >> 1;
for ($i = 0; $i < $blocks; ++$i) {
// mt_rand(-2147483648, 0x7FFFFFFF) always produces -2147483648 on some systems
$random.= pack('n', mt_rand(0, 0xFFFF));
}
} }
$fragment = new Math_BigInteger($random, 256); $max = $max->subtract($min->subtract($one));
$leading = $fragment->compare(new Math_BigInteger(substr($max, 1), 256)) > 0 ? $size = strlen(ltrim($max->toBytes(), chr(0)));
ord($max[0]) - 1 : ord($max[0]);
if (!$crypt_random) { /*
$msb = chr(mt_rand(0, $leading)); doing $random % $max doesn't work because some numbers will be more likely to occur than others.
} else { eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
$cutoff = floor(0xFF / $leading) * $leading; would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
while (true) { not all numbers would be equally likely. some would be more likely than others.
$msb = ord(crypt_random_string(1));
if ($msb <= $cutoff) { creating a whole new random number until you find one that is within the range doesn't work
$msb%= $leading; because, for sufficiently small ranges, the likelihood that you'd get a number within that range
break; would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
} would be pretty high that $random would be greater than $max.
}
$msb = chr($msb); phpseclib works around this using the technique described here:
http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
*/
$random_max = new Math_BigInteger(chr(1) . str_repeat("\0", $size), 256);
$random = $this->_random_number_helper($size);
list($max_multiple) = $random_max->divide($max);
$max_multiple = $max_multiple->multiply($max);
while ($random->compare($max_multiple) >= 0) {
$random = $random->subtract($max_multiple);
$random_max = $random_max->subtract($max_multiple);
$random = $random->bitwise_leftShift(8);
$random = $random->add($this->_random_number_helper(1));
$random_max = $random_max->bitwise_leftShift(8);
list($max_multiple) = $random_max->divide($max);
$max_multiple = $max_multiple->multiply($max);
} }
list(, $random) = $random->divide($max);
$random = new Math_BigInteger($msb . $random, 256);
return $this->_normalize($random->add($min)); return $this->_normalize($random->add($min));
} }
@ -3094,10 +3169,18 @@ class Math_BigInteger {
*/ */
function randomPrime($min = false, $max = false, $timeout = false) function randomPrime($min = false, $max = false, $timeout = false)
{ {
if ($min === false) {
$min = new Math_BigInteger(0);
}
if ($max === false) {
$max = new Math_BigInteger(0x7FFFFFFF);
}
$compare = $max->compare($min); $compare = $max->compare($min);
if (!$compare) { if (!$compare) {
return $min; return $min->isPrime() ? $min : false;
} else if ($compare < 0) { } else if ($compare < 0) {
// if $min is bigger then $max, swap $min and $max // if $min is bigger then $max, swap $min and $max
$temp = $max; $temp = $max;
@ -3105,36 +3188,6 @@ class Math_BigInteger {
$min = $temp; $min = $temp;
} }
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
// we don't rely on Math_BigInteger::random()'s min / max when gmp_nextprime() is being used since this function
// does its own checks on $max / $min when gmp_nextprime() is used. When gmp_nextprime() is not used, however,
// the same $max / $min checks are not performed.
if ($min === false) {
$min = new Math_BigInteger(0);
}
if ($max === false) {
$max = new Math_BigInteger(0x7FFFFFFF);
}
$x = $this->random($min, $max);
$x->value = gmp_nextprime($x->value);
if ($x->compare($max) <= 0) {
return $x;
}
$x->value = gmp_nextprime($min->value);
if ($x->compare($max) <= 0) {
return $x;
}
return false;
}
static $one, $two; static $one, $two;
if (!isset($one)) { if (!isset($one)) {
$one = new Math_BigInteger(1); $one = new Math_BigInteger(1);
@ -3144,6 +3197,23 @@ class Math_BigInteger {
$start = time(); $start = time();
$x = $this->random($min, $max); $x = $this->random($min, $max);
// gmp_nextprime() requires PHP 5 >= 5.2.0 per <http://php.net/gmp-nextprime>.
if ( MATH_BIGINTEGER_MODE == MATH_BIGINTEGER_MODE_GMP && function_exists('gmp_nextprime') ) {
$p = new Math_BigInteger();
$p->value = gmp_nextprime($x->value);
if ($p->compare($max) <= 0) {
return $p;
}
if (!$min->equals($x)) {
$x = $x->subtract($one);
}
return $x->randomPrime($min, $x);
}
if ($x->equals($two)) { if ($x->equals($two)) {
return $x; return $x;
} }
@ -3375,16 +3445,16 @@ class Math_BigInteger {
return; return;
} }
$num_digits = (int) ($shift / 26); $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
$shift %= 26; $shift %= MATH_BIGINTEGER_BASE;
$shift = 1 << $shift; $shift = 1 << $shift;
$carry = 0; $carry = 0;
for ($i = 0; $i < count($this->value); ++$i) { for ($i = 0; $i < count($this->value); ++$i) {
$temp = $this->value[$i] * $shift + $carry; $temp = $this->value[$i] * $shift + $carry;
$carry = (int) ($temp / 0x4000000); $carry = (int) ($temp / MATH_BIGINTEGER_BASE_FULL);
$this->value[$i] = (int) ($temp - $carry * 0x4000000); $this->value[$i] = (int) ($temp - $carry * MATH_BIGINTEGER_BASE_FULL);
} }
if ( $carry ) { if ( $carry ) {
@ -3410,9 +3480,9 @@ class Math_BigInteger {
return; return;
} }
$num_digits = (int) ($shift / 26); $num_digits = (int) ($shift / MATH_BIGINTEGER_BASE);
$shift %= 26; $shift %= MATH_BIGINTEGER_BASE;
$carry_shift = 26 - $shift; $carry_shift = MATH_BIGINTEGER_BASE - $shift;
$carry_mask = (1 << $shift) - 1; $carry_mask = (1 << $shift) - 1;
if ( $num_digits ) { if ( $num_digits ) {
@ -3485,6 +3555,7 @@ class Math_BigInteger {
* *
* Removes leading zeros * Removes leading zeros
* *
* @param Array $value
* @return Math_BigInteger * @return Math_BigInteger
* @access private * @access private
*/ */
@ -3630,4 +3701,4 @@ class Math_BigInteger {
$temp = ltrim(pack('N', $length), chr(0)); $temp = ltrim(pack('N', $length), chr(0));
return pack('Ca*', 0x80 | strlen($temp), $temp); return pack('Ca*', 0x80 | strlen($temp), $temp);
} }
} }

View file

@ -0,0 +1,362 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Pure-PHP implementation of SCP.
*
* PHP versions 4 and 5
*
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
*
* Here's a short example of how to use this library:
* <code>
* <?php
* include('Net/SCP.php');
* include('Net/SSH2.php');
*
* $ssh = new Net_SSH2('www.domain.tld');
* if (!$ssh->login('username', 'password')) {
* exit('bad login');
* }
* $scp = new Net_SCP($ssh);
* $scp->put('abcd', str_repeat('x', 1024*1024));
* ?>
* </code>
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* 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.
*
* @category Net
* @package Net_SCP
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMX Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**#@+
* @access public
* @see Net_SCP::put()
*/
/**
* Reads data from a local file.
*/
define('NET_SCP_LOCAL_FILE', 1);
/**
* Reads data from a string.
*/
define('NET_SCP_STRING', 2);
/**#@-*/
/**#@+
* @access private
* @see Net_SCP::_send()
* @see Net_SCP::_receive()
*/
/**
* SSH1 is being used.
*/
define('NET_SCP_SSH1', 1);
/**
* SSH2 is being used.
*/
define('NET_SCP_SSH2', 2);
/**#@-*/
/**
* Pure-PHP implementations of SCP.
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.1.0
* @access public
* @package Net_SCP
*/
class Net_SCP {
/**
* SSH Object
*
* @var Object
* @access private
*/
var $ssh;
/**
* Packet Size
*
* @var Integer
* @access private
*/
var $packet_size;
/**
* Mode
*
* @var Integer
* @access private
*/
var $mode;
/**
* Default Constructor.
*
* Connects to an SSH server
*
* @param String $host
* @param optional Integer $port
* @param optional Integer $timeout
* @return Net_SCP
* @access public
*/
function Net_SCP($ssh)
{
if (!is_object($ssh)) {
return;
}
switch (strtolower(get_class($ssh))) {
case'net_ssh2':
$this->mode = NET_SCP_SSH2;
break;
case 'net_ssh1':
$this->packet_size = 50000;
$this->mode = NET_SCP_SSH1;
break;
default:
return;
}
$this->ssh = $ssh;
}
/**
* Uploads a file to the SCP server.
*
* By default, Net_SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
* So, for example, if you set $data to 'filename.ext' and then do Net_SCP::get(), you will get a file, twelve bytes
* long, containing 'filename.ext' as its contents.
*
* Setting $mode to NET_SCP_LOCAL_FILE will change the above behavior. With NET_SCP_LOCAL_FILE, $remote_file will
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
* large $remote_file will be, as well.
*
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
* care of that, yourself.
*
* @param String $remote_file
* @param String $data
* @param optional Integer $mode
* @param optional Callable $callback
* @return Boolean
* @access public
*/
function put($remote_file, $data, $mode = NET_SCP_STRING, $callback = null)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -t ' . $remote_file, false)) { // -t = to
return false;
}
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
if ($this->mode == NET_SCP_SSH2) {
$this->packet_size = $this->ssh->packet_size_client_to_server[NET_SSH2_CHANNEL_EXEC];
}
$remote_file = basename($remote_file);
if ($mode == NET_SCP_STRING) {
$size = strlen($data);
} else {
if (!is_file($data)) {
user_error("$data is not a valid file", E_USER_NOTICE);
return false;
}
$fp = @fopen($data, 'rb');
if (!$fp) {
fclose($fp);
return false;
}
$size = filesize($data);
}
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
$temp = $this->_receive();
if ($temp !== chr(0)) {
return false;
}
$sent = 0;
while ($sent < $size) {
$temp = $mode & NET_SCP_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
$this->_send($temp);
$sent+= strlen($temp);
if (is_callable($callback)) {
$callback($sent);
}
}
$this->_close();
if ($mode != NET_SCP_STRING) {
fclose($fp);
}
return true;
}
/**
* Downloads a file from the SCP server.
*
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
* operation
*
* @param String $remote_file
* @param optional String $local_file
* @return Mixed
* @access public
*/
function get($remote_file, $local_file = false)
{
if (!isset($this->ssh)) {
return false;
}
if (!$this->ssh->exec('scp -f ' . $remote_file, false)) { // -f = from
return false;
}
$this->_send("\0");
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
return false;
}
$this->_send("\0");
$size = 0;
if ($local_file !== false) {
$fp = @fopen($local_file, 'wb');
if (!$fp) {
return false;
}
}
$content = '';
while ($size < $info['size']) {
$data = $this->_receive();
// SCP usually seems to split stuff out into 16k chunks
$size+= strlen($data);
if ($local_file === false) {
$content.= $data;
} else {
fputs($fp, $data);
}
}
$this->_close();
if ($local_file !== false) {
fclose($fp);
return true;
}
return $content;
}
/**
* Sends a packet to an SSH server
*
* @param String $data
* @access private
*/
function _send($data)
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_send_channel_packet(NET_SSH2_CHANNEL_EXEC, $data);
break;
case NET_SCP_SSH1:
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
$this->ssh->_send_binary_packet($data);
}
}
/**
* Receives a packet from an SSH server
*
* @return String
* @access private
*/
function _receive()
{
switch ($this->mode) {
case NET_SCP_SSH2:
return $this->ssh->_get_channel_packet(NET_SSH2_CHANNEL_EXEC, true);
case NET_SCP_SSH1:
if (!$this->ssh->bitmap) {
return false;
}
while (true) {
$response = $this->ssh->_get_binary_packet();
switch ($response[NET_SSH1_RESPONSE_TYPE]) {
case NET_SSH1_SMSG_STDOUT_DATA:
extract(unpack('Nlength', $response[NET_SSH1_RESPONSE_DATA]));
return $this->ssh->_string_shift($response[NET_SSH1_RESPONSE_DATA], $length);
case NET_SSH1_SMSG_STDERR_DATA:
break;
case NET_SSH1_SMSG_EXITSTATUS:
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
fclose($this->ssh->fsock);
$this->ssh->bitmap = 0;
return false;
default:
user_error('Unknown packet received', E_USER_NOTICE);
return false;
}
}
}
}
/**
* Closes the connection to an SSH server
*
* @access private
*/
function _close()
{
switch ($this->mode) {
case NET_SCP_SSH2:
$this->ssh->_close_channel(NET_SSH2_CHANNEL_EXEC);
break;
case NET_SCP_SSH1:
$this->ssh->disconnect();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,771 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* SFTP Stream Wrapper
*
* Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
*
* PHP version 5
*
* LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* 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.
*
* @category Net
* @package Net_SFTP_Stream
* @author Jim Wigginton <terrafrost@php.net>
* @copyright MMXIII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @link http://phpseclib.sourceforge.net
*/
/**
* SFTP Stream Wrapper
*
* @author Jim Wigginton <terrafrost@php.net>
* @version 0.3.2
* @access public
* @package Net_SFTP_Stream
*/
class Net_SFTP_Stream {
/**
* SFTP instances
*
* Rather than re-create the connection we re-use instances if possible
*
* @var Array
* @access static
*/
static $instances;
/**
* SFTP instance
*
* @var Object
* @access private
*/
var $sftp;
/**
* Path
*
* @var String
* @access private
*/
var $path;
/**
* Mode
*
* @var String
* @access private
*/
var $mode;
/**
* Position
*
* @var Integer
* @access private
*/
var $pos;
/**
* Size
*
* @var Integer
* @access private
*/
var $size;
/**
* Directory entries
*
* @var Array
* @access private
*/
var $entries;
/**
* EOF flag
*
* @var Boolean
* @access private
*/
var $eof;
/**
* Context resource
*
* Technically this needs to be publically accessible so PHP can set it directly
*
* @var Resource
* @access public
*/
var $context;
/**
* Notification callback function
*
* @var Callable
* @access public
*/
var $notification;
/**
* The Constructor
*
* @access public
*/
function Net_SFTP_Stream()
{
if (!class_exists('Net_SFTP')) {
require_once('Net/SFTP.php');
}
}
/**
* Path Parser
*
* Extract a path from a URI and actually connect to an SSH server if appropriate
*
* If "notification" is set as a context parameter the message code for successful login is
* NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
*
* @param String $path
* @return String
* @access private
*/
function _parse_path($path)
{
extract(parse_url($path) + array('port' => 22));
if (!isset($host)) {
return false;
}
if (isset($this->context)) {
$context = stream_context_get_params($this->context);
if (isset($context['notification'])) {
$this->notification = $context['notification'];
}
}
if ($host[0] == '$') {
$host = substr($host, 1);
global $$host;
if (!is_object($$host) || get_class($$host) != 'Net_SFTP') {
return false;
}
$this->sftp = $$host;
} else {
if (isset($this->context)) {
$context = stream_context_get_options($this->context);
}
if (isset($context['sftp']['session'])) {
$sftp = $context['sftp']['session'];
}
if (isset($context['sftp']['sftp'])) {
$sftp = $context['sftp']['sftp'];
}
if (isset($sftp) && is_object($sftp) && get_class($sftp) == 'Net_SFTP') {
$this->sftp = $sftp;
return $path;
}
if (isset($context['sftp']['username'])) {
$user = $context['sftp']['username'];
}
if (isset($context['sftp']['password'])) {
$pass = $context['sftp']['password'];
}
if (isset($context['sftp']['privkey']) && is_object($context['sftp']['privkey']) && get_Class($context['sftp']['privkey']) == 'Crypt_RSA') {
$pass = $context['sftp']['privkey'];
}
if (!isset($user) || !isset($pass)) {
return false;
}
// casting $pass to a string is necessary in the event that it's a Crypt_RSA object
if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
$this->sftp = self::$instances[$host][$port][$user][(string) $pass];
} else {
$this->sftp = new Net_SFTP($host, $port);
if (isset($this->notification) && is_callable($this->notification)) {
/* if !is_callable($this->notification) we could do this:
user_error('fopen(): failed to call user notifier', E_USER_WARNING);
the ftp wrapper gives errors like that when the notifier isn't callable.
i've opted not to do that, however, since the ftp wrapper gives the line
on which the fopen occurred as the line number - not the line that the
user_error is on.
*/
call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
if (!$this->sftp->login($user, $pass)) {
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
return false;
}
call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
} else {
if (!$this->sftp->login($user, $pass)) {
return false;
}
}
self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
}
}
return $path;
}
/**
* Opens file or URL
*
* @param String $path
* @param String $mode
* @param Integer $options
* @param String $opened_path
* @return Boolean
* @access public
*/
function _stream_open($path, $mode, $options, &$opened_path)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$this->path = $path;
$this->size = $this->sftp->size($path);
$this->mode = preg_replace('#[bt]$#', '', $mode);
$this->eof = false;
if ($this->size === false) {
if ($this->mode[0] == 'r') {
return false;
}
} else {
switch ($this->mode[0]) {
case 'x':
return false;
case 'w':
case 'c':
$this->sftp->truncate($path, 0);
}
}
$this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
return true;
}
/**
* Read from stream
*
* @param Integer $count
* @return Mixed
* @access public
*/
function _stream_read($count)
{
switch ($this->mode) {
case 'w':
case 'a':
case 'x':
case 'c':
return false;
}
// commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
//if ($this->pos >= $this->size) {
// $this->eof = true;
// return false;
//}
$result = $this->sftp->get($this->path, false, $this->pos, $count);
if (isset($this->notification) && is_callable($this->notification)) {
if ($result === false) {
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
return 0;
}
// seems that PHP calls stream_read in 8k chunks
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
}
if (empty($result)) { // ie. false or empty string
$this->eof = true;
return false;
}
$this->pos+= strlen($result);
return $result;
}
/**
* Write to stream
*
* @param String $data
* @return Mixed
* @access public
*/
function _stream_write($data)
{
switch ($this->mode) {
case 'r':
return false;
}
$result = $this->sftp->put($this->path, $data, NET_SFTP_STRING, $this->pos);
if (isset($this->notification) && is_callable($this->notification)) {
if (!$result) {
call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
return 0;
}
// seems that PHP splits up strings into 8k blocks before calling stream_write
call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
}
if ($result === false) {
return false;
}
$this->pos+= strlen($data);
if ($this->pos > $this->size) {
$this->size = $this->pos;
}
$this->eof = false;
return strlen($data);
}
/**
* Retrieve the current position of a stream
*
* @return Integer
* @access public
*/
function _stream_tell()
{
return $this->pos;
}
/**
* Tests for end-of-file on a file pointer
*
* In my testing there are four classes functions that normally effect the pointer:
* fseek, fputs / fwrite, fgets / fread and ftruncate.
*
* Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
* will return false. do fread($fp, 1) and feof() will then return true.
*
* @return Boolean
* @access public
*/
function _stream_eof()
{
return $this->eof;
}
/**
* Seeks to specific location in a stream
*
* @param Integer $offset
* @param Integer $whence
* @return Boolean
* @access public
*/
function _stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset >= $this->size || $offset < 0) {
return false;
}
break;
case SEEK_CUR:
$offset+= $this->pos;
break;
case SEEK_END:
$offset+= $this->size;
}
$this->pos = $offset;
$this->eof = false;
return true;
}
/**
* Change stream options
*
* @param String $path
* @param Integer $option
* @param Mixed $var
* @return Boolean
* @access public
*/
function _stream_metadata($path, $option, $var)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
// stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
// see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
// and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
switch ($option) {
case 1: // PHP_STREAM_META_TOUCH
return $this->sftp->touch($path, $var[0], $var[1]);
case 2: // PHP_STREAM_OWNER_NAME
case 3: // PHP_STREAM_GROUP_NAME
return false;
case 4: // PHP_STREAM_META_OWNER
return $this->sftp->chown($path, $var);
case 5: // PHP_STREAM_META_GROUP
return $this->sftp->chgrp($path, $var);
case 6: // PHP_STREAM_META_ACCESS
return $this->sftp->chmod($path, $var) !== false;
}
}
/**
* Retrieve the underlaying resource
*
* @param Integer $cast_as
* @return Resource
* @access public
*/
function _stream_cast($cast_as)
{
return $this->sftp->fsock;
}
/**
* Advisory file locking
*
* @param Integer $operation
* @return Boolean
* @access public
*/
function _stream_lock($operation)
{
return false;
}
/**
* Renames a file or directory
*
* Attempts to rename oldname to newname, moving it between directories if necessary.
* If newname exists, it will be overwritten. This is a departure from what Net_SFTP
* does.
*
* @param String $path_from
* @param String $path_to
* @return Boolean
* @access public
*/
function _rename($path_from, $path_to)
{
$path1 = parse_url($path_from);
$path2 = parse_url($path_to);
unset($path1['path'], $path2['path']);
if ($path1 != $path2) {
return false;
}
$path_from = $this->_parse_path($path_from);
$path_to = parse_url($path_to);
if ($path_from == false) {
return false;
}
$path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2
// "It is an error if there already exists a file with the name specified by newpath."
// -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
if (!$this->sftp->rename($path_from, $path_to)) {
if ($this->sftp->stat($path_to)) {
return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
}
return false;
}
return true;
}
/**
* Open directory handle
*
* The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
* removed in 5.4 I'm just going to ignore it
*
* @param String $path
* @param Integer $options
* @return Boolean
* @access public
*/
function _dir_opendir($path, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$this->pos = 0;
$this->entries = $this->sftp->nlist($path);
return $this->entries !== false;
}
/**
* Read entry from directory handle
*
* @return Mixed
* @access public
*/
function _dir_readdir()
{
if (isset($this->entries[$this->pos])) {
return $this->entries[$this->pos++];
}
return false;
}
/**
* Rewind directory handle
*
* @return Boolean
* @access public
*/
function _dir_rewinddir()
{
$this->pos = 0;
return true;
}
/**
* Close directory handle
*
* @return Boolean
* @access public
*/
function _dir_closedir()
{
return true;
}
/**
* Create a directory
*
* Only valid $options is STREAM_MKDIR_RECURSIVE
*
* @param String $path
* @param Integer $mode
* @param Integer $options
* @return Boolean
* @access public
*/
function _mkdir($path, $mode, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
}
/**
* Removes a directory
*
* Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
* <http://php.net/rmdir> does not have a $recursive parameter as mkdir() does so I don't know how
* STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
* $options. What does 8 correspond to?
*
* @param String $path
* @param Integer $mode
* @param Integer $options
* @return Boolean
* @access public
*/
function _rmdir($path, $options)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->rmdir($path);
}
/**
* Flushes the output
*
* See <http://php.net/fflush>. Always returns true because Net_SFTP doesn't cache stuff before writing
*
* @return Boolean
* @access public
*/
function _stream_flush()
{
return true;
}
/**
* Retrieve information about a file resource
*
* @return Mixed
* @access public
*/
function _stream_stat()
{
$results = $this->sftp->stat($this->path);
if ($results === false) {
return false;
}
return $results;
}
/**
* Delete a file
*
* @param String $path
* @return Boolean
* @access public
*/
function _unlink($path)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
return $this->sftp->delete($path, false);
}
/**
* Retrieve information about a file
*
* Ignores the STREAM_URL_STAT_QUIET flag because the entirety of Net_SFTP_Stream is quiet by default
* might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
* cross that bridge when and if it's reached
*
* @param String $path
* @param Integer $flags
* @return Mixed
* @access public
*/
function _url_stat($path, $flags)
{
$path = $this->_parse_path($path);
if ($path === false) {
return false;
}
$results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
if ($results === false) {
return false;
}
return $results;
}
/**
* Truncate stream
*
* @param Integer $new_size
* @return Boolean
* @access public
*/
function _stream_truncate($new_size)
{
if (!$this->sftp->truncate($this->path, $new_size)) {
return false;
}
$this->eof = false;
$this->size = $new_size;
return true;
}
/**
* Change stream options
*
* STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
* The other two aren't supported because of limitations in Net_SFTP.
*
* @param Integer $option
* @param Integer $arg1
* @param Integer $arg2
* @return Boolean
* @access public
*/
function _stream_set_option($option, $arg1, $arg2)
{
return false;
}
/**
* Close an resource
*
* @access public
*/
function _stream_close()
{
}
/**
* __call Magic Method
*
* When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
* Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
* lets you figure that out.
*
* If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
* NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
*
* @param String
* @param Array
* @return Mixed
* @access public
*/
function __call($name, $arguments)
{
if (defined('NET_SFTP_STREAM_LOGGING')) {
echo $name . '(';
$last = count($arguments) - 1;
foreach ($arguments as $i => $argument) {
var_export($argument);
if ($i != $last) {
echo ',';
}
}
echo ")\r\n";
}
$name = '_' . $name;
if (!method_exists($this, $name)) {
return false;
}
return call_user_func_array(array($this, $name), $arguments);
}
}
if (function_exists('stream_wrapper_register')) {
stream_wrapper_register('sftp', 'Net_SFTP_Stream');
}

View file

@ -62,56 +62,9 @@
* @author Jim Wigginton <terrafrost@php.net> * @author Jim Wigginton <terrafrost@php.net>
* @copyright MMVII Jim Wigginton * @copyright MMVII Jim Wigginton
* @license http://www.opensource.org/licenses/mit-license.html MIT License * @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version $Id: SSH1.php,v 1.15 2010/03/22 22:01:38 terrafrost Exp $
* @link http://phpseclib.sourceforge.net * @link http://phpseclib.sourceforge.net
*/ */
/**
* Include Math_BigInteger
*
* Used to do RSA encryption.
*/
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
/**
* Include Crypt_Null
*/
//require_once('Crypt/Null.php');
/**
* Include Crypt_DES
*/
if (!class_exists('Crypt_DES')) {
require_once('Crypt/DES.php');
}
/**
* Include Crypt_TripleDES
*/
if (!class_exists('Crypt_TripleDES')) {
require_once('Crypt/TripleDES.php');
}
/**
* Include Crypt_RC4
*/
if (!class_exists('Crypt_RC4')) {
require_once('Crypt/RC4.php');
}
/**
* Include Crypt_Random
*/
// the class_exists() will only be called if the crypt_random_string function hasn't been defined and
// will trigger a call to __autoload() if you're wanting to auto-load classes
// call function_exists() a second time to stop the require_once from being called outside
// of the auto loader
if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) {
require_once('Crypt/Random.php');
}
/**#@+ /**#@+
* Encryption Methods * Encryption Methods
* *
@ -495,6 +448,19 @@ class Net_SSH1 {
*/ */
function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES) function Net_SSH1($host, $port = 22, $timeout = 10, $cipher = NET_SSH1_CIPHER_3DES)
{ {
if (!class_exists('Math_BigInteger')) {
require_once('Math/BigInteger.php');
}
// Include Crypt_Random
// the class_exists() will only be called if the crypt_random_string function hasn't been defined and
// will trigger a call to __autoload() if you're wanting to auto-load classes
// call function_exists() a second time to stop the require_once from being called outside
// of the auto loader
if (!function_exists('crypt_random_string') && !class_exists('Crypt_Random') && !function_exists('crypt_random_string')) {
require_once('Crypt/Random.php');
}
$this->protocol_flags = array( $this->protocol_flags = array(
1 => 'NET_SSH1_MSG_DISCONNECT', 1 => 'NET_SSH1_MSG_DISCONNECT',
2 => 'NET_SSH1_SMSG_PUBLIC_KEY', 2 => 'NET_SSH1_SMSG_PUBLIC_KEY',
@ -636,18 +602,27 @@ class Net_SSH1 {
// $this->crypto = new Crypt_Null(); // $this->crypto = new Crypt_Null();
// break; // break;
case NET_SSH1_CIPHER_DES: case NET_SSH1_CIPHER_DES:
if (!class_exists('Crypt_DES')) {
require_once('Crypt/DES.php');
}
$this->crypto = new Crypt_DES(); $this->crypto = new Crypt_DES();
$this->crypto->disablePadding(); $this->crypto->disablePadding();
$this->crypto->enableContinuousBuffer(); $this->crypto->enableContinuousBuffer();
$this->crypto->setKey(substr($session_key, 0, 8)); $this->crypto->setKey(substr($session_key, 0, 8));
break; break;
case NET_SSH1_CIPHER_3DES: case NET_SSH1_CIPHER_3DES:
if (!class_exists('Crypt_TripleDES')) {
require_once('Crypt/TripleDES.php');
}
$this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC); $this->crypto = new Crypt_TripleDES(CRYPT_DES_MODE_3CBC);
$this->crypto->disablePadding(); $this->crypto->disablePadding();
$this->crypto->enableContinuousBuffer(); $this->crypto->enableContinuousBuffer();
$this->crypto->setKey(substr($session_key, 0, 24)); $this->crypto->setKey(substr($session_key, 0, 24));
break; break;
//case NET_SSH1_CIPHER_RC4: //case NET_SSH1_CIPHER_RC4:
// if (!class_exists('Crypt_RC4')) {
// require_once('Crypt/RC4.php');
// }
// $this->crypto = new Crypt_RC4(); // $this->crypto = new Crypt_RC4();
// $this->crypto->enableContinuousBuffer(); // $this->crypto->enableContinuousBuffer();
// $this->crypto->setKey(substr($session_key, 0, 16)); // $this->crypto->setKey(substr($session_key, 0, 16));
@ -935,7 +910,7 @@ class Net_SSH1 {
* Returns the output of an interactive shell when no more output is available. * Returns the output of an interactive shell when no more output is available.
* *
* Requires PHP 4.3.0 or later due to the use of the stream_select() function. If you see stuff like * Requires PHP 4.3.0 or later due to the use of the stream_select() function. If you see stuff like
* "", you're seeing ANSI escape codes. According to * "^[[00m", you're seeing ANSI escape codes. According to
* {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT * {@link http://support.microsoft.com/kb/101875 How to Enable ANSI.SYS in a Command Window}, "Windows NT
* does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user, * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user,
* there's not going to be much recourse. * there's not going to be much recourse.
@ -1574,4 +1549,4 @@ class Net_SSH1 {
fputs($this->realtime_log_file, $entry); fputs($this->realtime_log_file, $entry);
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -12,8 +12,8 @@ span.error {
background: #ce3702; background: #ce3702;
} }
td.mountPoint, td.backend { width:10em; } td.mountPoint, td.backend { width:160px; }
td.remove>img { visibility:hidden; padding-top:0.8em; } td.remove>img { visibility:hidden; padding-top:13px; }
tr:hover>td.remove>img { visibility:visible; cursor:pointer; } tr:hover>td.remove>img { visibility:visible; cursor:pointer; }
#addMountPoint>td { border:none; } #addMountPoint>td { border:none; }
#addMountPoint>td.applicable { visibility:hidden; } #addMountPoint>td.applicable { visibility:hidden; }

View file

@ -10,6 +10,7 @@ namespace OC\Files\Storage;
set_include_path(get_include_path() . PATH_SEPARATOR . set_include_path(get_include_path() . PATH_SEPARATOR .
\OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib'); \OC_App::getAppPath('files_external') . '/3rdparty/phpseclib/phpseclib');
require 'Net/SFTP.php'; require 'Net/SFTP.php';
require 'Net/SFTP/Stream.php';
class SFTP extends \OC\Files\Storage\Common { class SFTP extends \OC\Files\Storage\Common {
private $host; private $host;
@ -205,16 +206,6 @@ class SFTP extends \OC\Files\Storage\Common {
if ( !$this->file_exists($path)) { if ( !$this->file_exists($path)) {
return false; return false;
} }
if (strrpos($path, '.')!==false) {
$ext=substr($path, strrpos($path, '.'));
} else {
$ext='';
}
$tmp = \OC_Helper::tmpFile($ext);
$this->getFile($absPath, $tmp);
return fopen($tmp, $mode);
case 'w': case 'w':
case 'wb': case 'wb':
case 'a': case 'a':
@ -227,38 +218,14 @@ class SFTP extends \OC\Files\Storage\Common {
case 'x+': case 'x+':
case 'c': case 'c':
case 'c+': case 'c+':
if (strrpos($path, '.')!==false) { // FIXME: make client login lazy to prevent it when using fopen()
$ext=substr($path, strrpos($path, '.')); return fopen($this->constructUrl($path), $mode);
} else {
$ext='';
}
$tmpFile=\OC_Helper::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback(
$tmpFile,
array($this, 'writeBack')
);
if ($this->file_exists($path)) {
$this->getFile($absPath, $tmpFile);
}
self::$tempFiles[$tmpFile]=$absPath;
return fopen('close://'.$tmpFile, $mode);
} }
} catch (\Exception $e) { } catch (\Exception $e) {
} }
return false; return false;
} }
public function writeBack($tmpFile) {
if (array_key_exists($tmpFile, self::$tempFiles)) {
$this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]);
unlink($tmpFile);
unset(self::$tempFiles[$tmpFile]);
}
}
public function touch($path, $mtime=null) { public function touch($path, $mtime=null) {
try { try {
if (!is_null($mtime)) { if (!is_null($mtime)) {
@ -309,4 +276,9 @@ class SFTP extends \OC\Files\Storage\Common {
return false; return false;
} }
} }
public function constructUrl($path) {
$url = 'sftp://'.$this->user.':'.$this->password.'@'.$this->host.$this->root.$path;
return $url;
}
} }

View file

@ -11,16 +11,13 @@
margin: 6px; margin: 6px;
} }
input[type="submit"]{ input[type='submit'] {
width: 45px; width: 45px;
height: 45px; height: 45px;
margin: 6px; margin: 6px;
background-image: url('%webroot%/core/img/actions/confirm.svg');
background-repeat: no-repeat;
background-position: center;
} }
#body-login input[type="submit"] { #body-login input[type='submit'] {
position: absolute; position: absolute;
top: 0px; top: 0px;
} }

View file

@ -3,7 +3,7 @@ body {
} }
#header { #header {
background: #1d2d44 url('%webroot%/core/img/noise.png') repeat; background-color: #1d2d44;
height:32px; height:32px;
left:0; left:0;
line-height:32px; line-height:32px;
@ -39,7 +39,7 @@ body {
#noPreview { #noPreview {
display:none; display:none;
padding-top:5em; padding-top:80px;
} }
footer { footer {
@ -49,7 +49,7 @@ footer {
p.info { p.info {
color: #777; color: #777;
text-align: center; text-align: center;
width: 22em; width: 352px;
margin: 0 auto; margin: 0 auto;
padding: 20px; padding: 20px;
} }
@ -61,8 +61,8 @@ p.info a {
#imgframe { #imgframe {
height:75%; height:75%;
padding-bottom:2em; padding-bottom:32px;
padding-top:2em; padding-top:32px;
width:80%; width:80%;
margin:0 auto; margin:0 auto;
} }

View file

@ -25,18 +25,16 @@ $(document).ready(function() {
window.location = $(tr).find('a.name').attr('href'); window.location = $(tr).find('a.name').attr('href');
} }
}); });
FileActions.register('file', 'Download', OC.PERMISSION_READ, '', function(filename) {
// override since the format is different
FileList.getDownloadUrl = function(filename, dir) {
// we use this because we need the service and token attributes
var tr = FileList.findFileEl(filename); var tr = FileList.findFileEl(filename);
if (tr.length > 0) { if (tr.length > 0) {
window.location = $(tr).find('a.name').attr('href'); return $(tr).find('a.name').attr('href') + '&download';
} }
}); return null;
FileActions.register('dir', 'Download', OC.PERMISSION_READ, '', function(filename) { };
var tr = FileList.findFileEl(filename);
if (tr.length > 0) {
window.location = $(tr).find('a.name').attr('href')+'&download';
}
});
} }
var file_upload_start = $('#file_upload_start'); var file_upload_start = $('#file_upload_start');

View file

@ -162,7 +162,7 @@ class Api {
$view = new \OC\Files\View('/'.\OCP\User::getUser().'/files'); $view = new \OC\Files\View('/'.\OCP\User::getUser().'/files');
if(!$view->is_dir($path)) { if(!$view->is_dir($path)) {
return new \OC_OCS_Result(null, 404, "not a directory"); return new \OC_OCS_Result(null, 400, "not a directory");
} }
$content = $view->getDirectoryContent($path); $content = $view->getDirectoryContent($path);
@ -223,7 +223,7 @@ class Api {
$encryptionEnabled = \OC_App::isEnabled('files_encryption'); $encryptionEnabled = \OC_App::isEnabled('files_encryption');
if(isset($_POST['publicUpload']) && if(isset($_POST['publicUpload']) &&
($encryptionEnabled || $publicUploadEnabled !== 'yes')) { ($encryptionEnabled || $publicUploadEnabled !== 'yes')) {
return new \OC_OCS_Result(null, 404, "public upload disabled by the administrator"); return new \OC_OCS_Result(null, 403, "public upload disabled by the administrator");
} }
$publicUpload = isset($_POST['publicUpload']) ? $_POST['publicUpload'] : 'false'; $publicUpload = isset($_POST['publicUpload']) ? $_POST['publicUpload'] : 'false';
// read, create, update (7) if public upload is enabled or // read, create, update (7) if public upload is enabled or
@ -231,7 +231,7 @@ class Api {
$permissions = $publicUpload === 'true' ? 7 : 1; $permissions = $publicUpload === 'true' ? 7 : 1;
break; break;
default: default:
return new \OC_OCS_Result(null, 404, "unknown share type"); return new \OC_OCS_Result(null, 400, "unknown share type");
} }
try { try {
@ -243,7 +243,7 @@ class Api {
$permissions $permissions
); );
} catch (\Exception $e) { } catch (\Exception $e) {
return new \OC_OCS_Result(null, 404, $e->getMessage()); return new \OC_OCS_Result(null, 403, $e->getMessage());
} }
if ($token) { if ($token) {
@ -365,7 +365,7 @@ class Api {
$publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes'); $publicUploadEnabled = \OC_Appconfig::getValue('core', 'shareapi_allow_public_upload', 'yes');
$encryptionEnabled = \OC_App::isEnabled('files_encryption'); $encryptionEnabled = \OC_App::isEnabled('files_encryption');
if($encryptionEnabled || $publicUploadEnabled !== 'yes') { if($encryptionEnabled || $publicUploadEnabled !== 'yes') {
return new \OC_OCS_Result(null, 404, "public upload disabled by the administrator"); return new \OC_OCS_Result(null, 403, "public upload disabled by the administrator");
} }
if ($share['item_type'] !== 'folder' || if ($share['item_type'] !== 'folder' ||

View file

@ -127,7 +127,18 @@ class Shared_Cache extends Cache {
return $files; return $files;
} else { } else {
if ($cache = $this->getSourceCache($folder)) { if ($cache = $this->getSourceCache($folder)) {
return $cache->getFolderContents($this->files[$folder]); $sourceFolderContent = $cache->getFolderContents($this->files[$folder]);
foreach ($sourceFolderContent as $key => $c) {
$ownerPathParts = explode('/', \OC_Filesystem::normalizePath($c['path']));
$userPathParts = explode('/', \OC_Filesystem::normalizePath($folder));
$usersPath = 'files/Shared/'.$userPathParts[1];
foreach (array_slice($ownerPathParts, 3) as $part) {
$usersPath .= '/'.$part;
}
$sourceFolderContent[$key]['usersPath'] = $usersPath;
}
return $sourceFolderContent;
} }
} }
return false; return false;
@ -260,7 +271,7 @@ class Shared_Cache extends Cache {
return $this->searchWithWhere($where, $value); return $this->searchWithWhere($where, $value);
} }
/** /**
* The maximum number of placeholders that can be used in an SQL query. * The maximum number of placeholders that can be used in an SQL query.
* Value MUST be <= 1000 for oracle: * Value MUST be <= 1000 for oracle:
@ -268,7 +279,7 @@ class Shared_Cache extends Cache {
* FIXME we should get this from doctrine as other DBs allow a lot more placeholders * FIXME we should get this from doctrine as other DBs allow a lot more placeholders
*/ */
const MAX_SQL_CHUNK_SIZE = 1000; const MAX_SQL_CHUNK_SIZE = 1000;
/** /**
* search for files with a custom where clause and value * search for files with a custom where clause and value
* the $wherevalue will be array_merge()d with the file id chunks * the $wherevalue will be array_merge()d with the file id chunks
@ -282,16 +293,16 @@ class Shared_Cache extends Cache {
$ids = $this->getAll(); $ids = $this->getAll();
$files = array(); $files = array();
// divide into chunks // divide into chunks
$chunks = array_chunk($ids, $chunksize); $chunks = array_chunk($ids, $chunksize);
foreach ($chunks as $chunk) { foreach ($chunks as $chunk) {
$placeholders = join(',', array_fill(0, count($chunk), '?')); $placeholders = join(',', array_fill(0, count($chunk), '?'));
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
`encrypted`, `unencrypted_size`, `etag` `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE ' . $sqlwhere . ' `fileid` IN (' . $placeholders . ')'; FROM `*PREFIX*filecache` WHERE ' . $sqlwhere . ' `fileid` IN (' . $placeholders . ')';
$stmt = \OC_DB::prepare($sql); $stmt = \OC_DB::prepare($sql);
$result = $stmt->execute(array_merge(array($wherevalue), $chunk)); $result = $stmt->execute(array_merge(array($wherevalue), $chunk));

View file

@ -9,7 +9,7 @@
<p class="infield"> <p class="infield">
<label for="password" class="infield"><?php p($l->t('Password')); ?></label> <label for="password" class="infield"><?php p($l->t('Password')); ?></label>
<input type="password" name="password" id="password" placeholder="" value="" autofocus /> <input type="password" name="password" id="password" placeholder="" value="" autofocus />
<input type="submit" value="" class="svg" /> <input type="submit" value="" class="svg icon icon-confirm" />
</p> </p>
</fieldset> </fieldset>
</form> </form>

View file

@ -9,7 +9,7 @@
<input type="hidden" name="sharingToken" value="<?php p($_['sharingToken']) ?>" id="sharingToken"> <input type="hidden" name="sharingToken" value="<?php p($_['sharingToken']) ?>" id="sharingToken">
<input type="hidden" name="filename" value="<?php p($_['filename']) ?>" id="filename"> <input type="hidden" name="filename" value="<?php p($_['filename']) ?>" id="filename">
<input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype"> <input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype">
<header><div id="header"> <header><div id="header" class="icon icon-noise">
<a href="<?php print_unescaped(link_to('', 'index.php')); ?>" title="" id="owncloud"><img class="svg" <a href="<?php print_unescaped(link_to('', 'index.php')); ?>" title="" id="owncloud"><img class="svg"
src="<?php print_unescaped(image_path('', 'logo-wide.svg')); ?>" alt="<?php p($theme->getName()); ?>" /></a> src="<?php print_unescaped(image_path('', 'logo-wide.svg')); ?>" alt="<?php p($theme->getName()); ?>" /></a>
<div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div> <div id="logo-claim" style="display:none;"><?php p($theme->getLogoClaim()); ?></div>

View file

@ -44,7 +44,7 @@
<notnull>true</notnull> <notnull>true</notnull>
<length>512</length> <length>512</length>
</field> </field>
<field> <field>
<name>type</name> <name>type</name>
<type>text</type> <type>text</type>
@ -52,15 +52,15 @@
<notnull>true</notnull> <notnull>true</notnull>
<length>4</length> <length>4</length>
</field> </field>
<field> <field>
<name>mime</name> <name>mime</name>
<type>text</type> <type>text</type>
<default></default> <default></default>
<notnull>true</notnull> <notnull>true</notnull>
<length>30</length> <length>255</length>
</field> </field>
<index> <index>
<name>id_index</name> <name>id_index</name>
<field> <field>
@ -68,7 +68,7 @@
<sorting>ascending</sorting> <sorting>ascending</sorting>
</field> </field>
</index> </index>
<index> <index>
<name>timestamp_index</name> <name>timestamp_index</name>
<field> <field>
@ -76,7 +76,7 @@
<sorting>ascending</sorting> <sorting>ascending</sorting>
</field> </field>
</index> </index>
<index> <index>
<name>user_index</name> <name>user_index</name>
<field> <field>
@ -84,7 +84,7 @@
<sorting>ascending</sorting> <sorting>ascending</sorting>
</field> </field>
</index> </index>
</declaration> </declaration>
</table> </table>
@ -110,7 +110,7 @@
<notnull>true</notnull> <notnull>true</notnull>
<length>50</length> <length>50</length>
</field> </field>
</declaration> </declaration>
</table> </table>

View file

@ -1 +1 @@
0.4 0.5

View file

@ -1,5 +1,5 @@
#dropdown.drop-versions { #dropdown.drop-versions {
width:24em; width:320px;
} }
#found_versions li { #found_versions li {

View file

@ -33,9 +33,9 @@
width: 100% !important; width: 100% !important;
height: 50px; height: 50px;
background-color: lightyellow; background-color: lightyellow;
border-radius: 0.5em; border-radius: 8px;
padding: 0.6em 0.5em 0.4em !important; padding: 10px 8px 6px !important;
margin-bottom: 0.3em; margin-bottom: 5px;
} }
#ldapWizard1 .hostPortCombinator { #ldapWizard1 .hostPortCombinator {
@ -68,17 +68,17 @@
} }
.ldapwarning { .ldapwarning {
margin-left: 1.4em; margin-left: 22px;
color: #FF3B3B; color: #FF3B3B;
} }
.wizSpinner { .wizSpinner {
height: 15px; height: 15px;
margin: 0.3em; margin: 5px;
} }
.ldapSettingControls { .ldapSettingControls {
margin-top: 3ex; margin-top: 3px;
} }
#ldap fieldset p label { #ldap fieldset p label {
@ -126,4 +126,4 @@ select[multiple=multiple] + button {
.ldap_grey { .ldap_grey {
color: #777; color: #777;
} }

37
autotest-js.sh Executable file
View file

@ -0,0 +1,37 @@
#!/bin/bash
#
# ownCloud
#
# Run JS tests
#
# @author Vincent Petry
# @copyright 2014 Vincent Petry <pvince81@owncloud.com>
#
NPM="$(which npm 2>/dev/null)"
PREFIX="build"
if test -z "$NPM"
then
echo 'Node JS >= 0.8 is required to run the JavaScript tests' >&2
exit 1
fi
# update/install test packages
mkdir -p "$PREFIX" && $NPM install --link --prefix "$PREFIX" || exit 3
KARMA="$(which karma 2>/dev/null)"
# If not installed globally, try local version
if test -z "$KARMA"
then
KARMA="$PREFIX/node_modules/karma/bin/karma"
fi
if test -z "$KARMA"
then
echo 'Karma module executable not found' >&2
exit 2
fi
KARMA_TESTSUITE="$1" $KARMA start tests/karma.config.js --single-run

20
build/package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "owncloud-js-tests",
"description": "ownCloud tests",
"version": "0.0.1",
"author": {
"name": "Vincent Petry",
"email": "pvince81@owncloud.com"
},
"private": true,
"homepage": "https://github.com/owncloud/",
"contributors": [],
"dependencies": {},
"devDependencies": {
"karma": "*",
"karma-jasmine": "*",
"karma-junit-reporter": "*",
"karma-coverage": "*"
},
"engine": "node >= 0.8"
}

View file

@ -80,6 +80,12 @@ $CONFIG = array(
/* Domain name used by ownCloud for the sender mail address, e.g. no-reply@example.com */ /* Domain name used by ownCloud for the sender mail address, e.g. no-reply@example.com */
"mail_domain" => "example.com", "mail_domain" => "example.com",
/* FROM address used by ownCloud for the sender mail address, e.g. owncloud@example.com
This setting overwrites the built in 'sharing-noreply' and 'lostpassword-noreply'
FROM addresses, that ownCloud uses
*/
"mail_from_address" => "owncloud",
/* Enable SMTP class debugging */ /* Enable SMTP class debugging */
"mail_smtpdebug" => false, "mail_smtpdebug" => false,

View file

@ -119,8 +119,12 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
$subject = (string)$l->t('%s shared »%s« with you', array($ownerDisplayName, $filename)); $subject = (string)$l->t('%s shared »%s« with you', array($ownerDisplayName, $filename));
$expiration = null; $expiration = null;
if (isset($items[0]['expiration'])) { if (isset($items[0]['expiration'])) {
$date = new DateTime($items[0]['expiration']); try {
$expiration = $date->format('Y-m-d'); $date = new DateTime($items[0]['expiration']);
$expiration = $l->l('date', $date->getTimestamp());
} catch (Exception $e) {
\OCP\Util::writeLog('sharing', "Couldn't read date: " . $e->getMessage(), \OCP\Util::ERROR);
}
} }
if ($itemType === 'folder') { if ($itemType === 'folder') {
@ -183,6 +187,8 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
break; break;
case 'email': case 'email':
// enable l10n support
$l = OC_L10N::get('core');
// read post variables // read post variables
$user = OCP\USER::getUser(); $user = OCP\USER::getUser();
$displayName = OCP\User::getDisplayName(); $displayName = OCP\User::getDisplayName();
@ -191,8 +197,16 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
$file = $_POST['file']; $file = $_POST['file'];
$to_address = $_POST['toaddress']; $to_address = $_POST['toaddress'];
// enable l10n support $expiration = null;
$l = OC_L10N::get('core'); if (isset($_POST['expiration']) && $_POST['expiration'] !== '') {
try {
$date = new DateTime($_POST['expiration']);
$expiration = $l->l('date', $date->getTimestamp());
} catch (Exception $e) {
\OCP\Util::writeLog('sharing', "Couldn't read date: " . $e->getMessage(), \OCP\Util::ERROR);
}
}
// setup the email // setup the email
$subject = (string)$l->t('%s shared »%s« with you', array($displayName, $file)); $subject = (string)$l->t('%s shared »%s« with you', array($displayName, $file));
@ -202,6 +216,7 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
$content->assign ('type', $type); $content->assign ('type', $type);
$content->assign ('user_displayname', $displayName); $content->assign ('user_displayname', $displayName);
$content->assign ('filename', $file); $content->assign ('filename', $file);
$content->assign('expiration', $expiration);
$text = $content->fetchPage(); $text = $content->fetchPage();
$content = new OC_Template("core", "altmail", ""); $content = new OC_Template("core", "altmail", "");
@ -209,6 +224,7 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
$content->assign ('type', $type); $content->assign ('type', $type);
$content->assign ('user_displayname', $displayName); $content->assign ('user_displayname', $displayName);
$content->assign ('filename', $file); $content->assign ('filename', $file);
$content->assign('expiration', $expiration);
$alttext = $content->fetchPage(); $alttext = $content->fetchPage();
$default_from = OCP\Util::getDefaultEmailAddress('sharing-noreply'); $default_from = OCP\Util::getDefaultEmailAddress('sharing-noreply');

View file

@ -1,7 +1,7 @@
h2 { h2 {
font-size:2em; font-size:32px;
font-weight:700; font-weight:700;
margin-bottom:1em; margin-bottom:16px;
white-space:nowrap; white-space:nowrap;
} }
@ -18,8 +18,8 @@ h2 img {
} }
#oauth { #oauth {
width:20em; width:320px;
margin:4em auto 2em; margin:64px auto 32px;
} }
#allow-auth { #allow-auth {
@ -33,7 +33,7 @@ h2 img {
background:none; background:none;
border:0; border:0;
box-shadow:0 0 0 #fff, 0 0 0 #fff inset; box-shadow:0 0 0 #fff, 0 0 0 #fff inset;
font-size:1.2em; font-size:19px;
margin:.7em; margin:11px;
padding:0; padding:0;
} }

240
core/css/icons.css Normal file
View file

@ -0,0 +1,240 @@
.icon {
background-repeat: no-repeat;
background-position: center;
}
/* general assets */
.icon-breadcrumb {
background-image: url('../img/breadcrumb.svg');
}
.icon-loading {
background-image: url('../img/loading.gif');
}
.icon-loading-dark {
background-image: url('../img/loading-dark.gif');
}
.icon-loading-small {
background-image: url('../img/loading-small.gif');
}
.icon-noise {
background-image: url('../img/noise.png');
background-repeat: no-repeat;
}
/* action icons */
.icon-add {
background-image: url('../img/actions/add.svg');
}
.icon-caret {
background-image: url('../img/actions/caret.svg');
}
.icon-caret-dark {
background-image: url('../img/actions/caret-dark.svg');
}
.icon-checkmark {
background-image: url('../img/actions/checkmark.svg');
}
.icon-clock {
background-image: url('../img/actions/clock.svg');
}
.icon-close {
background-image: url('../img/actions/close.svg');
}
.icon-confirm {
background-image: url('../img/actions/confirm.svg');
}
.icon-delete {
background-image: url('../img/actions/delete.svg');
}
.icon-delete-hover {
background-image: url('../img/actions/delete-hover.svg');
}
.icon-download {
background-image: url('../img/actions/download.svg');
}
.icon-history {
background-image: url('../img/actions/history.svg');
}
.icon-info {
background-image: url('../img/actions/info.svg');
}
.icon-lock {
background-image: url('../img/actions/lock.svg');
}
.icon-logout {
background-image: url('../img/actions/logout.svg');
}
.icon-mail {
background-image: url('../img/actions/mail.svg');
}
.icon-more {
background-image: url('../img/actions/more.svg');
}
.icon-password {
background-image: url('../img/actions/password.svg');
}
.icon-pause {
background-image: url('../img/actions/pause.svg');
}
.icon-pause-big {
background-image: url('../img/actions/pause-big.svg');
}
.icon-play {
background-image: url('../img/actions/play.svg');
}
.icon-play-add {
background-image: url('../img/actions/play-add.svg');
}
.icon-play-big {
background-image: url('../img/actions/play-big.svg');
}
.icon-play-next {
background-image: url('../img/actions/play-next.svg');
}
.icon-play-previous {
background-image: url('../img/actions/play-previous.svg');
}
.icon-public {
background-image: url('../img/actions/public.svg');
}
.icon-rename {
background-image: url('../img/actions/rename.svg');
}
.icon-search {
background-image: url('../img/actions/search.svg');
}
.icon-settings {
background-image: url('../img/actions/settings.svg');
}
.icon-share {
background-image: url('../img/actions/share.svg');
}
.icon-shared {
background-image: url('../img/actions/shared.svg');
}
.icon-sound {
background-image: url('../img/actions/sound.svg');
}
.icon-sound-off {
background-image: url('../img/actions/sound-off.svg');
}
.icon-star {
background-image: url('../img/actions/star.svg');
}
.icon-starred {
background-image: url('../img/actions/starred.svg');
}
.icon-toggle {
background-image: url('../img/actions/toggle.svg');
}
.icon-triangle-e {
background-image: url('../img/actions/triangle-e.svg');
}
.icon-triangle-n {
background-image: url('../img/actions/triangle-n.svg');
}
.icon-triangle-s {
background-image: url('../img/actions/triangle-s.svg');
}
.icon-upload {
background-image: url('../img/actions/upload.svg');
}
.icon-upload-white {
background-image: url('../img/actions/upload-white.svg');
}
.icon-user {
background-image: url('../img/actions/user.svg');
}
.icon-view-close {
background-image: url('../img/actions/view-close.svg');
}
.icon-view-next {
background-image: url('../img/actions/view-next.svg');
}
.icon-view-pause {
background-image: url('../img/actions/view-pause.svg');
}
.icon-view-play {
background-image: url('../img/actions/view-play.svg');
}
.icon-view-previous {
background-image: url('../img/actions/view-previous.svg');
}
/* places icons */
.icon-calendar-dark {
background-image: url('../img/places/calendar-dark.svg');
}
.icon-contacts-dark {
background-image: url('../img/places/contacts-dark.svg');
}
.icon-file {
background-image: url('../img/places/file.svg');
}
.icon-files {
background-image: url('../img/places/files.svg');
}
.icon-folder {
background-image: url('../img/places/folder.svg');
}
.icon-home {
background-image: url('../img/places/home.svg');
}
.icon-link {
background-image: url('../img/places/link.svg');
}
.icon-music {
background-image: url('../img/places/music.svg');
}
.icon-picture {
background-image: url('../img/places/picture.svg');
}

View file

@ -1,23 +1,23 @@
.ui-multiselect { padding:2px 0 2px 4px; text-align:left } .ui-multiselect { padding:2px 0 2px 4px; text-align:left; }
.ui-multiselect span.ui-icon { float:right } .ui-multiselect span.ui-icon { float:right; }
.ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; } .ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; }
.ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important } .ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important; }
.ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px } .ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px; }
.ui-multiselect-header ul { font-size:0.9em } .ui-multiselect-header ul { font-size:14px; }
.ui-multiselect-header ul li { float:left; padding:0 10px 0 0 } .ui-multiselect-header ul li { float:left; padding:0 10px 0 0; }
.ui-multiselect-header a { text-decoration:none } .ui-multiselect-header a { text-decoration:none; }
.ui-multiselect-header a:hover { text-decoration:underline } .ui-multiselect-header a:hover { text-decoration:underline; }
.ui-multiselect-header span.ui-icon { float:left } .ui-multiselect-header span.ui-icon { float:left;}
.ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0 } .ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0; }
.ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000; text-align: left } .ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000; text-align: left; }
.ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:scroll } .ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:scroll; }
.ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px } .ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px; }
.ui-multiselect-checkboxes label input { position:relative; top:1px } .ui-multiselect-checkboxes label input { position:relative; top:1px; }
.ui-multiselect-checkboxes li { clear:both; font-size:0.9em; padding-right:3px } .ui-multiselect-checkboxes li { clear:both; font-size:14px; padding-right:3px; }
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid } .ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid; }
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none } .ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none; }
/* remove label borders in IE6 because IE6 does not support transparency */ /* remove label borders in IE6 because IE6 does not support transparency */
* html .ui-multiselect-checkboxes label { border:none } * html .ui-multiselect-checkboxes label { border:none; }

View file

@ -7,7 +7,7 @@ ul.multiselectoptions {
border: 1px solid #ddd; border: 1px solid #ddd;
border-top: none; border-top: none;
box-shadow: 0 1px 1px #ddd; box-shadow: 0 1px 1px #ddd;
padding-top: .5em; padding-top: 8px;
position: absolute; position: absolute;
max-height: 20em; max-height: 20em;
overflow-y: auto; overflow-y: auto;
@ -15,8 +15,8 @@ ul.multiselectoptions {
} }
ul.multiselectoptions.down { ul.multiselectoptions.down {
border-bottom-left-radius: .5em; border-bottom-left-radius: 8px;
border-bottom-right-radius: .5em; border-bottom-right-radius: 8px;
width: 100%; /* do not cut off group names */ width: 100%; /* do not cut off group names */
-webkit-box-shadow: 0px 0px 20px rgba(29,45,68,.4); -webkit-box-shadow: 0px 0px 20px rgba(29,45,68,.4);
-moz-box-shadow: 0px 0px 20px rgba(29,45,68,.4); -moz-box-shadow: 0px 0px 20px rgba(29,45,68,.4);
@ -24,8 +24,8 @@ ul.multiselectoptions.down {
} }
ul.multiselectoptions.up { ul.multiselectoptions.up {
border-top-left-radius: .5em; border-top-left-radius: 8px;
border-top-right-radius: .5em; border-top-right-radius: 8px;
} }
ul.multiselectoptions>li { ul.multiselectoptions>li {
@ -52,8 +52,8 @@ div.multiselect {
display: inline-block; display: inline-block;
max-width: 400px; max-width: 400px;
min-width: 150px; min-width: 150px;
padding-right: 10px;
min-height: 20px; min-height: 20px;
padding-right: .6em;
position: relative; position: relative;
vertical-align: bottom; vertical-align: bottom;
} }
@ -78,7 +78,7 @@ div.multiselect.down {
div.multiselect>span:first-child { div.multiselect>span:first-child {
float: left; float: left;
margin-right: 2em; margin-right: 32px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
width: 90%; width: 90%;
@ -86,12 +86,12 @@ div.multiselect>span:first-child {
div.multiselect>span:last-child { div.multiselect>span:last-child {
position: absolute; position: absolute;
right: .8em; right: 13px;
} }
ul.multiselectoptions input.new { ul.multiselectoptions input.new {
padding-bottom: .2em; padding-bottom: 3px;
padding-top: .2em; padding-top: 3px;
margin: 0; margin: 0;
} }

View file

@ -8,54 +8,53 @@
border-bottom-right-radius: 5px; border-bottom-right-radius: 5px;
box-shadow:0 1px 1px #777; box-shadow:0 1px 1px #777;
display:block; display:block;
margin-right:7em; margin-right:112px;
position:absolute; position:absolute;
right:0; right:0;
width:25em; width:320px;
z-index:500; z-index:500;
padding:1em; padding:16px;
} }
#shareWithList { #shareWithList {
list-style-type:none; list-style-type:none;
padding:.5em; padding:8px;
} }
#shareWithList li { #shareWithList li {
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
font-weight: bold; font-weight: bold;
line-height: 21px; line-height: 21px;
white-space: normal; white-space: normal;
} }
#shareWithList .unshare img, #shareWithList .showCruds img { #shareWithList .unshare img, #shareWithList .showCruds img {
vertical-align:text-bottom; /* properly align icons */ vertical-align:text-bottom; /* properly align icons */
} }
#shareWithList label input[type=checkbox]{ #shareWithList label input[type=checkbox]{
margin-left: 0; margin-left: 0;
} }
#shareWithList .username{ #shareWithList .username{
padding-right: .5em; padding-right: 8px;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: 254px; max-width: 254px;
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
vertical-align: middle; vertical-align: middle;
} }
#shareWithList li label{ #shareWithList li label{
margin-right: .5em; margin-right: 8px;
} }
#dropdown label { #dropdown label {
font-weight:400; font-weight:400;
white-space: nowrap; white-space: nowrap;
} }
#dropdown input[type="checkbox"] { #dropdown input[type="checkbox"] {
margin:0 .2em 0 .5em; margin:0 3px 0 8px;
vertical-align: middle;
} }
a.showCruds { a.showCruds {
@ -67,13 +66,13 @@ a.unshare {
display:inline; display:inline;
float:right; float:right;
opacity:.5; opacity:.5;
padding:.3em 0 0 .3em !important; padding:5px 0 0 5px !important;
margin-top:-5px; margin-top:-5px;
} }
#link { #link {
border-top:1px solid #ddd; border-top:1px solid #ddd;
padding-top:.5em; padding-top:8px;
} }
#dropdown input[type="text"],#dropdown input[type="password"] { #dropdown input[type="text"],#dropdown input[type="password"] {
@ -91,12 +90,12 @@ a.unshare {
} }
#link #showPassword img { #link #showPassword img {
padding-left:.3em; padding-left:5px;
width:12px; width:12px;
} }
.reshare,#link label,#expiration label { .reshare,#link label,#expiration label {
padding-left:.5em; padding-left:8px;
} }
a.showCruds:hover,a.unshare:hover { a.showCruds:hover,a.unshare:hover {

View file

@ -264,7 +264,7 @@ input[type="submit"].enabled {
top: 45px; top: 45px;
} }
#content-wrapper { #content-wrapper {
position:absolute; height:100%; width:100%; padding-top:3.5em; padding-left:80px; position:absolute; height:100%; width:100%; padding-left:80px; padding-top: 45px;
-moz-box-sizing:border-box; box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box;
} }
#leftcontent, .leftcontent { #leftcontent, .leftcontent {

28
core/js/core.json Normal file
View file

@ -0,0 +1,28 @@
{
"modules": [
"jquery-1.10.0.min.js",
"jquery-migrate-1.2.1.min.js",
"jquery-ui-1.10.0.custom.js",
"jquery-showpassword.js",
"jquery.infieldlabel.js",
"jquery.placeholder.js",
"jquery-tipsy.js",
"compatibility.js",
"jquery.ocdialog.js",
"oc-dialogs.js",
"js.js",
"octemplate.js",
"eventsource.js",
"config.js",
"multiselect.js",
"search.js",
"router.js",
"oc-requesttoken.js",
"styles.js",
"apps.js",
"fixes.js",
"jquery-ui-2.10.0.custom.js",
"jquery-tipsy.js",
"jquery.ocdialog.js"
]
}

View file

@ -252,6 +252,12 @@ var OC={
} }
return link; return link;
}, },
/**
* Redirect to the target URL, can also be used for downloads.
*/
redirect: function(targetUrl) {
window.location = targetUrl;
},
/** /**
* get the absolute path to an image file * get the absolute path to an image file
* @param app the app id to which the image belongs * @param app the app id to which the image belongs
@ -364,6 +370,34 @@ var OC={
} }
return result; return result;
}, },
/**
* Builds a URL query from a JS map.
* @param params parameter map
* @return string containing a URL query (without question) mark
*/
buildQueryString: function(params) {
var s = '';
var first = true;
if (!params) {
return s;
}
for (var key in params) {
var value = params[key];
if (first) {
first = false;
}
else {
s += '&';
}
s += encodeURIComponent(key);
if (value !== null && typeof(value) !== 'undefined') {
s += '=' + encodeURIComponent(value);
}
}
return s;
},
/** /**
* Opens a popup with the setting for an app. * Opens a popup with the setting for an app.
* @param appid String. The ID of the app e.g. 'calendar', 'contacts' or 'files'. * @param appid String. The ID of the app e.g. 'calendar', 'contacts' or 'files'.

View file

@ -3,9 +3,12 @@ OC.Router = {
// register your ajax requests to load after the loading of the routes // register your ajax requests to load after the loading of the routes
// has finished. otherwise you face problems with race conditions // has finished. otherwise you face problems with race conditions
registerLoadedCallback: function(callback){ registerLoadedCallback: function(callback){
if (!this.routes_request){
return;
}
this.routes_request.done(callback); this.routes_request.done(callback);
}, },
routes_request: $.ajax(OC.router_base_url + '/core/routes.json', { routes_request: !window.TESTING && $.ajax(OC.router_base_url + '/core/routes.json', {
dataType: 'json', dataType: 'json',
success: function(jsondata) { success: function(jsondata) {
if (jsondata.status === 'success') { if (jsondata.status === 'success') {
@ -75,4 +78,4 @@ OC.Router = {
return OC.router_base_url + url; return OC.router_base_url + url;
} }
}; }

View file

@ -733,12 +733,16 @@ $(document).ready(function() {
var itemSource = $('#dropdown').data('item-source'); var itemSource = $('#dropdown').data('item-source');
var file = $('tr').filterAttr('data-id', String(itemSource)).data('file'); var file = $('tr').filterAttr('data-id', String(itemSource)).data('file');
var email = $('#email').val(); var email = $('#email').val();
var expirationDate = '';
if ( $('#expirationCheckbox').is(':checked') === true ) {
expirationDate = $( "#expirationDate" ).val();
}
if (email != '') { if (email != '') {
$('#email').prop('disabled', true); $('#email').prop('disabled', true);
$('#email').val(t('core', 'Sending ...')); $('#email').val(t('core', 'Sending ...'));
$('#emailButton').prop('disabled', true); $('#emailButton').prop('disabled', true);
$.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'email', toaddress: email, link: link, itemType: itemType, itemSource: itemSource, file: file}, $.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'email', toaddress: email, link: link, itemType: itemType, itemSource: itemSource, file: file, expiration: expirationDate},
function(result) { function(result) {
$('#email').prop('disabled', false); $('#email').prop('disabled', false);
$('#emailButton').prop('disabled', false); $('#emailButton').prop('disabled', false);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Simulate the variables that are normally set by PHP code
*/
// from core/js/config.php
window.TESTING = true;
window.oc_debug = true;
window.datepickerFormatDate = 'MM d, yy';
window.dayNames = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
window.monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
window.firstDay = 0;
// setup dummy webroots
window.oc_webroot = location.href + '/';
window.oc_appswebroots = {
"files": window.oc_webroot + '/apps/files/'
};
// global setup for all tests
(function setupTests() {
var fakeServer = null;
beforeEach(function() {
// enforce fake XHR, tests should not depend on the server and
// must use fake responses for expected calls
fakeServer = sinon.fakeServer.create();
// return fake translations as they might be requested for many test runs
fakeServer.respondWith(/\/index.php\/core\/ajax\/translations.php$/, [
200, {
"Content-Type": "application/json"
},
'{"data": [], "plural_form": "nplurals=2; plural=(n != 1);"}'
]);
// make it globally available, so that other tests can define
// custom responses
window.fakeServer = fakeServer;
});
afterEach(function() {
// uncomment this to log requests
// console.log(window.fakeServer.requests);
fakeServer.restore();
});
})();

View file

@ -0,0 +1,107 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
describe('Core base tests', function() {
describe('Base values', function() {
it('Sets webroots', function() {
expect(OC.webroot).toBeDefined();
expect(OC.appswebroots).toBeDefined();
});
});
describe('Link functions', function() {
var TESTAPP = 'testapp';
var TESTAPP_ROOT = OC.webroot + '/appsx/testapp';
beforeEach(function() {
OC.appswebroots[TESTAPP] = TESTAPP_ROOT;
});
afterEach(function() {
// restore original array
delete OC.appswebroots[TESTAPP];
});
it('Generates correct links for core apps', function() {
expect(OC.linkTo('core', 'somefile.php')).toEqual(OC.webroot + '/core/somefile.php');
expect(OC.linkTo('admin', 'somefile.php')).toEqual(OC.webroot + '/admin/somefile.php');
});
it('Generates correct links for regular apps', function() {
expect(OC.linkTo(TESTAPP, 'somefile.php')).toEqual(OC.webroot + '/index.php/apps/' + TESTAPP + '/somefile.php');
});
it('Generates correct remote links', function() {
expect(OC.linkToRemote('webdav')).toEqual(window.location.protocol + '//' + window.location.host + OC.webroot + '/remote.php/webdav');
});
describe('Images', function() {
it('Generates image path with given extension', function() {
var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return true; });
expect(OC.imagePath('core', 'somefile.jpg')).toEqual(OC.webroot + '/core/img/somefile.jpg');
expect(OC.imagePath(TESTAPP, 'somefile.jpg')).toEqual(TESTAPP_ROOT + '/img/somefile.jpg');
svgSupportStub.restore();
});
it('Generates image path with svg extension when svg support exists', function() {
var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return true; });
expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.svg');
expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.svg');
svgSupportStub.restore();
});
it('Generates image path with png ext when svg support is not available', function() {
var svgSupportStub = sinon.stub(window, 'SVGSupport', function() { return false; });
expect(OC.imagePath('core', 'somefile')).toEqual(OC.webroot + '/core/img/somefile.png');
expect(OC.imagePath(TESTAPP, 'somefile')).toEqual(TESTAPP_ROOT + '/img/somefile.png');
svgSupportStub.restore();
});
});
});
describe('Query string building', function() {
it('Returns empty string when empty params', function() {
expect(OC.buildQueryString()).toEqual('');
expect(OC.buildQueryString({})).toEqual('');
});
it('Encodes regular query strings', function() {
expect(OC.buildQueryString({
a: 'abc',
b: 'def'
})).toEqual('a=abc&b=def');
});
it('Encodes special characters', function() {
expect(OC.buildQueryString({
unicode: '汉字',
})).toEqual('unicode=%E6%B1%89%E5%AD%97');
expect(OC.buildQueryString({
b: 'spaace value',
'space key': 'normalvalue',
'slash/this': 'amp&ersand'
})).toEqual('b=spaace%20value&space%20key=normalvalue&slash%2Fthis=amp%26ersand');
});
it('Encodes data types and empty values', function() {
expect(OC.buildQueryString({
'keywithemptystring': '',
'keywithnull': null,
'keywithundefined': null,
something: 'else'
})).toEqual('keywithemptystring=&keywithnull&keywithundefined&something=else');
expect(OC.buildQueryString({
'booleanfalse': false,
'booleantrue': true
})).toEqual('booleanfalse=false&booleantrue=true');
expect(OC.buildQueryString({
'number': 123,
})).toEqual('number=123');
});
});
});

View file

@ -303,6 +303,7 @@ class OC {
public static function initTemplateEngine() { public static function initTemplateEngine() {
// Add the stuff we need always // Add the stuff we need always
// TODO: read from core/js/core.json
OC_Util::addScript("jquery-1.10.0.min"); OC_Util::addScript("jquery-1.10.0.min");
OC_Util::addScript("jquery-migrate-1.2.1.min"); OC_Util::addScript("jquery-migrate-1.2.1.min");
OC_Util::addScript("jquery-ui-1.10.0.custom"); OC_Util::addScript("jquery-ui-1.10.0.custom");
@ -331,6 +332,7 @@ class OC {
} }
OC_Util::addStyle("styles"); OC_Util::addStyle("styles");
OC_Util::addStyle("icons");
OC_Util::addStyle("apps"); OC_Util::addStyle("apps");
OC_Util::addStyle("fixes"); OC_Util::addStyle("fixes");
OC_Util::addStyle("multiselect"); OC_Util::addStyle("multiselect");

View file

@ -0,0 +1,50 @@
<?php
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* @license AGPL3
*/
class OC_Connector_Sabre_ExceptionLoggerPlugin extends Sabre_DAV_ServerPlugin
{
private $appName;
/**
* @param string $loggerAppName app name to use when logging
*/
public function __construct($loggerAppName = 'webdav') {
$this->appName = $loggerAppName;
}
/**
* This initializes the plugin.
*
* This function is called by Sabre_DAV_Server, after
* addPlugin is called.
*
* This method should set up the required event subscriptions.
*
* @param Sabre_DAV_Server $server
* @return void
*/
public function initialize(Sabre_DAV_Server $server) {
$server->subscribeEvent('exception', array($this, 'logException'), 10);
}
/**
* Log exception
*
* @internal param Exception $e exception
*/
public function logException($e) {
$exceptionClass = get_class($e);
if ($exceptionClass !== 'Sabre_DAV_Exception_NotAuthenticated') {
\OCP\Util::logException($this->appName, $e);
}
}
}

View file

@ -79,7 +79,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
\OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR); \OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR);
$fs->unlink($partpath); $fs->unlink($partpath);
// because we have no clue about the cause we can only throw back a 500/Internal Server Error // because we have no clue about the cause we can only throw back a 500/Internal Server Error
throw new Sabre_DAV_Exception(); throw new Sabre_DAV_Exception('Could not write file contents');
} }
} catch (\OCP\Files\NotPermittedException $e) { } catch (\OCP\Files\NotPermittedException $e) {
// a more general case - due to whatever reason the content could not be written // a more general case - due to whatever reason the content could not be written
@ -105,7 +105,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
if ($renameOkay === false || $fileExists === false) { if ($renameOkay === false || $fileExists === false) {
\OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR);
$fs->unlink($partpath); $fs->unlink($partpath);
throw new Sabre_DAV_Exception(); throw new Sabre_DAV_Exception('Could not rename part file to final file');
} }
// allow sync clients to send the mtime along in a header // allow sync clients to send the mtime along in a header
@ -246,7 +246,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
if ($fileExists) { if ($fileExists) {
$fs->unlink($targetPath); $fs->unlink($targetPath);
} }
throw new Sabre_DAV_Exception(); throw new Sabre_DAV_Exception('Could not rename part file assembled from chunks');
} }
// allow sync clients to send the mtime along in a header // allow sync clients to send the mtime along in a header

View file

@ -50,6 +50,8 @@ class APC extends Cache {
static public function isAvailable() { static public function isAvailable() {
if (!extension_loaded('apc')) { if (!extension_loaded('apc')) {
return false; return false;
} elseif (!ini_get('apc.enabled')) {
return false;
} elseif (!ini_get('apc.enable_cli') && \OC::$CLI) { } elseif (!ini_get('apc.enable_cli') && \OC::$CLI) {
return false; return false;
} else { } else {

View file

@ -88,14 +88,18 @@ class Util {
* @param Exception $ex exception to log * @param Exception $ex exception to log
*/ */
public static function logException( $app, \Exception $ex ) { public static function logException( $app, \Exception $ex ) {
$message = $ex->getMessage(); $class = get_class($ex);
if ($class !== 'Exception') {
$message = $class . ': ';
}
$message .= $ex->getMessage();
if ($ex->getCode()) { if ($ex->getCode()) {
$message .= ' [' . $ex->getCode() . ']'; $message .= ' [' . $ex->getCode() . ']';
} }
\OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL); \OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL);
if (defined('DEBUG') and DEBUG) { if (defined('DEBUG') and DEBUG) {
// also log stack trace // also log stack trace
$stack = explode('#', $ex->getTraceAsString()); $stack = explode("\n", $ex->getTraceAsString());
// first element is empty // first element is empty
array_shift($stack); array_shift($stack);
foreach ($stack as $s) { foreach ($stack as $s) {
@ -254,8 +258,13 @@ class Util {
* Example: when given lostpassword-noreply as $user_part param, * Example: when given lostpassword-noreply as $user_part param,
* and is currently accessed via http(s)://example.com/, * and is currently accessed via http(s)://example.com/,
* it would return 'lostpassword-noreply@example.com' * it would return 'lostpassword-noreply@example.com'
*
* If the configuration value 'mail_from_address' is set in
* config.php, this value will override the $user_part that
* is passed to this function
*/ */
public static function getDefaultEmailAddress($user_part) { public static function getDefaultEmailAddress($user_part) {
$user_part = \OC_Config::getValue('mail_from_address', $user_part);
$host_name = self::getServerHostName(); $host_name = self::getServerHostName();
$host_name = \OC_Config::getValue('mail_domain', $host_name); $host_name = \OC_Config::getValue('mail_domain', $host_name);
$defaultEmailAddress = $user_part.'@'.$host_name; $defaultEmailAddress = $user_part.'@'.$host_name;

View file

@ -165,6 +165,11 @@ $(document).ready(function(){
$('#email').keyup(function(){ $('#email').keyup(function(){
if ($('#email').val() !== '' ){ if ($('#email').val() !== '' ){
// if this is the enter key changeEmailAddress() is already invoked
// so it doesn't need to be triggered again
if(event.keyCode === 13) {
return;
}
if(typeof timeout !== 'undefined'){ if(typeof timeout !== 'undefined'){
clearTimeout(timeout); clearTimeout(timeout);
} }
@ -172,6 +177,18 @@ $(document).ready(function(){
} }
}); });
$('#email').keypress(function(event){
// check for enter key and non empty email
if (event.keyCode === 13 && $('#email').val() !== '' ){
event.preventDefault()
// clear timeout of previous keyup event - prevents duplicate changeEmailAddress call
if(typeof timeout !== 'undefined'){
clearTimeout(timeout);
}
changeEmailAddress();
}
});
$("#languageinput").change( function(){ $("#languageinput").change( function(){
// Serialize the data // Serialize the data
var post = $( "#languageinput" ).serialize(); var post = $( "#languageinput" ).serialize();
@ -189,6 +206,8 @@ $(document).ready(function(){
$('button:button[name="submitDecryptAll"]').click(function() { $('button:button[name="submitDecryptAll"]').click(function() {
var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val(); var privateKeyPassword = $('#decryptAll input:password[id="privateKeyPassword"]').val();
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
OC.Encryption.decryptAll(privateKeyPassword); OC.Encryption.decryptAll(privateKeyPassword);
}); });
@ -197,6 +216,8 @@ $(document).ready(function(){
if (privateKeyPassword !== '' ) { if (privateKeyPassword !== '' ) {
$('#decryptAll button:button[name="submitDecryptAll"]').removeAttr("disabled"); $('#decryptAll button:button[name="submitDecryptAll"]').removeAttr("disabled");
if(event.which === 13) { if(event.which === 13) {
$('#decryptAll button:button[name="submitDecryptAll"]').prop("disabled", true);
$('#decryptAll input:password[name="privateKeyPassword"]').prop("disabled", true);
OC.Encryption.decryptAll(privateKeyPassword); OC.Encryption.decryptAll(privateKeyPassword);
} }
} else { } else {
@ -263,13 +284,13 @@ OC.Encryption = {
$.post('ajax/decryptall.php', {password:password}, function(data) { $.post('ajax/decryptall.php', {password:password}, function(data) {
if (data.status === "error") { if (data.status === "error") {
OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data); OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data);
$('#decryptAll input:password[name="privateKeyPassword"]').removeAttr("disabled");
} else { } else {
OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data); OC.Encryption.msg.finishedDecrypting('#decryptAll .msg', data);
} }
} });
);
} }
} };
OC.Encryption.msg={ OC.Encryption.msg={
startDecrypting:function(selector){ startDecrypting:function(selector){

View file

@ -39,9 +39,11 @@ if($_['passwordChangeSupported']) {
<h2><?php p($l->t('Password'));?></h2> <h2><?php p($l->t('Password'));?></h2>
<div id="passwordchanged"><?php echo $l->t('Your password was changed');?></div> <div id="passwordchanged"><?php echo $l->t('Your password was changed');?></div>
<div id="passworderror"><?php echo $l->t('Unable to change your password');?></div> <div id="passworderror"><?php echo $l->t('Unable to change your password');?></div>
<input type="password" id="pass1" name="oldpassword" placeholder="<?php echo $l->t('Current password');?>" /> <input type="password" id="pass1" name="oldpassword"
placeholder="<?php echo $l->t('Current password');?>" autocomplete="off" />
<input type="password" id="pass2" name="personal-password" <input type="password" id="pass2" name="personal-password"
placeholder="<?php echo $l->t('New password');?>" data-typetoggle="#personal-show" /> placeholder="<?php echo $l->t('New password');?>"
data-typetoggle="#personal-show" autocomplete="off" />
<input type="checkbox" id="personal-show" name="show" /><label for="personal-show"></label> <input type="checkbox" id="personal-show" name="show" /><label for="personal-show"></label>
<input id="passwordbutton" type="submit" value="<?php echo $l->t('Change password');?>" /> <input id="passwordbutton" type="submit" value="<?php echo $l->t('Change password');?>" />
<br/> <br/>
@ -146,29 +148,27 @@ if($_['passwordChangeSupported']) {
};?> };?>
<?php if($_['enableDecryptAll']): ?> <?php if($_['enableDecryptAll']): ?>
<form id="decryptAll"> <fieldset class="personalblock" id="decryptAll">
<fieldset class="personalblock"> <h2>
<h2> <?php p( $l->t( 'Encryption' ) ); ?>
<?php p( $l->t( 'Encryption' ) ); ?> </h2>
</h2> <?php p($l->t( "The encryption app is no longer enabled, please decrypt all your files" )); ?>
<?php p($l->t( "The encryption app is no longer enabled, please decrypt all your files" )); ?> <p>
<p> <input
<input type="password"
type="password" name="privateKeyPassword"
name="privateKeyPassword" id="privateKeyPassword" />
id="privateKeyPassword" /> <label for="privateKeyPassword"><?php p($l->t( "Log-in password" )); ?></label>
<label for="privateKeyPassword"><?php p($l->t( "Log-in password" )); ?></label>
<br />
<button
type="button"
disabled
name="submitDecryptAll"><?php p($l->t( "Decrypt all Files" )); ?>
</button>
<span class="msg"></span>
</p>
<br /> <br />
</fieldset> <button
</form> type="button"
disabled
name="submitDecryptAll"><?php p($l->t( "Decrypt all Files" )); ?>
</button>
<span class="msg"></span>
</p>
<br />
</fieldset>
<?php endif; ?> <?php endif; ?>
<fieldset class="personalblock"> <fieldset class="personalblock">

149
tests/karma.config.js Normal file
View file

@ -0,0 +1,149 @@
/**
* ownCloud
*
* @author Vincent Petry
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* This node module is run by the karma executable to specify its configuration.
*
* The list of files from all needed JavaScript files including the ones from the
* apps to test, and the test specs will be passed as configuration object.
*
* Note that it is possible to test a single app by setting the KARMA_TESTSUITE
* environment variable to the apps name, for example "core" or "files_encryption".
* Multiple apps can be specified by separating them with space.
*
*/
module.exports = function(config) {
// default apps to test when none is specified (TODO: read from filesystem ?)
var defaultApps = 'core files';
var appsToTest = process.env.KARMA_TESTSUITE || defaultApps;
// read core files from core.json,
// these are required by all apps so always need to be loaded
// note that the loading order is important that's why they
// are specified in a separate file
var corePath = 'core/js/';
var coreFiles = require('../' + corePath + 'core.json').modules;
var testCore = false;
var files = [];
var index;
// find out what apps to test from appsToTest
appsToTest = appsToTest.split(' ');
index = appsToTest.indexOf('core');
if (index > -1) {
appsToTest.splice(index, 1);
testCore = true;
}
// extra test libs
files.push(corePath + 'tests/lib/sinon-1.7.3.js');
// core mocks
files.push(corePath + 'tests/specHelper.js');
// add core files
for ( var i = 0; i < coreFiles.length; i++ ) {
files.push( corePath + coreFiles[i] );
}
// need to test the core app as well ?
if (testCore) {
// core tests
files.push(corePath + 'tests/specs/*.js');
}
for ( var i = 0; i < appsToTest.length; i++ ) {
// add app JS
files.push('apps/' + appsToTest[i] + '/js/*.js');
// add test specs
files.push('apps/' + appsToTest[i] + '/tests/js/*.js');
}
config.set({
// base path, that will be used to resolve files and exclude
basePath: '..',
// frameworks to use
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: files,
// list of files to exclude
exclude: [
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['dots', 'junit', 'coverage'],
junitReporter: {
outputFile: 'tests/autotest-results-js.xml'
},
// web server port
port: 9876,
preprocessors: {
'apps/files/js/*.js': 'coverage'
},
coverageReporter: {
dir:'tests/karma-coverage',
reporters: [
{ type: 'html' },
{ type: 'cobertura' }
]
},
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
browsers: ['PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
};

View file

@ -88,6 +88,15 @@ class Test_Util extends PHPUnit_Framework_TestCase {
OC_Config::deleteKey('mail_domain'); OC_Config::deleteKey('mail_domain');
} }
function testGetConfiguredEmailAddressFromConfig() {
OC_Config::setValue('mail_domain', 'example.com');
OC_Config::setValue('mail_from_address', 'owncloud');
$email = \OCP\Util::getDefaultEmailAddress("no-reply");
$this->assertEquals('owncloud@example.com', $email);
OC_Config::deleteKey('mail_domain');
OC_Config::deleteKey('mail_from_address');
}
function testGetInstanceIdGeneratesValidId() { function testGetInstanceIdGeneratesValidId() {
OC_Config::deleteKey('instanceid'); OC_Config::deleteKey('instanceid');
$this->assertStringStartsWith('oc', OC_Util::getInstanceId()); $this->assertStringStartsWith('oc', OC_Util::getInstanceId());