From 435f778ce583e3b3096538ef0fdcf01768b21e63 Mon Sep 17 00:00:00 2001 From: Nicole Cordes <typo3@cordes.co> Date: Sun, 12 Jul 2015 23:53:28 +0200 Subject: [PATCH] [FEATURE] Add api for rsaauth encryption This patch introduces new API which eases the use of RSA encryption across the core and for third party extensions. For backend encryption a new RequireJS module is included which finds fields to encrypt automatically by their data attribute. For frontend encryption the JavaScript was rewritten to work the same way the RequireJS module works but with plain (vanilla) JavaScript. Releases: master Resolves: #67932 Resolves: #34568 Change-Id: Id35dd65d1019a8c16858f03989ff48e3434698e4 Reviewed-on: http://review.typo3.org/40938 Reviewed-by: Markus Klein <markus.klein@typo3.org> Tested-by: Markus Klein <markus.klein@typo3.org> Reviewed-by: Nicole Cordes <typo3@cordes.co> Tested-by: Nicole Cordes <typo3@cordes.co> Reviewed-by: Georg Ringer <georg.ringer@gmail.com> Tested-by: Georg Ringer <georg.ringer@gmail.com> --- .../Classes/Controller/BackendController.php | 5 + .../Classes/Http/AjaxRequestHandler.php | 3 +- .../Private/Templates/UserPassLoginForm.html | 4 +- .../Public/JavaScript/LoginRefresh.js | 47 +- .../Public/JavaScript/UserPassLogin.js | 6 +- ...recation-67932-DeprecatedOldRsaauthApi.rst | 21 + .../Feature-67932-RsaauthApiRewrite.rst | 71 ++ typo3/sysext/felogin/template.html | 2 +- .../Classes/Backend/AjaxLoginHandler.php | 17 +- .../Classes/Hook/BackendHookForAjaxLogin.php | 43 - .../Classes/Hook/FrontendLoginHook.php | 31 +- .../rsaauth/Classes/Hook/UserSetupHook.php | 83 +- .../sysext/rsaauth/Classes/RsaAuthService.php | 46 +- .../rsaauth/Classes/RsaEncryptionDecoder.php | 107 +++ .../rsaauth/Classes/RsaEncryptionEncoder.php | 115 +++ .../Slot/UsernamePasswordProviderSlot.php | 22 +- .../PHP/FrontendLoginRsaPublicKey.php | 4 + .../BackendLoginFormRsaEncryption.js | 104 --- .../FrontendLoginFormRsaEncryption.js | 154 --- .../FrontendLoginFormRsaEncryption.min.js | 15 - .../Public/JavaScript/RsaEncryption.js | 180 ++++ .../Public/JavaScript/RsaEncryptionModule.js | 113 +++ .../JavaScript/RsaEncryptionWithLib.min.js | 1 + .../Resources/Public/JavaScript/RsaLibrary.js | 884 ++++++++++++++++++ .../Resources/Public/JavaScript/jsbn/LICENSE | 40 - .../Public/JavaScript/jsbn/base64.js | 71 -- .../Resources/Public/JavaScript/jsbn/jsbn.js | 559 ----------- .../Resources/Public/JavaScript/jsbn/jsbn2.js | 648 ------------- .../Resources/Public/JavaScript/jsbn/prng4.js | 45 - .../Resources/Public/JavaScript/jsbn/rng.js | 68 -- .../Resources/Public/JavaScript/jsbn/rsa.js | 112 --- .../Resources/Public/JavaScript/jsbn/rsa2.js | 132 --- .../Resources/Public/JavaScript/rsaauth.js | 23 - .../Public/JavaScript/rsaauth_min.js | 1 - typo3/sysext/rsaauth/ext_localconf.php | 8 +- .../Controller/SetupModuleController.php | 1 + 36 files changed, 1596 insertions(+), 2190 deletions(-) create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-67932-DeprecatedOldRsaauthApi.rst create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Feature-67932-RsaauthApiRewrite.rst delete mode 100644 typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php create mode 100644 typo3/sysext/rsaauth/Classes/RsaEncryptionDecoder.php create mode 100644 typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/BackendLoginFormRsaEncryption.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.min.js create mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js create mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js create mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionWithLib.min.js create mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/LICENSE delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/base64.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn2.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/prng4.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rng.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa2.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth.js delete mode 100644 typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth_min.js diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php index a66ebeb60008..4823fe40dcb6 100644 --- a/typo3/sysext/backend/Classes/Controller/BackendController.php +++ b/typo3/sysext/backend/Classes/Controller/BackendController.php @@ -22,6 +22,7 @@ use TYPO3\CMS\Backend\Module\ModuleLoader; use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; use TYPO3\CMS\Core\Utility\MathUtility; use TYPO3\CMS\Fluid\View\StandaloneView; +use TYPO3\CMS\Rsaauth\RsaEncryptionEncoder; /** * Class for rendering the TYPO3 backend @@ -153,6 +154,10 @@ class BackendController { // load debug console $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DebugConsole'); + // Load RSA encryption + $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class); + $rsaEncryptionEncoder->enableRsaEncryption(TRUE); + $this->pageRenderer->addInlineSetting('ShowItem', 'moduleUrl', BackendUtility::getModuleUrl('show_item')); $this->css = ''; diff --git a/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php b/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php index 554ad8fb2de0..0b7a4b04d953 100644 --- a/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/AjaxRequestHandler.php @@ -46,7 +46,8 @@ class AjaxRequestHandler implements RequestHandlerInterface { 'BackendLogin::refreshLogin', 'BackendLogin::isTimedOut', 'BackendLogin::getChallenge', - 'BackendLogin::getRsaPublicKey' + 'BackendLogin::getRsaPublicKey', + 'RsaEncryption::getRsaPublicKey' ); /** diff --git a/typo3/sysext/backend/Resources/Private/Templates/UserPassLoginForm.html b/typo3/sysext/backend/Resources/Private/Templates/UserPassLoginForm.html index bccc96bbcd22..f21e64b55a91 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/UserPassLoginForm.html +++ b/typo3/sysext/backend/Resources/Private/Templates/UserPassLoginForm.html @@ -4,7 +4,7 @@ <div class="form-group t3js-login-username-section" id="t3-login-username-section"> <div class="form-control-wrap"> <div class="form-control-holder"> - <input type="text" id="t3-username" name="username" value="{presetUsername}" placeholder="{f:translate(key: 'login.username')}" class="form-control input-login t3js-clearable t3js-login-username-field" autofocus="autofocus" required="required"> + <input type="text" id="t3-username" name="username" value="{presetUsername}" placeholder="{f:translate(key: 'login.username')}" class="form-control input-login t3js-clearable t3js-login-username-field" autofocus="autofocus" required="required" /> <div class="form-notice-capslock hidden t3js-login-alert-capslock"> <img src="{images.capslock}" width="14" height="14" alt="{f:translate(key: 'login.error.capslock')}" title="{f:translate(key: 'login.error.capslock')}" /> </div> @@ -14,7 +14,7 @@ <div class="form-group t3js-login-password-section" id="t3-login-password-section"> <div class="form-control-wrap"> <div class="form-control-holder"> - <input type="password" id="t3-password" name="p_field" value="{presetPassword}" placeholder="{f:translate(key: 'login.password')}" class="form-control input-login t3js-clearable t3js-login-password-field" required="required"> + <input type="password" id="t3-password" name="p_field" value="{presetPassword}" placeholder="{f:translate(key: 'login.password')}" class="form-control input-login t3js-clearable t3js-login-password-field" required="required" data-rsa-encryption="t3-field-userident" /> <div class="form-notice-capslock hidden t3js-login-alert-capslock"> <img src="{images.capslock}" width="14" height="14" alt="{f:translate(key: 'login.error.capslock')}" title="{f:translate(key: 'login.error.capslock')}" /> </div> diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js index 2846cdb19e13..bf7f8dabb7c6 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js @@ -197,10 +197,10 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) { $('<p />').text(TYPO3.LLL.core.login_expired), $('<form />', {id: 'beLoginRefresh', method: 'POST', action: TYPO3.settings.ajaxUrls['BackendLogin::login']}).append( $('<div />', {class: 'form-group'}).append( - $('<input />', {type: 'password', name: 'p_field', autofocus: 'autofocus', class: 'form-control', placeholder: TYPO3.LLL.core.refresh_login_password}) + $('<input />', {type: 'password', name: 'p_field', autofocus: 'autofocus', class: 'form-control', placeholder: TYPO3.LLL.core.refresh_login_password, 'data-rsa-encryption': 't3-loginrefres-userident'}) ), $('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}), - $('<input />', {type: 'hidden', name: 'userident'}) + $('<input />', {type: 'hidden', name: 'userident', id: 't3-loginrefres-userident'}) ) ); LoginRefresh.$loginForm.find('.modal-footer').append( @@ -210,7 +210,7 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) { }) ); - LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.triggerSubmitForm); + LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.submitForm); $('body').append(LoginRefresh.$loginForm); }; @@ -295,57 +295,28 @@ define('TYPO3/CMS/Backend/LoginRefresh', ['jquery', 'bootstrap'], function($) { }, 300); }; - /** - * Triggers the form submit based on the security level. - */ - LoginRefresh.triggerSubmitForm = function(e) { - e.preventDefault(); - - switch (TYPO3.configuration.securityLevel) { - case 'rsa': - $.ajax({ - url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'], - method: 'GET', - data: { - skipSessionUpdate: 1 - }, - success: function(response) { - if (response.publicKeyModulus && response.exponent) { - LoginRefresh.submitForm(response); - } - } - }); - break; - default: - LoginRefresh.submitForm(); - } - }; - /** * Creates additional data based on the security level and "submits" the form * via an AJAX request. */ - LoginRefresh.submitForm = function(parameters) { + LoginRefresh.submitForm = function(event) { + event.preventDefault(); + var $form = LoginRefresh.$loginForm.find('form'), $passwordField = $form.find('input[name=p_field]'), $useridentField = $form.find('input[name=userident]'), passwordFieldValue = $passwordField.val(); - if (passwordFieldValue === '') { + if (passwordFieldValue === '' && $useridentField.val() === '') { top.TYPO3.Notification.error(TYPO3.LLL.core.refresh_login_failed, TYPO3.LLL.core.refresh_login_emptyPassword); $passwordField.focus(); return; } - if (TYPO3.configuration.securityLevel === 'rsa') { - var rsa = new RSAKey(); - rsa.setPublic(parameters.publicKeyModulus, parameters.exponent); - var encryptedPassword = rsa.encrypt(passwordFieldValue); - $useridentField.val('rsa:' + hex2b64(encryptedPassword)); - } else { + if (passwordFieldValue) { $useridentField.val(passwordFieldValue); + $passwordField.val(''); } - $passwordField.val(''); var postData = { login_status: 'login' diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/UserPassLogin.js b/typo3/sysext/backend/Resources/Public/JavaScript/UserPassLogin.js index 6261222dc276..cbe102a8aea6 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/UserPassLogin.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/UserPassLogin.js @@ -54,8 +54,10 @@ define('TYPO3/CMS/Backend/UserPassLogin', ['jquery', 'TYPO3/CMS/Backend/Login'], "use strict"; var $passwordField = $(UserPassLogin.options.passwordField); - $(Login.options.useridentField).val($passwordField.val()); - $passwordField.val(''); + if ($passwordField.val()) { + $(Login.options.useridentField).val($passwordField.val()); + $passwordField.val(''); + } }; /** diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-67932-DeprecatedOldRsaauthApi.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-67932-DeprecatedOldRsaauthApi.rst new file mode 100644 index 000000000000..1c1e903248ca --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-67932-DeprecatedOldRsaauthApi.rst @@ -0,0 +1,21 @@ +=========================================================== +Deprecation: #67932 - Deprecated old rsaauth encryption API +=========================================================== + +Description +=========== + +The rsaauth API was rebuilt to be more generic. Therefore the Ajax Handler ``BackendLogin::getRsaPublicKey`` and +the eID script ``FrontendLoginRsaPublicKey`` were marked as deprecated. + + +Affected Installations +====================== + +Any installation using one of the entry points above in a third-party extension. + + +Migration +========= + +There is no reason to use the entry points on your own anymore. Please update your scripts to use the new rsaauth API. diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-67932-RsaauthApiRewrite.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-67932-RsaauthApiRewrite.rst new file mode 100644 index 000000000000..f23db4a1a4e6 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-67932-RsaauthApiRewrite.rst @@ -0,0 +1,71 @@ +================================= +Feature: #67932 - New rsaauth API +================================= + +Description +=========== + +The rsaauth API was rewritten to be more generic and can now be used easily in more +parts of the core as well as in third party extensions. + + +Impact +====== + +Form fields (e.g. password fields) can be encrypted before transmission. This helps to improve the security of +your and your user's data. + + +Examples +======== + +Encode +------ + +Encoding is done automatically via a JavaScript function which gets a public key and encrypts the data. + +1) Include JavaScript to parse form fields for encryption. You can either choose to include a RequireJS module or a +plain Javascript file. + +.. code-block:: php + + $rsaEncryptionEncoder = GeneralUtility::makeInstance(\TYPO3\CMS\Rsaauth\RsaEncryptionEncoder::class); + $rsaEncryptionEncoder->enableRsaEncryption(); // Adds plain JavaScript + $rsaEncryptionEncoder->enableRsaEncryption(TRUE); // Adds RequireJS module + +2) Activate encryption for your from fields with the data attribute ``data-rsa-encryption``. + +.. code-block:: html + + <input type="password" id="pass" name="pass" value="" data-rsa-encryption="" /> + +If you want the encrypted value to be stored in another field, you have to use the RequiredJS module and you can +pass the id of that form field as value to the data attribute. + +.. code-block:: html + + <input type="password" id="t3-password" name="p_field" value="" data-rsa-encryption="t3-field-userident" /> + <input type="hidden" name="userident" id="t3-field-userident" /> + +Decode +------ + +To decode your data you can use the method ``TYPO3\CMS\Rsaauth\RsaEncryptionDecoder::decrypt`` which can +either handle a string or an array as parameter. + +Notice: A RSA public key can only be used once to decrypt data. If you encrypt multiple fields in your form +you have to pass an array to the decrypt function with all data you want to decrypt. The function parses the +values for a ``rsa:`` prefix so you can be sure that non-matching data will not be changed. + +.. code-block:: php + + $rsaEncryptionDecoder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rsaauth\RsaEncryptionDecoder::class); + + // Decrypt a single string + $password = $loginData['uident']; + $decryptedPassword = $rsaEncryptionDecoder->decrypt($password); + + // Decrypt an array + if ($this->isRsaAvailable()) { + $parameters['be_user_data'] = $this->getRsaEncryptionDecoder()->decrypt($parameters['be_user_data']); + } diff --git a/typo3/sysext/felogin/template.html b/typo3/sysext/felogin/template.html index b90e6e34186d..90d53053713a 100644 --- a/typo3/sysext/felogin/template.html +++ b/typo3/sysext/felogin/template.html @@ -56,7 +56,7 @@ </div> <div> <label for="pass">###PASSWORD_LABEL###</label> - <input type="password" id="pass" name="pass" value="" /> + <input type="password" id="pass" name="pass" value="" data-rsa-encryption="" /> </div> <!--###PERMALOGIN_VALID###--> diff --git a/typo3/sysext/rsaauth/Classes/Backend/AjaxLoginHandler.php b/typo3/sysext/rsaauth/Classes/Backend/AjaxLoginHandler.php index 6e2b4f210672..f12cc3c117ec 100644 --- a/typo3/sysext/rsaauth/Classes/Backend/AjaxLoginHandler.php +++ b/typo3/sysext/rsaauth/Classes/Backend/AjaxLoginHandler.php @@ -24,21 +24,12 @@ class AjaxLoginHandler { * * @param array $parameters Parameters (not used) * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $parent The calling parent AJAX object - * @return void + * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8. Please use RsaEncryption::getRsaPublicKey as ajax handler instead. */ public function getRsaPublicKey(array $parameters, \TYPO3\CMS\Core\Http\AjaxRequestHandler $parent) { - $backend = BackendFactory::getBackend(); - if ($backend !== NULL) { - $keyPair = $backend->createNewKeyPair(); - $storage = \TYPO3\CMS\Rsaauth\Storage\StorageFactory::getStorage(); - $storage->put($keyPair->getPrivateKey()); - session_commit(); - $parent->addContent('publicKeyModulus', $keyPair->getPublicKeyModulus()); - $parent->addContent('exponent', sprintf('%x', $keyPair->getExponent())); - $parent->setContentFormat('json'); - } else { - $parent->setError('No OpenSSL backend could be obtained for rsaauth.'); - } + \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction(); + $rsaEncryptionEncoder = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Rsaauth\RsaEncryptionEncoder::class); + $rsaEncryptionEncoder->getRsaPublicKeyAjaxHandler($parameters, $parent); } } \ No newline at end of file diff --git a/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php b/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php deleted file mode 100644 index 60f4b46a5ca2..000000000000 --- a/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -namespace TYPO3\CMS\Rsaauth\Hook; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * This class adds RSA JavaScript to the backend - */ -class BackendHookForAjaxLogin { - - /** - * Adds RSA-specific JavaScript - * - * @param array $configuration - * @param \TYPO3\CMS\Backend\Controller\BackendController $backendController - * @return void - */ - public function addRsaJsLibraries(array $configuration, \TYPO3\CMS\Backend\Controller\BackendController $backendController) { - $javascriptPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath('rsaauth') . 'Resources/Public/JavaScript/'; - $files = array( - 'jsbn/jsbn.js', - 'jsbn/prng4.js', - 'jsbn/rng.js', - 'jsbn/rsa.js', - 'jsbn/base64.js' - ); - foreach ($files as $file) { - $backendController->getPageRenderer()->addJsLibrary($file, $javascriptPath . $file); - } - } - -} diff --git a/typo3/sysext/rsaauth/Classes/Hook/FrontendLoginHook.php b/typo3/sysext/rsaauth/Classes/Hook/FrontendLoginHook.php index 5a2b7ddf600c..367bab63c009 100644 --- a/typo3/sysext/rsaauth/Classes/Hook/FrontendLoginHook.php +++ b/typo3/sysext/rsaauth/Classes/Hook/FrontendLoginHook.php @@ -14,6 +14,9 @@ namespace TYPO3\CMS\Rsaauth\Hook; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Rsaauth\RsaEncryptionEncoder; + /** * This class contains a hook to implement RSA authentication for the TYPO3 * Frontend. Warning: felogin must be USER_INT for this to work! @@ -28,29 +31,13 @@ class FrontendLoginHook { * @return array 0 => onSubmit function, 1 => extra fields and required files */ public function loginFormHook() { - $result = array(0 => '', 1 => ''); - if (trim($GLOBALS['TYPO3_CONF_VARS']['FE']['loginSecurityLevel']) === 'rsa') { - $backend = \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend(); - if ($backend) { - $result[0] = 'return TYPO3FrontendLoginFormRsaEncryption.submitForm(this, TYPO3FrontendLoginFormRsaEncryptionPublicKeyUrl);'; - $javascriptPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/'; - $files = array( - 'jsbn/jsbn.js', - 'jsbn/prng4.js', - 'jsbn/rng.js', - 'jsbn/rsa.js', - 'jsbn/base64.js', - 'FrontendLoginFormRsaEncryption.min.js' - ); - $eIdUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::quoteJSvalue($GLOBALS['TSFE']->absRefPrefix . 'index.php?eID=FrontendLoginRsaPublicKey'); - $additionalHeader = '<script type="text/javascript">var TYPO3FrontendLoginFormRsaEncryptionPublicKeyUrl = ' . $eIdUrl . ';</script>'; - foreach ($files as $file) { - $additionalHeader .= '<script type="text/javascript" src="' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $javascriptPath . $file . '"></script>'; - } - $GLOBALS['TSFE']->additionalHeaderData['rsaauth_js'] = $additionalHeader; - } + /** @var RsaEncryptionEncoder $rsaEncryptionEncoder */ + $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class); + if ($rsaEncryptionEncoder->isAvailable()) { + $rsaEncryptionEncoder->enableRsaEncryption(); } - return $result; + + return array(0 => '', 1 => ''); } } diff --git a/typo3/sysext/rsaauth/Classes/Hook/UserSetupHook.php b/typo3/sysext/rsaauth/Classes/Hook/UserSetupHook.php index 814aa91c98a0..6bc81f3bacfd 100644 --- a/typo3/sysext/rsaauth/Classes/Hook/UserSetupHook.php +++ b/typo3/sysext/rsaauth/Classes/Hook/UserSetupHook.php @@ -14,6 +14,11 @@ namespace TYPO3\CMS\Rsaauth\Hook; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Rsaauth\RsaEncryptionDecoder; +use TYPO3\CMS\Rsaauth\RsaEncryptionEncoder; +use TYPO3\CMS\Setup\Controller\SetupModuleController; + /** * This class provides a hook to the login form to add extra javascript code * and supply a proper form tag. @@ -23,68 +28,33 @@ namespace TYPO3\CMS\Rsaauth\Hook; class UserSetupHook { /** - * Decrypt the password fields if they are filled. + * @var RsaEncryptionDecoder + */ + protected $rsaEncryptionDecoder = NULL; + + /** + * Decrypt all password fields which were encrypted. * * @param array $parameters Parameters to the script - * @return void */ public function decryptPassword(array $parameters) { if ($this->isRsaAvailable()) { - $be_user_data = &$parameters['be_user_data']; - if (substr($be_user_data['password'], 0, 4) === 'rsa:' && substr($be_user_data['password2'], 0, 4) === 'rsa:') { - $backend = \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend(); - /** @var $storage \TYPO3\CMS\Rsaauth\Storage\AbstractStorage */ - $storage = \TYPO3\CMS\Rsaauth\Storage\StorageFactory::getStorage(); - $key = $storage->get(); - $password = $backend->decrypt($key, substr($be_user_data['password'], 4)); - $password2 = $backend->decrypt($key, substr($be_user_data['password2'], 4)); - $passwordCurrent = $backend->decrypt($key, substr($be_user_data['passwordCurrent'], 4)); - $be_user_data['password'] = $password ?: $be_user_data['password']; - $be_user_data['password2'] = $password2 ?: $be_user_data['password2']; - $be_user_data['passwordCurrent'] = $passwordCurrent ?: $be_user_data['passwordCurrent']; - } + // Note: although $parameters is not passed by reference, the 'be_user_data' is a reference + $parameters['be_user_data'] = $this->getRsaEncryptionDecoder()->decrypt($parameters['be_user_data']); } } /** - * Provides form code and javascript for the user setup. + * Includes rsa libraries * * @param array $parameters Parameters to the script - * @param \TYPO3\CMS\Setup\Controller\SetupModuleController $userSetupObject Calling object: user setup module - * @return string The code for the user setup + * @param SetupModuleController $userSetupObject Calling object: user setup module + * @return string */ - public function getLoginScripts(array $parameters, \TYPO3\CMS\Setup\Controller\SetupModuleController $userSetupObject) { - $content = ''; - if ($this->isRsaAvailable()) { - // If we can get the backend, we can proceed - $backend = \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend(); - $javascriptPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/'; - $files = array( - 'jsbn/jsbn.js', - 'jsbn/prng4.js', - 'jsbn/rng.js', - 'jsbn/rsa.js', - 'jsbn/base64.js', - 'rsaauth_min.js' - ); - $content = ''; - foreach ($files as $file) { - $content .= '<script type="text/javascript" src="' . \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL') . $javascriptPath . $file . '"></script>'; - } - // Generate a new key pair - $keyPair = $backend->createNewKeyPair(); - // Save private key - $storage = \TYPO3\CMS\Rsaauth\Storage\StorageFactory::getStorage(); - /** @var $storage \TYPO3\CMS\Rsaauth\Storage\AbstractStorage */ - $storage->put($keyPair->getPrivateKey()); - // Add form tag - $form = '<form action="' . \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleUrl('user_setup') . '" method="post" name="usersetup" enctype="application/x-www-form-urlencoded" onsubmit="tx_rsaauth_encryptUserSetup();">'; - // Add RSA hidden fields - $form .= '<input type="hidden" id="rsa_n" name="n" value="' . htmlspecialchars($keyPair->getPublicKeyModulus()) . '" />'; - $form .= '<input type="hidden" id="rsa_e" name="e" value="' . sprintf('%x', $keyPair->getExponent()) . '" />'; - $userSetupObject->doc->form = $form; - } - return $content; + public function getLoginScripts(array $parameters, SetupModuleController $userSetupObject) { + $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class); + $rsaEncryptionEncoder->enableRsaEncryption(TRUE); + return ''; } /** @@ -93,7 +63,18 @@ class UserSetupHook { * @return bool */ protected function isRsaAvailable() { - return trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) === 'rsa' && \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend() !== NULL; + return trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) === 'rsa' && $this->getRsaEncryptionDecoder()->isAvailable(); + } + + /** + * @return RsaEncryptionDecoder + */ + protected function getRsaEncryptionDecoder() { + if ($this->rsaEncryptionDecoder === NULL) { + $this->rsaEncryptionDecoder = GeneralUtility::makeInstance(RsaEncryptionDecoder::class); + } + + return $this->rsaEncryptionDecoder; } } diff --git a/typo3/sysext/rsaauth/Classes/RsaAuthService.php b/typo3/sysext/rsaauth/Classes/RsaAuthService.php index 491430849959..0ac402eba5ab 100644 --- a/typo3/sysext/rsaauth/Classes/RsaAuthService.php +++ b/typo3/sysext/rsaauth/Classes/RsaAuthService.php @@ -14,6 +14,8 @@ namespace TYPO3\CMS\Rsaauth; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Utility\GeneralUtility; + /** * Service "RSA authentication" for the "rsaauth" extension. This service will * authenticate a user using hos password encoded with one time public key. It @@ -26,11 +28,9 @@ namespace TYPO3\CMS\Rsaauth; class RsaAuthService extends \TYPO3\CMS\Sv\AuthenticationService { /** - * An RSA backend. - * - * @var \TYPO3\CMS\Rsaauth\Backend\AbstractBackend + * @var RsaEncryptionDecoder */ - protected $backend = NULL; + protected $rsaEncryptionDecoder = NULL; /** * Standard extension key for the service @@ -54,7 +54,7 @@ class RsaAuthService extends \TYPO3\CMS\Sv\AuthenticationService { * * @var string */ - public $scriptRelPath = 'sv1/class.tx_rsaauth_sv1.php'; + public $scriptRelPath = 'Classes/RsaAuthService.php'; /** * Process the submitted credentials. @@ -67,27 +67,20 @@ class RsaAuthService extends \TYPO3\CMS\Sv\AuthenticationService { public function processLoginData(array &$loginData, $passwordTransmissionStrategy) { $isProcessed = FALSE; if ($passwordTransmissionStrategy === 'rsa') { - $storage = \TYPO3\CMS\Rsaauth\Storage\StorageFactory::getStorage(); - /** @var $storage \TYPO3\CMS\Rsaauth\Storage\AbstractStorage */ - // Decrypt the password $password = $loginData['uident']; - $key = $storage->get(); - if ($key !== NULL && substr($password, 0, 4) === 'rsa:') { - // Decode password and store it in loginData - $decryptedPassword = $this->backend->decrypt($key, substr($password, 4)); - if ($decryptedPassword !== NULL) { + if (substr($password, 0, 4) === 'rsa:') { + $decryptedPassword = $this->getRsaEncryptionDecoder()->decrypt($password); + if ($decryptedPassword !== $password) { $loginData['uident_text'] = $decryptedPassword; $isProcessed = TRUE; } else { if ($this->pObj->writeDevLog) { - \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Process login data: Failed to RSA decrypt password', \TYPO3\CMS\Rsaauth\RsaAuthService::class); + GeneralUtility::devLog('Process login data: Failed to RSA decrypt password', RsaAuthService::class); } } - // Remove the key - $storage->put(NULL); } else { if ($this->pObj->writeDevLog) { - \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Process login data: passwordTransmissionStrategy has been set to "rsa" but no rsa encrypted password has been found.', \TYPO3\CMS\Rsaauth\RsaAuthService::class); + GeneralUtility::devLog('Process login data: passwordTransmissionStrategy has been set to "rsa" but no rsa encrypted password has been found.', RsaAuthService::class); } } } @@ -100,15 +93,18 @@ class RsaAuthService extends \TYPO3\CMS\Sv\AuthenticationService { * @return bool */ public function init() { - $available = parent::init(); - if ($available) { - // Get the backend - $this->backend = \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend(); - if ($this->backend === NULL) { - $available = FALSE; - } + return parent::init() && $this->getRsaEncryptionDecoder()->isAvailable(); + } + + /** + * @return RsaEncryptionDecoder + */ + protected function getRsaEncryptionDecoder() { + if ($this->rsaEncryptionDecoder === NULL) { + $this->rsaEncryptionDecoder = GeneralUtility::makeInstance(RsaEncryptionDecoder::class); } - return $available; + + return $this->rsaEncryptionDecoder; } } diff --git a/typo3/sysext/rsaauth/Classes/RsaEncryptionDecoder.php b/typo3/sysext/rsaauth/Classes/RsaEncryptionDecoder.php new file mode 100644 index 000000000000..0ad0cf96c2c7 --- /dev/null +++ b/typo3/sysext/rsaauth/Classes/RsaEncryptionDecoder.php @@ -0,0 +1,107 @@ +<?php +namespace TYPO3\CMS\Rsaauth; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * This class decodes rsa protected data + */ +class RsaEncryptionDecoder implements \TYPO3\CMS\Core\SingletonInterface { + + /** + * @var Backend\AbstractBackend + */ + protected $backend = NULL; + + /** + * @var Storage\AbstractStorage + */ + protected $storage = NULL; + + /** + * @var string + */ + protected $key = NULL; + + /** + * @param string|array $data + * @return string|array + */ + public function decrypt($data) { + if ($this->getKey() === '' || !$this->isAvailable()) { + return $data; + } + + $decryptedData = is_array($data) ? $data : array($data); + + foreach ($decryptedData as $key => $value) { + if (substr($value, 0, 4) !== 'rsa:') { + continue; + } + + $decryptedValue = $this->getBackend()->decrypt($this->getKey(), substr($value, 4)); + if ($decryptedValue !== NULL) { + $decryptedData[$key] = $decryptedValue; + } + } + $this->getStorage()->put(NULL); + + return is_array($data) ? $decryptedData : $decryptedData[0]; + } + + /** + * @return bool + */ + public function isAvailable() { + return $this->getBackend() instanceof Backend\AbstractBackend; + } + + /** + * @return string + */ + protected function getKey() { + if ($this->key === NULL) { + $this->key = $this->getStorage()->get(); + + if ($this->key === NULL) { + $this->key = ''; + } + } + + return $this->key; + } + + /** + * @return Backend\AbstractBackend|NULL + */ + protected function getBackend() { + if ($this->backend === NULL) { + $this->backend = Backend\BackendFactory::getBackend(); + } + + return $this->backend; + } + + /** + * @return Storage\AbstractStorage + */ + protected function getStorage() { + if ($this->storage === NULL) { + $this->storage = Storage\StorageFactory::getStorage(); + } + + return $this->storage; + } + +} diff --git a/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php b/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php new file mode 100644 index 000000000000..69332cfbb634 --- /dev/null +++ b/typo3/sysext/rsaauth/Classes/RsaEncryptionEncoder.php @@ -0,0 +1,115 @@ +<?php +namespace TYPO3\CMS\Rsaauth; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Http\AjaxRequestHandler; +use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; + +/** + * This class adds necessary Javascript code to encrypt fields in a form + */ +class RsaEncryptionEncoder implements SingletonInterface { + + /** + * @var bool + */ + protected $moduleLoaded = FALSE; + + /** + * @var PageRenderer + */ + protected $pageRenderer = NULL; + + /** + * Load all necessary Javascript files + * + * @param bool $useRequireJsModule + */ + public function enableRsaEncryption($useRequireJsModule = FALSE) { + if ($this->moduleLoaded || !$this->isAvailable()) { + return; + } + $this->moduleLoaded = TRUE; + $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class); + // Include necessary javascript files + if ($useRequireJsModule) { + $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rsaauth/RsaEncryptionModule'); + } else { + // Register ajax handler url + $code = 'var TYPO3RsaEncryptionPublicKeyUrl = ' . GeneralUtility::quoteJSvalue(BackendUtility::getAjaxUrl('RsaEncryption::getRsaPublicKey')) . ';'; + $pageRenderer->addJsInlineCode('TYPO3RsaEncryptionPublicKeyUrl', $code); + $javascriptPath = ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/'; + if (!$GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['debug']) { + $files = array('RsaEncryptionWithLib.min.js'); + } else { + $files = array( + 'RsaLibrary.js', + 'RsaEncryption.js', + ); + } + foreach ($files as $file) { + $pageRenderer->addJsFile($javascriptPath . $file); + } + } + } + + /** + * @return bool + */ + public function isAvailable() { + return trim($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['loginSecurityLevel']) === 'rsa'; + } + + /** + * Gets RSA Public Key. + * + * @return Keypair|NULL + */ + public function getRsaPublicKey() { + $keyPair = NULL; + $backend = Backend\BackendFactory::getBackend(); + if ($backend !== NULL) { + $keyPair = $backend->createNewKeyPair(); + $storage = Storage\StorageFactory::getStorage(); + $storage->put($keyPair->getPrivateKey()); + session_commit(); + } + + return $keyPair; + } + + /** + * Ajax handler to return a RSA public key. + * + * @param array $parameters Parameters (not used) + * @param AjaxRequestHandler $parent The calling parent AJAX object + */ + public function getRsaPublicKeyAjaxHandler(array $parameters, AjaxRequestHandler $parent) { + $keyPair = $this->getRsaPublicKey(); + if ($keyPair !== NULL) { + $parent->addContent('publicKeyModulus', $keyPair->getPublicKeyModulus()); + $parent->addContent('spacer', ':'); + $parent->addContent('exponent', sprintf('%x', $keyPair->getExponent())); + $parent->setContentFormat('plain'); + } else { + $parent->setError('No OpenSSL backend could be obtained for rsaauth.'); + } + } + +} diff --git a/typo3/sysext/rsaauth/Classes/Slot/UsernamePasswordProviderSlot.php b/typo3/sysext/rsaauth/Classes/Slot/UsernamePasswordProviderSlot.php index e6b962dbaafc..e98bb3834d72 100644 --- a/typo3/sysext/rsaauth/Classes/Slot/UsernamePasswordProviderSlot.php +++ b/typo3/sysext/rsaauth/Classes/Slot/UsernamePasswordProviderSlot.php @@ -14,9 +14,9 @@ namespace TYPO3\CMS\Rsaauth\Slot; * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Backend\Controller\LoginController; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Rsaauth\RsaEncryptionEncoder; /** * Class UsernamePasswordProviderSlot @@ -27,21 +27,7 @@ class UsernamePasswordProviderSlot { * @param PageRenderer $pageRenderer */ public function getPageRenderer(PageRenderer $pageRenderer) { - $loginSecurityLevel = trim($GLOBALS['TYPO3_CONF_VARS']['BE']['loginSecurityLevel']) ?: 'normal'; - if ($loginSecurityLevel === 'rsa') { - $javascriptPath = '../' . ExtensionManagementUtility::siteRelPath('rsaauth') . 'Resources/Public/JavaScript/'; - $files = array( - 'jsbn/jsbn.js', - 'jsbn/prng4.js', - 'jsbn/rng.js', - 'jsbn/rsa.js', - 'jsbn/base64.js' - ); - foreach ($files as $file) { - $pageRenderer->addJsFile($javascriptPath . $file); - } - - $pageRenderer->loadRequireJsModule('TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption'); - } + $rsaEncryptionEncoder = GeneralUtility::makeInstance(RsaEncryptionEncoder::class); + $rsaEncryptionEncoder->enableRsaEncryption(TRUE); } } diff --git a/typo3/sysext/rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php b/typo3/sysext/rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php index 9abb815a92d2..73288b3a335c 100644 --- a/typo3/sysext/rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php +++ b/typo3/sysext/rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php @@ -14,6 +14,10 @@ defined('TYPO3_MODE') or die(); * The TYPO3 project - inspiring people to share! */ +\TYPO3\CMS\Core\Utility\GeneralUtility::deprecationLog( + 'The generation of the RSA public key was moved to the ajax handler \'RsaEncryptionEncoder::getRsaPublicKey\'. Please use the rsaauth api to encrypt your form fields. This script will be removed in TYPO3 CMS 8.' +); + /** @var \TYPO3\CMS\Rsaauth\Backend\AbstractBackend $backend */ $backend = \TYPO3\CMS\Rsaauth\Backend\BackendFactory::getBackend(); if ($backend !== NULL) { diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/BackendLoginFormRsaEncryption.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/BackendLoginFormRsaEncryption.js deleted file mode 100644 index 5b9b63c38a7f..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/BackendLoginFormRsaEncryption.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Object that handles RSA encryption and submission of the form - */ -define( - 'TYPO3/CMS/Rsaauth/BackendLoginFormRsaEncryption', - ['jquery', 'TYPO3/CMS/Backend/Login', 'TYPO3/CMS/Backend/UserPassLogin'], - function($, Login, UserPassLogin) { - - var RsaBackendLogin = { - - /** - * Field in which users enter their password - */ - userPasswordField: false, - - /** - * Field that is used by TYPO3 to evaluate the password during login process - */ - typo3PasswordField: false, - - /** - * Remember if we fetched the RSA key already - */ - fetchedRsaKey: false, - - /** - * Replace event handler of submit button - */ - initialize: function() { - this.userPasswordField = UserPassLogin.options.passwordField; - this.typo3PasswordField = Login.options.useridentField; - this.loginForm = Login.options.loginForm; - - Login.options.submitHandler = this.handleFormSubmitRequest; - }, - - /** - * Fetches a new public key by Ajax and encrypts the password for transmission - * - * @param event - */ - handleFormSubmitRequest: function(event) { - if (!RsaBackendLogin.fetchedRsaKey) { - RsaBackendLogin.fetchedRsaKey = true; - - event.preventDefault(); - - $.ajax({ - url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'], - data: {'skipSessionUpdate': 1}, - success: RsaBackendLogin.handlePublicKeyResponse, - dataType: 'json' - }); - } else { - // we come here again when the submit is triggered below - // reset the variable to fetch a new key for next attempt - RsaBackendLogin.fetchedRsaKey = false; - } - }, - - /** - * Parses the Json response and triggers submission of the form - * - * @param publicKey Ajax response object - */ - handlePublicKeyResponse: function(publicKey) { - if (!publicKey.publicKeyModulus || !publicKey.exponent) { - alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); - return; - } - - var rsa = new RSAKey(); - rsa.setPublic(publicKey.publicKeyModulus, publicKey.exponent); - var encryptedPassword = rsa.encrypt($(RsaBackendLogin.userPasswordField).val()); - - // Reset user password field to prevent it from being submitted - $(RsaBackendLogin.userPasswordField).val(''); - $(RsaBackendLogin.typo3PasswordField).val('rsa:' + hex2b64(encryptedPassword)); - - var $formElement = $(RsaBackendLogin.loginForm); - - // Create a hidden input field to fake pressing the submit button - $formElement.append('<input type="hidden" name="commandLI" value="Submit">'); - - // Submit the form - $formElement.trigger('submit'); - } - }; - - RsaBackendLogin.initialize(); -}); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.js deleted file mode 100644 index 95d36b3b32a9..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.js +++ /dev/null @@ -1,154 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Object that handles RSA encryption and submission of the FE login form - */ -TYPO3FrontendLoginFormRsaEncryption = function() { - - var rsaFrontendLogin = function(form, publicKeyEndpointUrl) { - - /** - * Submitted form element - */ - this.form = form; - - /** - * XMLHttpRequest - */ - this.xhr = null; - - /** - * Endpoint URL to fetch the public key for encryption - */ - this.publicKeyEndpointUrl = publicKeyEndpointUrl; - - /** - * Field in which users enter their password - */ - this.userPasswordField = form.pass; - - /** - * Fetches a new public key by Ajax and encrypts the password for transmission - */ - this.handleFormSubmitRequest = function() { - var rsaFrontendLogin = this; - this.ajaxCall( - this.publicKeyEndpointUrl, - function(response) { - rsaFrontendLogin.handlePublicKeyResponse(response, rsaFrontendLogin); - } - ); - }; - - /** - * Do Ajax call to fetch RSA public key - */ - this.ajaxCall = function(url, callback) { - - // abort previous request, only last request/generated key pair can be used - if (this.xhr) { - this.xhr.abort(); - } - - if (typeof XMLHttpRequest !== 'undefined') { - this.xhr = new XMLHttpRequest(); - } else { - var versions = [ - "MSXML2.XmlHttp.5.0", - "MSXML2.XmlHttp.4.0", - "MSXML2.XmlHttp.3.0", - "MSXML2.XmlHttp.2.0", - "Microsoft.XmlHttp" - ]; - for (var i = 0, len = versions.length; i < len; i++) { - try { - this.xhr = new ActiveXObject(versions[i]); - break; - } catch(e) {} - } - } - - this.xhr.onreadystatechange = function() { - // only process requests that are ready and have a status (not aborted) - if (this.readyState === 4 && this.status > 0) { - callback(this); - } - }; - - this.xhr.open('GET', url, true); - this.xhr.send(''); - }; - - /** - * Parses the response and triggers submission of the form - * - * @param response Ajax response object - * @param rsaFrontendLogin current processed object - */ - this.handlePublicKeyResponse = function(response, rsaFrontendLogin) { - var publicKey = response.responseText.split(':'); - if (publicKey[0] && publicKey[1]) { - rsaFrontendLogin.encryptPasswordAndSubmitForm(publicKey[0], publicKey[1]); - } else { - alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); - } - }; - - /** - * Uses the public key with the RSA library to encrypt the password. - * - * @param publicKeyModulus - * @param exponent - */ - this.encryptPasswordAndSubmitForm = function(publicKeyModulus, exponent) { - var rsa, encryptedPassword; - - rsa = new RSAKey(); - rsa.setPublic(publicKeyModulus, exponent); - encryptedPassword = rsa.encrypt(this.userPasswordField.value); - - // replace password value with encrypted password - this.userPasswordField.value = 'rsa:' + hex2b64(encryptedPassword); - - // Submit the form again but now with encrypted pass - document.createElement("form").submit.call(this.form); - }; - }; - - /** - * Encrypt password on submit - * - * @param form - * @param publicKeyEndpointUrl - * @return boolean - */ - this.submitForm = function(form, publicKeyEndpointUrl) { - - if (!form.rsaFrontendLogin) { - form.rsaFrontendLogin = new rsaFrontendLogin(form, publicKeyEndpointUrl); - } - - // if pass is not encrypted yet fetch public key and encrypt pass - if (!form.pass.value.match(/^rsa:/) ) { - form.rsaFrontendLogin.handleFormSubmitRequest(); - return false; - - // pass is encrypted so form can be submitted - } else { - return true; - } - }; - - return this; -}(); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.min.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.min.js deleted file mode 100644 index 700e1bbd1d7b..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/FrontendLoginFormRsaEncryption.min.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** Object that handles RSA encryption and submission of the FE login form */ -TYPO3FrontendLoginFormRsaEncryption=function(){var e=function(e,t){this.form=e;this.xhr=null;this.publicKeyEndpointUrl=t;this.userPasswordField=e.pass;this.handleFormSubmitRequest=function(){var e=this;this.ajaxCall(this.publicKeyEndpointUrl,function(t){e.handlePublicKeyResponse(t,e)})};this.ajaxCall=function(e,t){if(this.xhr){this.xhr.abort()}if(typeof XMLHttpRequest!=="undefined"){this.xhr=new XMLHttpRequest}else{var n=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"];for(var r=0,i=n.length;r<i;r++){try{this.xhr=new ActiveXObject(n[r]);break}catch(s){}}}this.xhr.onreadystatechange=function(){if(this.readyState===4&&this.status>0){t(this)}};this.xhr.open("GET",e,true);this.xhr.send("")};this.handlePublicKeyResponse=function(e,t){var n=e.responseText.split(":");if(n[0]&&n[1]){t.encryptPasswordAndSubmitForm(n[0],n[1])}else{alert("No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.")}};this.encryptPasswordAndSubmitForm=function(e,t){var n,r;n=new RSAKey;n.setPublic(e,t);r=n.encrypt(this.userPasswordField.value);this.userPasswordField.value="rsa:"+hex2b64(r);document.createElement("form").submit.call(this.form)}};this.submitForm=function(t,n){if(!t.rsaFrontendLogin){t.rsaFrontendLogin=new e(t,n)}if(!t.pass.value.match(/^rsa:/)){t.rsaFrontendLogin.handleFormSubmitRequest();return false}else{return true}};return this}() \ No newline at end of file diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js new file mode 100644 index 000000000000..75c5426fd3fb --- /dev/null +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js @@ -0,0 +1,180 @@ +(function() { + 'use strict'; + + /** + * Prevent calling the function multiple times + */ + var documentReadyFunctionCalled = false; + + var rsaEncryption = function(form) { + + /** + * Submitted form element + */ + this.form = form; + + /** + * Store found fields in an array + */ + this.fields = []; + + /** + * XMLHttpRequest + */ + this.xhr = null; + + /** + * Remember if we fetched the RSA key already + */ + this.fetchedRsaKey = false; + + /** + * Fetches a new public key by Ajax and encrypts the password for transmission + */ + this.handleFormSubmitRequest = function(event) { + var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption; + if (!rsaEncryption) { + return; + } + if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) { + rsaEncryption.fetchedRsaKey = true; + rsaEncryption.ajaxCall( + TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP + rsaEncryption, + function(response) { + rsaEncryption.handlePublicKeyResponse(response, rsaEncryption); + } + ); + + if (event.preventDefault) { + event.preventDefault(); + } else if (window.event) { + window.event.returnValue = false; + } + } + }; + + this.ajaxCall = function(url, rsaEncryption, callback) { + // Abort previous request, only last request/generated key pair can be used + if (rsaEncryption.xhr) { + rsaEncryption.xhr.abort(); + } + + if (typeof XMLHttpRequest !== 'undefined') { + rsaEncryption.xhr = new XMLHttpRequest(); + } else { + var versions = [ + 'MSXML2.XmlHttp.5.0', + 'MSXML2.XmlHttp.4.0', + 'MSXML2.XmlHttp.3.0', + 'MSXML2.XmlHttp.2.0', + 'Microsoft.XmlHttp' + ]; + for (var i = 0, count = versions.length; i < count; i++) { + try { + rsaEncryption.xhr = new ActiveXObject(versions[i]); + break; + } catch (e) { + } + } + } + + rsaEncryption.xhr.onreadystatechange = function() { + // Only process requests that are ready and have a status (not aborted) + if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) { + callback(rsaEncryption.xhr); + } + }; + + rsaEncryption.xhr.open('GET', url, true); + rsaEncryption.xhr.send(''); + }; + + this.handlePublicKeyResponse = function(response, rsaEncryption) { + var publicKey = response.responseText.split(':'); + if (!publicKey[0] || !publicKey[1]) { + alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); + return false; + } + + var rsa = new RSAKey(); + rsa.setPublic(publicKey[0], publicKey[1]); + for (var i = rsaEncryption.fields.length; i--;) { + var field = rsaEncryption.fields[i]; + var encryptedValue = rsa.encrypt(field.value); + // Replace value with encrypted value + field.value = 'rsa:' + hex2b64(encryptedValue); + } + + // Submit the form again but now with encrypted values + var form = document.createElement('form'); + if (form.submit.call) { + form.submit.call(rsaEncryption.form); + } else { + var fields = rsaEncryption.form.getElementsByTagName('*'); + for (var j = fields.length; j--;) { + var submitField = fields[j]; + if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") { + submitField.click(); + } + } + } + }; + }; + + /** + * Bind submit handler to all forms with input:data-rsa-encryption fields + */ + function ready() { + if (documentReadyFunctionCalled) { + return; + } + + documentReadyFunctionCalled = true; + rng_seed_time(); + var forms = document.getElementsByTagName('form'); + for (var i = forms.length; i--;) { + var form = forms[i]; + var fields = form.getElementsByTagName('*'); + for (var j = fields.length; j--;) { + var field = fields[j]; + if (field.nodeName.toLowerCase() === 'input') { + var dataAttribute = field.getAttribute('data-rsa-encryption'); + if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) { + if (!form.rsaEncryption) { + form.rsaEncryption = new rsaEncryption(form); + if (form.addEventListener) { + form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false); + } else if (form.attachEvent) { + form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest); + } + } + form.rsaEncryption.fields.push(field); + } + } + } + } + } + + // If the document is ready, callback function can be called + if (document.readyState === 'complete') { + setTimeout(ready, 1); + } else { + // Install event handlers for older browsers + if (document.addEventListener) { + // First register DOMContentLoaded event + document.addEventListener('DOMContentLoaded', ready, false); + // Register backup on windows object + window.addEventListener('load', ready, false); + } else { + // Fallback for Internet Explorer + document.attachEvent('onreadystatechange', function() { + if (document.readyState === 'complete') { + ready(); + } + }); + window.attachEvent('onload', ready); + } + } + +})(); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js new file mode 100644 index 000000000000..c16e732a837b --- /dev/null +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js @@ -0,0 +1,113 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Object that handles RSA encryption and submission of the form + */ +define('TYPO3/CMS/Rsaauth/RsaEncryptionModule', ['jquery', './RsaLibrary'], function($) { + 'use strict'; + + var RsaEncryption = { + + /** + * Remember the form which was submitted + */ + $currentForm: null, + + /** + * Remember if we fetched the RSA key already + */ + fetchedRsaKey: false, + + /** + * Replace event handler of submit button + */ + initialize: function() { + $(':input[data-rsa-encryption]').closest('form').each(function() { + var $this = $(this); + $this.on('submit', RsaEncryption.handleFormSubmitRequest); + // Bind submit event first (this is a dirty hack with jquery internals, but there is no way around that) + var handlers = $._data(this, 'events').submit; + var handler = handlers.pop(); + handlers.unshift(handler); + }); + rng_seed_time(); + }, + + /** + * Fetches a new public key by Ajax and encrypts the password for transmission + * + * @param event + */ + handleFormSubmitRequest: function(event) { + if (!RsaEncryption.fetchedRsaKey) { + event.stopImmediatePropagation(); + + RsaEncryption.fetchedRsaKey = true; + RsaEncryption.$currentForm = $(this); + + $.ajax({ + url: TYPO3.settings.ajaxUrls['RsaEncryption::getRsaPublicKey'], + data: {'skipSessionUpdate': 1}, + success: RsaEncryption.handlePublicKeyResponse + }); + + return false; + } else { + // we come here again when the submit is triggered below + // reset the variable to fetch a new key for next attempt + RsaEncryption.fetchedRsaKey = false; + } + }, + + /** + * Parses the Json response and triggers submission of the form + * + * @param response Ajax response object + */ + handlePublicKeyResponse: function(response) { + var publicKey = response.split(':'); + if (!publicKey[0] || !publicKey[1]) { + alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); + return; + } + + var rsa = new RSAKey(); + rsa.setPublic(publicKey[0], publicKey[1]); + RsaEncryption.$currentForm.find(':input[data-rsa-encryption]').each(function() { + var $this = $(this); + var encryptedPassword = rsa.encrypt($this.val()); + var dataAttribute = $this.data('rsa-encryption'); + + if (!dataAttribute) { + $this.val('rsa:' + hex2b64(encryptedPassword)); + } else { + var $typo3Field = $('#' + dataAttribute); + $typo3Field.val('rsa:' + hex2b64(encryptedPassword)); + // Reset user password field to prevent it from being submitted + $this.val(''); + } + }); + + // Create a hidden input field to fake pressing the submit button + RsaEncryption.$currentForm.append('<input type="hidden" name="commandLI" value="Submit">'); + + // Submit the form + RsaEncryption.$currentForm.trigger('submit'); + } + }; + + $(document).ready(RsaEncryption.initialize); + + return RsaEncryption; +}); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionWithLib.min.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionWithLib.min.js new file mode 100644 index 000000000000..3a4f961ee3a4 --- /dev/null +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionWithLib.min.js @@ -0,0 +1 @@ +function hex2b64(t){var r,n,e="";for(r=0;r+3<=t.length;r+=3)n=parseInt(t.substring(r,r+3),16),e+=b64map.charAt(n>>6)+b64map.charAt(63&n);for(r+1==t.length?(n=parseInt(t.substring(r,r+1),16),e+=b64map.charAt(n<<2)):r+2==t.length&&(n=parseInt(t.substring(r,r+2),16),e+=b64map.charAt(n>>2)+b64map.charAt((3&n)<<4));(3&e.length)>0;)e+=b64padchar;return e}function b64tohex(t){var r,n,e="",i=0;for(r=0;r<t.length&&t.charAt(r)!=b64padchar;++r)v=b64map.indexOf(t.charAt(r)),v<0||(0==i?(e+=int2char(v>>2),n=3&v,i=1):1==i?(e+=int2char(n<<2|v>>4),n=15&v,i=2):2==i?(e+=int2char(n),e+=int2char(v>>2),n=3&v,i=3):(e+=int2char(n<<2|v>>4),e+=int2char(15&v),i=0));return 1==i&&(e+=int2char(n<<2)),e}function b64toBA(t){var r,n=b64tohex(t),e=new Array;for(r=0;2*r<n.length;++r)e[r]=parseInt(n.substring(2*r,2*r+2),16);return e}function BigInteger(t,r,n){null!=t&&("number"==typeof t?this.fromNumber(t,r,n):null==r&&"string"!=typeof t?this.fromString(t,256):this.fromString(t,r))}function nbi(){return new BigInteger(null)}function am1(t,r,n,e,i,o){for(;--o>=0;){var s=r*this[t++]+n[e]+i;i=Math.floor(s/67108864),n[e++]=67108863&s}return i}function am2(t,r,n,e,i,o){for(var s=32767&r,h=r>>15;--o>=0;){var a=32767&this[t],p=this[t++]>>15,u=h*a+p*s;a=s*a+((32767&u)<<15)+n[e]+(1073741823&i),i=(a>>>30)+(u>>>15)+h*p+(i>>>30),n[e++]=1073741823&a}return i}function am3(t,r,n,e,i,o){for(var s=16383&r,h=r>>14;--o>=0;){var a=16383&this[t],p=this[t++]>>14,u=h*a+p*s;a=s*a+((16383&u)<<14)+n[e]+i,i=(a>>28)+(u>>14)+h*p,n[e++]=268435455&a}return i}function int2char(t){return BI_RM.charAt(t)}function intAt(t,r){var n=BI_RC[t.charCodeAt(r)];return null==n?-1:n}function bnpCopyTo(t){for(var r=this.t-1;r>=0;--r)t[r]=this[r];t.t=this.t,t.s=this.s}function bnpFromInt(t){this.t=1,this.s=0>t?-1:0,t>0?this[0]=t:-1>t?this[0]=t+this.DV:this.t=0}function nbv(t){var r=nbi();return r.fromInt(t),r}function bnpFromString(t,r){var n;if(16==r)n=4;else if(8==r)n=3;else if(256==r)n=8;else if(2==r)n=1;else if(32==r)n=5;else{if(4!=r)return void this.fromRadix(t,r);n=2}this.t=0,this.s=0;for(var e=t.length,i=!1,o=0;--e>=0;){var s=8==n?255&t[e]:intAt(t,e);0>s?"-"==t.charAt(e)&&(i=!0):(i=!1,0==o?this[this.t++]=s:o+n>this.DB?(this[this.t-1]|=(s&(1<<this.DB-o)-1)<<o,this[this.t++]=s>>this.DB-o):this[this.t-1]|=s<<o,o+=n,o>=this.DB&&(o-=this.DB))}8==n&&0!=(128&t[0])&&(this.s=-1,o>0&&(this[this.t-1]|=(1<<this.DB-o)-1<<o)),this.clamp(),i&&BigInteger.ZERO.subTo(this,this)}function bnpClamp(){for(var t=this.s&this.DM;this.t>0&&this[this.t-1]==t;)--this.t}function bnToString(t){if(this.s<0)return"-"+this.negate().toString(t);var r;if(16==t)r=4;else if(8==t)r=3;else if(2==t)r=1;else if(32==t)r=5;else{if(4!=t)return this.toRadix(t);r=2}var n,e=(1<<r)-1,i=!1,o="",s=this.t,h=this.DB-s*this.DB%r;if(s-->0)for(h<this.DB&&(n=this[s]>>h)>0&&(i=!0,o=int2char(n));s>=0;)r>h?(n=(this[s]&(1<<h)-1)<<r-h,n|=this[--s]>>(h+=this.DB-r)):(n=this[s]>>(h-=r)&e,0>=h&&(h+=this.DB,--s)),n>0&&(i=!0),i&&(o+=int2char(n));return i?o:"0"}function bnNegate(){var t=nbi();return BigInteger.ZERO.subTo(this,t),t}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(t){var r=this.s-t.s;if(0!=r)return r;var n=this.t;if(r=n-t.t,0!=r)return this.s<0?-r:r;for(;--n>=0;)if(0!=(r=this[n]-t[n]))return r;return 0}function nbits(t){var r,n=1;return 0!=(r=t>>>16)&&(t=r,n+=16),0!=(r=t>>8)&&(t=r,n+=8),0!=(r=t>>4)&&(t=r,n+=4),0!=(r=t>>2)&&(t=r,n+=2),0!=(r=t>>1)&&(t=r,n+=1),n}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(t,r){var n;for(n=this.t-1;n>=0;--n)r[n+t]=this[n];for(n=t-1;n>=0;--n)r[n]=0;r.t=this.t+t,r.s=this.s}function bnpDRShiftTo(t,r){for(var n=t;n<this.t;++n)r[n-t]=this[n];r.t=Math.max(this.t-t,0),r.s=this.s}function bnpLShiftTo(t,r){var n,e=t%this.DB,i=this.DB-e,o=(1<<i)-1,s=Math.floor(t/this.DB),h=this.s<<e&this.DM;for(n=this.t-1;n>=0;--n)r[n+s+1]=this[n]>>i|h,h=(this[n]&o)<<e;for(n=s-1;n>=0;--n)r[n]=0;r[s]=h,r.t=this.t+s+1,r.s=this.s,r.clamp()}function bnpRShiftTo(t,r){r.s=this.s;var n=Math.floor(t/this.DB);if(n>=this.t)return void(r.t=0);var e=t%this.DB,i=this.DB-e,o=(1<<e)-1;r[0]=this[n]>>e;for(var s=n+1;s<this.t;++s)r[s-n-1]|=(this[s]&o)<<i,r[s-n]=this[s]>>e;e>0&&(r[this.t-n-1]|=(this.s&o)<<i),r.t=this.t-n,r.clamp()}function bnpSubTo(t,r){for(var n=0,e=0,i=Math.min(t.t,this.t);i>n;)e+=this[n]-t[n],r[n++]=e&this.DM,e>>=this.DB;if(t.t<this.t){for(e-=t.s;n<this.t;)e+=this[n],r[n++]=e&this.DM,e>>=this.DB;e+=this.s}else{for(e+=this.s;n<t.t;)e-=t[n],r[n++]=e&this.DM,e>>=this.DB;e-=t.s}r.s=0>e?-1:0,-1>e?r[n++]=this.DV+e:e>0&&(r[n++]=e),r.t=n,r.clamp()}function bnpMultiplyTo(t,r){var n=this.abs(),e=t.abs(),i=n.t;for(r.t=i+e.t;--i>=0;)r[i]=0;for(i=0;i<e.t;++i)r[i+n.t]=n.am(0,e[i],r,i,0,n.t);r.s=0,r.clamp(),this.s!=t.s&&BigInteger.ZERO.subTo(r,r)}function bnpSquareTo(t){for(var r=this.abs(),n=t.t=2*r.t;--n>=0;)t[n]=0;for(n=0;n<r.t-1;++n){var e=r.am(n,r[n],t,2*n,0,1);(t[n+r.t]+=r.am(n+1,2*r[n],t,2*n+1,e,r.t-n-1))>=r.DV&&(t[n+r.t]-=r.DV,t[n+r.t+1]=1)}t.t>0&&(t[t.t-1]+=r.am(n,r[n],t,2*n,0,1)),t.s=0,t.clamp()}function bnpDivRemTo(t,r,n){var e=t.abs();if(!(e.t<=0)){var i=this.abs();if(i.t<e.t)return null!=r&&r.fromInt(0),void(null!=n&&this.copyTo(n));null==n&&(n=nbi());var o=nbi(),s=this.s,h=t.s,a=this.DB-nbits(e[e.t-1]);a>0?(e.lShiftTo(a,o),i.lShiftTo(a,n)):(e.copyTo(o),i.copyTo(n));var p=o.t,u=o[p-1];if(0!=u){var g=u*(1<<this.F1)+(p>1?o[p-2]>>this.F2:0),c=this.FV/g,f=(1<<this.F1)/g,l=1<<this.F2,m=n.t,v=m-p,b=null==r?nbi():r;for(o.dlShiftTo(v,b),n.compareTo(b)>=0&&(n[n.t++]=1,n.subTo(b,n)),BigInteger.ONE.dlShiftTo(p,b),b.subTo(o,o);o.t<p;)o[o.t++]=0;for(;--v>=0;){var d=n[--m]==u?this.DM:Math.floor(n[m]*c+(n[m-1]+l)*f);if((n[m]+=o.am(0,d,n,v,0,p))<d)for(o.dlShiftTo(v,b),n.subTo(b,n);n[m]<--d;)n.subTo(b,n)}null!=r&&(n.drShiftTo(p,r),s!=h&&BigInteger.ZERO.subTo(r,r)),n.t=p,n.clamp(),a>0&&n.rShiftTo(a,n),0>s&&BigInteger.ZERO.subTo(n,n)}}}function bnMod(t){var r=nbi();return this.abs().divRemTo(t,null,r),this.s<0&&r.compareTo(BigInteger.ZERO)>0&&t.subTo(r,r),r}function Classic(t){this.m=t}function cConvert(t){return t.s<0||t.compareTo(this.m)>=0?t.mod(this.m):t}function cRevert(t){return t}function cReduce(t){t.divRemTo(this.m,null,t)}function cMulTo(t,r,n){t.multiplyTo(r,n),this.reduce(n)}function cSqrTo(t,r){t.squareTo(r),this.reduce(r)}function bnpInvDigit(){if(this.t<1)return 0;var t=this[0];if(0==(1&t))return 0;var r=3&t;return r=r*(2-(15&t)*r)&15,r=r*(2-(255&t)*r)&255,r=r*(2-((65535&t)*r&65535))&65535,r=r*(2-t*r%this.DV)%this.DV,r>0?this.DV-r:-r}function Montgomery(t){this.m=t,this.mp=t.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<<t.DB-15)-1,this.mt2=2*t.t}function montConvert(t){var r=nbi();return t.abs().dlShiftTo(this.m.t,r),r.divRemTo(this.m,null,r),t.s<0&&r.compareTo(BigInteger.ZERO)>0&&this.m.subTo(r,r),r}function montRevert(t){var r=nbi();return t.copyTo(r),this.reduce(r),r}function montReduce(t){for(;t.t<=this.mt2;)t[t.t++]=0;for(var r=0;r<this.m.t;++r){var n=32767&t[r],e=n*this.mpl+((n*this.mph+(t[r]>>15)*this.mpl&this.um)<<15)&t.DM;for(n=r+this.m.t,t[n]+=this.m.am(0,e,t,r,0,this.m.t);t[n]>=t.DV;)t[n]-=t.DV,t[++n]++}t.clamp(),t.drShiftTo(this.m.t,t),t.compareTo(this.m)>=0&&t.subTo(this.m,t)}function montSqrTo(t,r){t.squareTo(r),this.reduce(r)}function montMulTo(t,r,n){t.multiplyTo(r,n),this.reduce(n)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(t,r){if(t>4294967295||1>t)return BigInteger.ONE;var n=nbi(),e=nbi(),i=r.convert(this),o=nbits(t)-1;for(i.copyTo(n);--o>=0;)if(r.sqrTo(n,e),(t&1<<o)>0)r.mulTo(e,i,n);else{var s=n;n=e,e=s}return r.revert(n)}function bnModPowInt(t,r){var n;return n=256>t||r.isEven()?new Classic(r):new Montgomery(r),this.exp(t,n)}function Arcfour(){this.i=0,this.j=0,this.S=new Array}function ARC4init(t){var r,n,e;for(r=0;256>r;++r)this.S[r]=r;for(n=0,r=0;256>r;++r)n=n+this.S[r]+t[r%t.length]&255,e=this.S[r],this.S[r]=this.S[n],this.S[n]=e;this.i=0,this.j=0}function ARC4next(){var t;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,t=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=t,this.S[t+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}function rng_seed_int(t){rng_pool[rng_pptr++]^=255&t,rng_pool[rng_pptr++]^=t>>8&255,rng_pool[rng_pptr++]^=t>>16&255,rng_pool[rng_pptr++]^=t>>24&255,rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}function rng_get_byte(){if(null==rng_state){for(rng_seed_time(),rng_state=prng_newstate(),rng_state.init(rng_pool),rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)rng_pool[rng_pptr]=0;rng_pptr=0}return rng_state.next()}function rng_get_bytes(t){var r;for(r=0;r<t.length;++r)t[r]=rng_get_byte()}function SecureRandom(){}function parseBigInt(t,r){return new BigInteger(t,r)}function linebrk(t,r){for(var n="",e=0;e+r<t.length;)n+=t.substring(e,e+r)+"\n",e+=r;return n+t.substring(e,t.length)}function byte2Hex(t){return 16>t?"0"+t.toString(16):t.toString(16)}function pkcs1pad2(t,r){if(r<t.length+11)return alert("Message too long for RSA"),null;for(var n=new Array,e=t.length-1;e>=0&&r>0;){var i=t.charCodeAt(e--);128>i?n[--r]=i:i>127&&2048>i?(n[--r]=63&i|128,n[--r]=i>>6|192):(n[--r]=63&i|128,n[--r]=i>>6&63|128,n[--r]=i>>12|224)}n[--r]=0;for(var o=new SecureRandom,s=new Array;r>2;){for(s[0]=0;0==s[0];)o.nextBytes(s);n[--r]=s[0]}return n[--r]=2,n[--r]=0,new BigInteger(n)}function RSAKey(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function RSASetPublic(t,r){null!=t&&null!=r&&t.length>0&&r.length>0?(this.n=parseBigInt(t,16),this.e=parseInt(r,16)):alert("Invalid RSA public key")}function RSADoPublic(t){return t.modPowInt(this.e,this.n)}function RSAEncrypt(t){var r=pkcs1pad2(t,this.n.bitLength()+7>>3);if(null==r)return null;var n=this.doPublic(r);if(null==n)return null;var e=n.toString(16);return 0==(1&e.length)?e:"0"+e}var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64padchar="=",dbits,canary=0xdeadbeefcafe,j_lm=15715070==(16777215&canary);j_lm&&"Microsoft Internet Explorer"==navigator.appName?(BigInteger.prototype.am=am2,dbits=30):j_lm&&"Netscape"!=navigator.appName?(BigInteger.prototype.am=am1,dbits=26):(BigInteger.prototype.am=am3,dbits=28),BigInteger.prototype.DB=dbits,BigInteger.prototype.DM=(1<<dbits)-1,BigInteger.prototype.DV=1<<dbits;var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP),BigInteger.prototype.F1=BI_FP-dbits,BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz",BI_RC=new Array,rr,vv;for(rr="0".charCodeAt(0),vv=0;9>=vv;++vv)BI_RC[rr++]=vv;for(rr="a".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;for(rr="A".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;Classic.prototype.convert=cConvert,Classic.prototype.revert=cRevert,Classic.prototype.reduce=cReduce,Classic.prototype.mulTo=cMulTo,Classic.prototype.sqrTo=cSqrTo,Montgomery.prototype.convert=montConvert,Montgomery.prototype.revert=montRevert,Montgomery.prototype.reduce=montReduce,Montgomery.prototype.mulTo=montMulTo,Montgomery.prototype.sqrTo=montSqrTo,BigInteger.prototype.copyTo=bnpCopyTo,BigInteger.prototype.fromInt=bnpFromInt,BigInteger.prototype.fromString=bnpFromString,BigInteger.prototype.clamp=bnpClamp,BigInteger.prototype.dlShiftTo=bnpDLShiftTo,BigInteger.prototype.drShiftTo=bnpDRShiftTo,BigInteger.prototype.lShiftTo=bnpLShiftTo,BigInteger.prototype.rShiftTo=bnpRShiftTo,BigInteger.prototype.subTo=bnpSubTo,BigInteger.prototype.multiplyTo=bnpMultiplyTo,BigInteger.prototype.squareTo=bnpSquareTo,BigInteger.prototype.divRemTo=bnpDivRemTo,BigInteger.prototype.invDigit=bnpInvDigit,BigInteger.prototype.isEven=bnpIsEven,BigInteger.prototype.exp=bnpExp,BigInteger.prototype.toString=bnToString,BigInteger.prototype.negate=bnNegate,BigInteger.prototype.abs=bnAbs,BigInteger.prototype.compareTo=bnCompareTo,BigInteger.prototype.bitLength=bnBitLength,BigInteger.prototype.mod=bnMod,BigInteger.prototype.modPowInt=bnModPowInt,BigInteger.ZERO=nbv(0),BigInteger.ONE=nbv(1),Arcfour.prototype.init=ARC4init,Arcfour.prototype.next=ARC4next;var rng_psize=256,rng_state,rng_pool,rng_pptr;if(null==rng_pool){rng_pool=new Array,rng_pptr=0;var t;if(window.crypto&&window.crypto.getRandomValues){var ua=new Uint8Array(32);for(window.crypto.getRandomValues(ua),t=0;32>t;++t)rng_pool[rng_pptr++]=ua[t]}if("Netscape"==navigator.appName&&navigator.appVersion<"5"&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)rng_pool[rng_pptr++]=255&z.charCodeAt(t)}for(;rng_psize>rng_pptr;)t=Math.floor(65536*Math.random()),rng_pool[rng_pptr++]=t>>>8,rng_pool[rng_pptr++]=255&t;rng_pptr=0,rng_seed_time()}SecureRandom.prototype.nextBytes=rng_get_bytes,RSAKey.prototype.doPublic=RSADoPublic,RSAKey.prototype.setPublic=RSASetPublic,RSAKey.prototype.encrypt=RSAEncrypt,function(){"use strict";function t(){if(!r){r=!0,rng_seed_time();for(var t=document.getElementsByTagName("form"),e=t.length;e--;)for(var i=t[e],o=i.getElementsByTagName("*"),s=o.length;s--;){var h=o[s];if("input"===h.nodeName.toLowerCase()){var a=h.getAttribute("data-rsa-encryption");(a||""===a&&h.outerHTML.match(/ data-rsa-encryption=""/))&&(i.rsaEncryption||(i.rsaEncryption=new n(i),i.addEventListener?i.addEventListener("submit",i.rsaEncryption.handleFormSubmitRequest,!1):i.attachEvent&&i.attachEvent("onsubmit",i.rsaEncryption.handleFormSubmitRequest)),i.rsaEncryption.fields.push(h))}}}}var r=!1,n=function(t){this.form=t,this.fields=[],this.xhr=null,this.fetchedRsaKey=!1,this.handleFormSubmitRequest=function(t){var r=this.rsaEncryption||t.srcElement.rsaEncryption;r&&r.fields.length&&!r.fetchedRsaKey&&(r.fetchedRsaKey=!0,r.ajaxCall(TYPO3RsaEncryptionPublicKeyUrl,r,function(t){r.handlePublicKeyResponse(t,r)}),t.preventDefault?t.preventDefault():window.event&&(window.event.returnValue=!1))},this.ajaxCall=function(t,r,n){if(r.xhr&&r.xhr.abort(),"undefined"!=typeof XMLHttpRequest)r.xhr=new XMLHttpRequest;else for(var e=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],i=0,o=e.length;o>i;i++)try{r.xhr=new ActiveXObject(e[i]);break}catch(s){}r.xhr.onreadystatechange=function(){4===r.xhr.readyState&&r.xhr.status>0&&n(r.xhr)},r.xhr.open("GET",t,!0),r.xhr.send("")},this.handlePublicKeyResponse=function(t,r){var n=t.responseText.split(":");if(!n[0]||!n[1])return alert("No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings."),!1;var e=new RSAKey;e.setPublic(n[0],n[1]);for(var i=r.fields.length;i--;){var o=r.fields[i],s=e.encrypt(o.value);o.value="rsa:"+hex2b64(s)}var h=document.createElement("form");if(h.submit.call)h.submit.call(r.form);else for(var a=r.form.getElementsByTagName("*"),p=a.length;p--;){var u=a[p];"input"===u.nodeName.toLowerCase()&&"submit"===u.type&&u.click()}}};"complete"===document.readyState?setTimeout(t,1):document.addEventListener?(document.addEventListener("DOMContentLoaded",t,!1),window.addEventListener("load",t,!1)):(document.attachEvent("onreadystatechange",function(){"complete"===document.readyState&&t()}),window.attachEvent("onload",t))}(); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js new file mode 100644 index 000000000000..96244d0412cc --- /dev/null +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js @@ -0,0 +1,884 @@ +// +// base64.js +// +var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var b64padchar="="; + +function hex2b64(h) { + var i; + var c; + var ret = ""; + for(i = 0; i+3 <= h.length; i+=3) { + c = parseInt(h.substring(i,i+3),16); + ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); + } + if(i+1 == h.length) { + c = parseInt(h.substring(i,i+1),16); + ret += b64map.charAt(c << 2); + } + else if(i+2 == h.length) { + c = parseInt(h.substring(i,i+2),16); + ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); + } + while((ret.length & 3) > 0) ret += b64padchar; + return ret; +} + +// convert a base64 string to hex +function b64tohex(s) { + var ret = ""; + var i; + var k = 0; // b64 state, 0-3 + var slop; + for(i = 0; i < s.length; ++i) { + if(s.charAt(i) == b64padchar) break; + v = b64map.indexOf(s.charAt(i)); + if(v < 0) continue; + if(k == 0) { + ret += int2char(v >> 2); + slop = v & 3; + k = 1; + } + else if(k == 1) { + ret += int2char((slop << 2) | (v >> 4)); + slop = v & 0xf; + k = 2; + } + else if(k == 2) { + ret += int2char(slop); + ret += int2char(v >> 2); + slop = v & 3; + k = 3; + } + else { + ret += int2char((slop << 2) | (v >> 4)); + ret += int2char(v & 0xf); + k = 0; + } + } + if(k == 1) + ret += int2char(slop << 2); + return ret; +} + +// convert a base64 string to a byte/number array +function b64toBA(s) { + //piggyback on b64tohex for now, optimize later + var h = b64tohex(s); + var i; + var a = new Array(); + for(i = 0; 2*i < h.length; ++i) { + a[i] = parseInt(h.substring(2*i,2*i+2),16); + } + return a; +} + +// +// jsbn.js +// + +// Copyright (c) 2005 Tom Wu +// All Rights Reserved. +// See "LICENSE" for details. + +// Basic JavaScript BN library - subset useful for RSA encryption. + +// Bits per digit +var dbits; + +// JavaScript engine analysis +var canary = 0xdeadbeefcafe; +var j_lm = ((canary&0xffffff)==0xefcafe); + +// (public) Constructor +function BigInteger(a,b,c) { + if(a != null) + if("number" == typeof a) this.fromNumber(a,b,c); + else if(b == null && "string" != typeof a) this.fromString(a,256); + else this.fromString(a,b); +} + +// return new, unset BigInteger +function nbi() { return new BigInteger(null); } + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. + +// am1: use a single mult and divide to get the high bits, +// max digit bits should be 26 because +// max internal value = 2*dvalue^2-2*dvalue (< 2^53) +function am1(i,x,w,j,c,n) { + while(--n >= 0) { + var v = x*this[i++]+w[j]+c; + c = Math.floor(v/0x4000000); + w[j++] = v&0x3ffffff; + } + return c; +} +// am2 avoids a big mult-and-extract completely. +// Max digit bits should be <= 30 because we do bitwise ops +// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) +function am2(i,x,w,j,c,n) { + var xl = x&0x7fff, xh = x>>15; + while(--n >= 0) { + var l = this[i]&0x7fff; + var h = this[i++]>>15; + var m = xh*l+h*xl; + l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); + c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); + w[j++] = l&0x3fffffff; + } + return c; +} +// Alternately, set max digit bits to 28 since some +// browsers slow down when dealing with 32-bit numbers. +function am3(i,x,w,j,c,n) { + var xl = x&0x3fff, xh = x>>14; + while(--n >= 0) { + var l = this[i]&0x3fff; + var h = this[i++]>>14; + var m = xh*l+h*xl; + l = xl*l+((m&0x3fff)<<14)+w[j]+c; + c = (l>>28)+(m>>14)+xh*h; + w[j++] = l&0xfffffff; + } + return c; +} +if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; +} +else if(j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; +} +else { // Mozilla/Netscape seems to prefer am3 + BigInteger.prototype.am = am3; + dbits = 28; +} + +BigInteger.prototype.DB = dbits; +BigInteger.prototype.DM = ((1<<dbits)-1); +BigInteger.prototype.DV = (1<<dbits); + +var BI_FP = 52; +BigInteger.prototype.FV = Math.pow(2,BI_FP); +BigInteger.prototype.F1 = BI_FP-dbits; +BigInteger.prototype.F2 = 2*dbits-BI_FP; + +// Digit conversions +var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; +var BI_RC = new Array(); +var rr,vv; +rr = "0".charCodeAt(0); +for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; +rr = "a".charCodeAt(0); +for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; +rr = "A".charCodeAt(0); +for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; + +function int2char(n) { return BI_RM.charAt(n); } +function intAt(s,i) { + var c = BI_RC[s.charCodeAt(i)]; + return (c==null)?-1:c; +} + +// (protected) copy this to r +function bnpCopyTo(r) { + for(var i = this.t-1; i >= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; +} + +// (protected) set from integer value x, -DV <= x < DV +function bnpFromInt(x) { + this.t = 1; + this.s = (x<0)?-1:0; + if(x > 0) this[0] = x; + else if(x < -1) this[0] = x+this.DV; + else this.t = 0; +} + +// return bigint initialized to value +function nbv(i) { var r = nbi(); r.fromInt(i); return r; } + +// (protected) set from string and radix +function bnpFromString(s,b) { + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 256) k = 8; // byte array + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else { this.fromRadix(s,b); return; } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while(--i >= 0) { + var x = (k==8)?s[i]&0xff:intAt(s,i); + if(x < 0) { + if(s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if(sh == 0) + this[this.t++] = x; + else if(sh+k > this.DB) { + this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh; + this[this.t++] = (x>>(this.DB-sh)); + } + else + this[this.t-1] |= x<<sh; + sh += k; + if(sh >= this.DB) sh -= this.DB; + } + if(k == 8 && (s[0]&0x80) != 0) { + this.s = -1; + if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh; + } + this.clamp(); + if(mi) BigInteger.ZERO.subTo(this,this); +} + +// (protected) clamp off excess high words +function bnpClamp() { + var c = this.s&this.DM; + while(this.t > 0 && this[this.t-1] == c) --this.t; +} + +// (public) return string representation in given radix +function bnToString(b) { + if(this.s < 0) return "-"+this.negate().toString(b); + var k; + if(b == 16) k = 4; + else if(b == 8) k = 3; + else if(b == 2) k = 1; + else if(b == 32) k = 5; + else if(b == 4) k = 2; + else return this.toRadix(b); + var km = (1<<k)-1, d, m = false, r = "", i = this.t; + var p = this.DB-(i*this.DB)%k; + if(i-- > 0) { + if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } + while(i >= 0) { + if(p < k) { + d = (this[i]&((1<<p)-1))<<(k-p); + d |= this[--i]>>(p+=this.DB-k); + } + else { + d = (this[i]>>(p-=k))&km; + if(p <= 0) { p += this.DB; --i; } + } + if(d > 0) m = true; + if(m) r += int2char(d); + } + } + return m?r:"0"; +} + +// (public) -this +function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } + +// (public) |this| +function bnAbs() { return (this.s<0)?this.negate():this; } + +// (public) return + if this > a, - if this < a, 0 if equal +function bnCompareTo(a) { + var r = this.s-a.s; + if(r != 0) return r; + var i = this.t; + r = i-a.t; + if(r != 0) return (this.s<0)?-r:r; + while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; + return 0; +} + +// returns bit length of the integer x +function nbits(x) { + var r = 1, t; + if((t=x>>>16) != 0) { x = t; r += 16; } + if((t=x>>8) != 0) { x = t; r += 8; } + if((t=x>>4) != 0) { x = t; r += 4; } + if((t=x>>2) != 0) { x = t; r += 2; } + if((t=x>>1) != 0) { x = t; r += 1; } + return r; +} + +// (public) return the number of bits in "this" +function bnBitLength() { + if(this.t <= 0) return 0; + return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); +} + +// (protected) r = this << n*DB +function bnpDLShiftTo(n,r) { + var i; + for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; + for(i = n-1; i >= 0; --i) r[i] = 0; + r.t = this.t+n; + r.s = this.s; +} + +// (protected) r = this >> n*DB +function bnpDRShiftTo(n,r) { + for(var i = n; i < this.t; ++i) r[i-n] = this[i]; + r.t = Math.max(this.t-n,0); + r.s = this.s; +} + +// (protected) r = this << n +function bnpLShiftTo(n,r) { + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<<cbs)-1; + var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i; + for(i = this.t-1; i >= 0; --i) { + r[i+ds+1] = (this[i]>>cbs)|c; + c = (this[i]&bm)<<bs; + } + for(i = ds-1; i >= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t+ds+1; + r.s = this.s; + r.clamp(); +} + +// (protected) r = this >> n +function bnpRShiftTo(n,r) { + r.s = this.s; + var ds = Math.floor(n/this.DB); + if(ds >= this.t) { r.t = 0; return; } + var bs = n%this.DB; + var cbs = this.DB-bs; + var bm = (1<<bs)-1; + r[0] = this[ds]>>bs; + for(var i = ds+1; i < this.t; ++i) { + r[i-ds-1] |= (this[i]&bm)<<cbs; + r[i-ds] = this[i]>>bs; + } + if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs; + r.t = this.t-ds; + r.clamp(); +} + +// (protected) r = this - a +function bnpSubTo(a,r) { + var i = 0, c = 0, m = Math.min(a.t,this.t); + while(i < m) { + c += this[i]-a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + if(a.t < this.t) { + c -= a.s; + while(i < this.t) { + c += this[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while(i < a.t) { + c -= a[i]; + r[i++] = c&this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c<0)?-1:0; + if(c < -1) r[i++] = this.DV+c; + else if(c > 0) r[i++] = c; + r.t = i; + r.clamp(); +} + +// (protected) r = this * a, r != this,a (HAC 14.12) +// "this" should be the larger one if appropriate. +function bnpMultiplyTo(a,r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i+y.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); + r.s = 0; + r.clamp(); + if(this.s != a.s) BigInteger.ZERO.subTo(r,r); +} + +// (protected) r = this^2, r != this (HAC 14.16) +function bnpSquareTo(r) { + var x = this.abs(); + var i = r.t = 2*x.t; + while(--i >= 0) r[i] = 0; + for(i = 0; i < x.t-1; ++i) { + var c = x.am(i,x[i],r,2*i,0,1); + if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { + r[i+x.t] -= x.DV; + r[i+x.t+1] = 1; + } + } + if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); + r.s = 0; + r.clamp(); +} + +// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) +// r != q, this != m. q or r may be null. +function bnpDivRemTo(m,q,r) { + var pm = m.abs(); + if(pm.t <= 0) return; + var pt = this.abs(); + if(pt.t < pm.t) { + if(q != null) q.fromInt(0); + if(r != null) this.copyTo(r); + return; + } + if(r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus + if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } + else { pm.copyTo(y); pt.copyTo(r); } + var ys = y.t; + var y0 = y[ys-1]; + if(y0 == 0) return; + var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0); + var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2; + var i = r.t, j = i-ys, t = (q==null)?nbi():q; + y.dlShiftTo(j,t); + if(r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t,r); + } + BigInteger.ONE.dlShiftTo(ys,t); + t.subTo(y,y); // "negative" y so we can replace sub with am later + while(y.t < ys) y[y.t++] = 0; + while(--j >= 0) { + // Estimate quotient digit + var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); + if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out + y.dlShiftTo(j,t); + r.subTo(t,r); + while(r[i] < --qd) r.subTo(t,r); + } + } + if(q != null) { + r.drShiftTo(ys,q); + if(ts != ms) BigInteger.ZERO.subTo(q,q); + } + r.t = ys; + r.clamp(); + if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder + if(ts < 0) BigInteger.ZERO.subTo(r,r); +} + +// (public) this mod a +function bnMod(a) { + var r = nbi(); + this.abs().divRemTo(a,null,r); + if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); + return r; +} + +// Modular reduction using "classic" algorithm +function Classic(m) { this.m = m; } +function cConvert(x) { + if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; +} +function cRevert(x) { return x; } +function cReduce(x) { x.divRemTo(this.m,null,x); } +function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } +function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +Classic.prototype.convert = cConvert; +Classic.prototype.revert = cRevert; +Classic.prototype.reduce = cReduce; +Classic.prototype.mulTo = cMulTo; +Classic.prototype.sqrTo = cSqrTo; + +// (protected) return "-1/this % 2^DB"; useful for Mont. reduction +// justification: +// xy == 1 (mod m) +// xy = 1+km +// xy(2-xy) = (1+km)(1-km) +// x[y(2-xy)] = 1-k^2m^2 +// x[y(2-xy)] == 1 (mod m^2) +// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 +// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. +// JS multiply "overflows" differently from C/C++, so care is needed here. +function bnpInvDigit() { + if(this.t < 1) return 0; + var x = this[0]; + if((x&1) == 0) return 0; + var y = x&3; // y == 1/x mod 2^2 + y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 + y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 + y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y>0)?this.DV-y:-y; +} + +// Montgomery reduction +function Montgomery(m) { + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp&0x7fff; + this.mph = this.mp>>15; + this.um = (1<<(m.DB-15))-1; + this.mt2 = 2*m.t; +} + +// xR mod m +function montConvert(x) { + var r = nbi(); + x.abs().dlShiftTo(this.m.t,r); + r.divRemTo(this.m,null,r); + if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); + return r; +} + +// x/R mod m +function montRevert(x) { + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; +} + +// x = x/R mod m (HAC 14.32) +function montReduce(x) { + while(x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for(var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i]&0x7fff; + var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; + // use am to combine the multiply-shift-add into one call + j = i+this.m.t; + x[j] += this.m.am(0,u0,x,i,0,this.m.t); + // propagate carry + while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } + } + x.clamp(); + x.drShiftTo(this.m.t,x); + if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); +} + +// r = "x^2/R mod m"; x != r +function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } + +// r = "xy/R mod m"; x,y != r +function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } + +Montgomery.prototype.convert = montConvert; +Montgomery.prototype.revert = montRevert; +Montgomery.prototype.reduce = montReduce; +Montgomery.prototype.mulTo = montMulTo; +Montgomery.prototype.sqrTo = montSqrTo; + +// (protected) true iff this is even +function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } + +// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) +function bnpExp(e,z) { + if(e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; + g.copyTo(r); + while(--i >= 0) { + z.sqrTo(r,r2); + if((e&(1<<i)) > 0) z.mulTo(r2,g,r); + else { var t = r; r = r2; r2 = t; } + } + return z.revert(r); +} + +// (public) this^e % m, 0 <= e < 2^32 +function bnModPowInt(e,m) { + var z; + if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e,z); +} + +// protected +BigInteger.prototype.copyTo = bnpCopyTo; +BigInteger.prototype.fromInt = bnpFromInt; +BigInteger.prototype.fromString = bnpFromString; +BigInteger.prototype.clamp = bnpClamp; +BigInteger.prototype.dlShiftTo = bnpDLShiftTo; +BigInteger.prototype.drShiftTo = bnpDRShiftTo; +BigInteger.prototype.lShiftTo = bnpLShiftTo; +BigInteger.prototype.rShiftTo = bnpRShiftTo; +BigInteger.prototype.subTo = bnpSubTo; +BigInteger.prototype.multiplyTo = bnpMultiplyTo; +BigInteger.prototype.squareTo = bnpSquareTo; +BigInteger.prototype.divRemTo = bnpDivRemTo; +BigInteger.prototype.invDigit = bnpInvDigit; +BigInteger.prototype.isEven = bnpIsEven; +BigInteger.prototype.exp = bnpExp; + +// public +BigInteger.prototype.toString = bnToString; +BigInteger.prototype.negate = bnNegate; +BigInteger.prototype.abs = bnAbs; +BigInteger.prototype.compareTo = bnCompareTo; +BigInteger.prototype.bitLength = bnBitLength; +BigInteger.prototype.mod = bnMod; +BigInteger.prototype.modPowInt = bnModPowInt; + +// "constants" +BigInteger.ZERO = nbv(0); +BigInteger.ONE = nbv(1); + +// +// prng4.js - uses Arcfour as a PRNG +// + +function Arcfour() { + this.i = 0; + this.j = 0; + this.S = new Array(); +} + +// Initialize arcfour context from key, an array of ints, each from [0..255] +function ARC4init(key) { + var i, j, t; + for(i = 0; i < 256; ++i) + this.S[i] = i; + j = 0; + for(i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; +} + +function ARC4next() { + var t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; +} + +Arcfour.prototype.init = ARC4init; +Arcfour.prototype.next = ARC4next; + +// Plug in your RNG constructor here +function prng_newstate() { + return new Arcfour(); +} + +// Pool size must be a multiple of 4 and greater than 32. +// An array of bytes the size of the pool will be passed to init() +var rng_psize = 256; + + +// +// rng.js +// + +// Random number generator - requires a PRNG backend, e.g. prng4.js + +// For best results, put code like +// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'> +// in your main HTML document. + +var rng_state; +var rng_pool; +var rng_pptr; + +// Mix in a 32-bit integer into the pool +function rng_seed_int(x) { + rng_pool[rng_pptr++] ^= x & 255; + rng_pool[rng_pptr++] ^= (x >> 8) & 255; + rng_pool[rng_pptr++] ^= (x >> 16) & 255; + rng_pool[rng_pptr++] ^= (x >> 24) & 255; + if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; +} + +// Mix in the current time (w/milliseconds) into the pool +function rng_seed_time() { + rng_seed_int(new Date().getTime()); +} + +// Initialize the pool with junk if needed. +if(rng_pool == null) { + rng_pool = new Array(); + rng_pptr = 0; + var t; + if(window.crypto && window.crypto.getRandomValues) { + // Use webcrypto if available + var ua = new Uint8Array(32); + window.crypto.getRandomValues(ua); + for(t = 0; t < 32; ++t) + rng_pool[rng_pptr++] = ua[t]; + } + if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { + // Extract entropy (256 bits) from NS4 RNG if available + var z = window.crypto.random(32); + for(t = 0; t < z.length; ++t) + rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; + } + while(rng_pptr < rng_psize) { // extract some randomness from Math.random() + t = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = t >>> 8; + rng_pool[rng_pptr++] = t & 255; + } + rng_pptr = 0; + rng_seed_time(); + //rng_seed_int(window.screenX); + //rng_seed_int(window.screenY); +} + +function rng_get_byte() { + if(rng_state == null) { + rng_seed_time(); + rng_state = prng_newstate(); + rng_state.init(rng_pool); + for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) + rng_pool[rng_pptr] = 0; + rng_pptr = 0; + //rng_pool = null; + } + // TODO: allow reseeding after first request + return rng_state.next(); +} + +function rng_get_bytes(ba) { + var i; + for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); +} + +function SecureRandom() {} + +SecureRandom.prototype.nextBytes = rng_get_bytes; + + +// +// rsa.js +// +// Depends on jsbn.js and rng.js + +// Version 1.1: support utf-8 encoding in pkcs1pad2 + +// convert a (hex) string to a bignum object +function parseBigInt(str,r) { + return new BigInteger(str,r); +} + +function linebrk(s,n) { + var ret = ""; + var i = 0; + while(i + n < s.length) { + ret += s.substring(i,i+n) + "\n"; + i += n; + } + return ret + s.substring(i,s.length); +} + +function byte2Hex(b) { + if(b < 0x10) + return "0" + b.toString(16); + else + return b.toString(16); +} + +// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint +function pkcs1pad2(s,n) { + if(n < s.length + 11) { // TODO: fix for utf-8 + alert("Message too long for RSA"); + return null; + } + var ba = new Array(); + var i = s.length - 1; + while(i >= 0 && n > 0) { + var c = s.charCodeAt(i--); + if(c < 128) { // encode using utf-8 + ba[--n] = c; + } + else if((c > 127) && (c < 2048)) { + ba[--n] = (c & 63) | 128; + ba[--n] = (c >> 6) | 192; + } + else { + ba[--n] = (c & 63) | 128; + ba[--n] = ((c >> 6) & 63) | 128; + ba[--n] = (c >> 12) | 224; + } + } + ba[--n] = 0; + var rng = new SecureRandom(); + var x = new Array(); + while(n > 2) { // random non-zero pad + x[0] = 0; + while(x[0] == 0) rng.nextBytes(x); + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); +} + +// "empty" RSA key constructor +function RSAKey() { + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; +} + +// Set the public key fields N and e from hex strings +function RSASetPublic(N,E) { + if(N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N,16); + this.e = parseInt(E,16); + } + else + alert("Invalid RSA public key"); +} + +// Perform raw public operation on "x": return x^e (mod n) +function RSADoPublic(x) { + return x.modPowInt(this.e, this.n); +} + +// Return the PKCS#1 RSA encryption of "text" as an even-length hex string +function RSAEncrypt(text) { + var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); + if(m == null) return null; + var c = this.doPublic(m); + if(c == null) return null; + var h = c.toString(16); + if((h.length & 1) == 0) return h; else return "0" + h; +} + +// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string +//function RSAEncryptB64(text) { +// var h = this.encrypt(text); +// if(h) return hex2b64(h); else return null; +//} + +// protected +RSAKey.prototype.doPublic = RSADoPublic; + +// public +RSAKey.prototype.setPublic = RSASetPublic; +RSAKey.prototype.encrypt = RSAEncrypt; +//RSAKey.prototype.encrypt_b64 = RSAEncryptB64; diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/LICENSE b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/LICENSE deleted file mode 100644 index 24502a9cf748..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/LICENSE +++ /dev/null @@ -1,40 +0,0 @@ -Licensing ---------- - -This software is covered under the following copyright: - -/* - * Copyright (c) 2003-2005 Tom Wu - * All Rights Reserved. - * - * 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" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * - * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF - * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * In addition, the following condition applies: - * - * All redistributions must retain an intact copy of this copyright notice - * and disclaimer. - */ - -Address all questions regarding this license to: - - Tom Wu - tjw@cs.Stanford.EDU diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/base64.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/base64.js deleted file mode 100644 index f5b168c4c306..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/base64.js +++ /dev/null @@ -1,71 +0,0 @@ -var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -var b64pad="="; - -function hex2b64(h) { - var i; - var c; - var ret = ""; - for(i = 0; i+3 <= h.length; i+=3) { - c = parseInt(h.substring(i,i+3),16); - ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); - } - if(i+1 == h.length) { - c = parseInt(h.substring(i,i+1),16); - ret += b64map.charAt(c << 2); - } - else if(i+2 == h.length) { - c = parseInt(h.substring(i,i+2),16); - ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); - } - while((ret.length & 3) > 0) ret += b64pad; - return ret; -} - -// convert a base64 string to hex -function b64tohex(s) { - var ret = "" - var i; - var k = 0; // b64 state, 0-3 - var slop; - for(i = 0; i < s.length; ++i) { - if(s.charAt(i) == b64pad) break; - v = b64map.indexOf(s.charAt(i)); - if(v < 0) continue; - if(k == 0) { - ret += int2char(v >> 2); - slop = v & 3; - k = 1; - } - else if(k == 1) { - ret += int2char((slop << 2) | (v >> 4)); - slop = v & 0xf; - k = 2; - } - else if(k == 2) { - ret += int2char(slop); - ret += int2char(v >> 2); - slop = v & 3; - k = 3; - } - else { - ret += int2char((slop << 2) | (v >> 4)); - ret += int2char(v & 0xf); - k = 0; - } - } - if(k == 1) - ret += int2char(slop << 2); - return ret; -} - -// convert a base64 string to a byte/number array -function b64toBA(s) { - //piggyback on b64tohex for now, optimize later - var h = b64tohex(s); - var i; - var a = new Array(); - for(i = 0; 2*i < h.length; ++i) { - a[i] = parseInt(h.substring(2*i,2*i+2),16); - } - return a; -} diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn.js deleted file mode 100644 index 928cc4f7bd56..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn.js +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) 2005 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Basic JavaScript BN library - subset useful for RSA encryption. - -// Bits per digit -var dbits; - -// JavaScript engine analysis -var canary = 0xdeadbeefcafe; -var j_lm = ((canary&0xffffff)==0xefcafe); - -// (public) Constructor -function BigInteger(a,b,c) { - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); -} - -// return new, unset BigInteger -function nbi() { return new BigInteger(null); } - -// am: Compute w_j += (x*this_i), propagate carries, -// c is initial carry, returns final carry. -// c < 3*dvalue, x < 2*dvalue, this_i < dvalue -// We need to select the fastest one that works in this environment. - -// am1: use a single mult and divide to get the high bits, -// max digit bits should be 26 because -// max internal value = 2*dvalue^2-2*dvalue (< 2^53) -function am1(i,x,w,j,c,n) { - while(--n >= 0) { - var v = x*this[i++]+w[j]+c; - c = Math.floor(v/0x4000000); - w[j++] = v&0x3ffffff; - } - return c; -} -// am2 avoids a big mult-and-extract completely. -// Max digit bits should be <= 30 because we do bitwise ops -// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) -function am2(i,x,w,j,c,n) { - var xl = x&0x7fff, xh = x>>15; - while(--n >= 0) { - var l = this[i]&0x7fff; - var h = this[i++]>>15; - var m = xh*l+h*xl; - l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); - c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); - w[j++] = l&0x3fffffff; - } - return c; -} -// Alternately, set max digit bits to 28 since some -// browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this[i]&0x3fff; - var h = this[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w[j++] = l&0xfffffff; - } - return c; -} -if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { - BigInteger.prototype.am = am2; - dbits = 30; -} -else if(j_lm && (navigator.appName != "Netscape")) { - BigInteger.prototype.am = am1; - dbits = 26; -} -else { // Mozilla/Netscape seems to prefer am3 - BigInteger.prototype.am = am3; - dbits = 28; -} - -BigInteger.prototype.DB = dbits; -BigInteger.prototype.DM = ((1<<dbits)-1); -BigInteger.prototype.DV = (1<<dbits); - -var BI_FP = 52; -BigInteger.prototype.FV = Math.pow(2,BI_FP); -BigInteger.prototype.F1 = BI_FP-dbits; -BigInteger.prototype.F2 = 2*dbits-BI_FP; - -// Digit conversions -var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; -var BI_RC = new Array(); -var rr,vv; -rr = "0".charCodeAt(0); -for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; -rr = "a".charCodeAt(0); -for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; -rr = "A".charCodeAt(0); -for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; - -function int2char(n) { return BI_RM.charAt(n); } -function intAt(s,i) { - var c = BI_RC[s.charCodeAt(i)]; - return (c==null)?-1:c; -} - -// (protected) copy this to r -function bnpCopyTo(r) { - for(var i = this.t-1; i >= 0; --i) r[i] = this[i]; - r.t = this.t; - r.s = this.s; -} - -// (protected) set from integer value x, -DV <= x < DV -function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this[0] = x; - else if(x < -1) this[0] = x+DV; - else this.t = 0; -} - -// return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } - -// (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this[this.t++] = x; - else if(sh+k > this.DB) { - this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh; - this[this.t++] = (x>>(this.DB-sh)); - } - else - this[this.t-1] |= x<<sh; - sh += k; - if(sh >= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh; - } - this.clamp(); - if(mi) BigInteger.ZERO.subTo(this,this); -} - -// (protected) clamp off excess high words -function bnpClamp() { - var c = this.s&this.DM; - while(this.t > 0 && this[this.t-1] == c) --this.t; -} - -// (public) return string representation in given radix -function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1<<k)-1, d, m = false, r = "", i = this.t; - var p = this.DB-(i*this.DB)%k; - if(i-- > 0) { - if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this[i]&((1<<p)-1))<<(k-p); - d |= this[--i]>>(p+=this.DB-k); - } - else { - d = (this[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; -} - -// (public) -this -function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } - -// (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } - -// (public) return + if this > a, - if this < a, 0 if equal -function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return r; - while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; - return 0; -} - -// returns bit length of the integer x -function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; -} - -// (public) return the number of bits in "this" -function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); -} - -// (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; - for(i = n-1; i >= 0; --i) r[i] = 0; - r.t = this.t+n; - r.s = this.s; -} - -// (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r[i-n] = this[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; -} - -// (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<<cbs)-1; - var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i; - for(i = this.t-1; i >= 0; --i) { - r[i+ds+1] = (this[i]>>cbs)|c; - c = (this[i]&bm)<<bs; - } - for(i = ds-1; i >= 0; --i) r[i] = 0; - r[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); -} - -// (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<<bs)-1; - r[0] = this[ds]>>bs; - for(var i = ds+1; i < this.t; ++i) { - r[i-ds-1] |= (this[i]&bm)<<cbs; - r[i-ds] = this[i]>>bs; - } - if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs; - r.t = this.t-ds; - r.clamp(); -} - -// (protected) r = this - a -function bnpSubTo(a,r) { - var i = 0, c = 0, m = Math.min(a.t,this.t); - while(i < m) { - c += this[i]-a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c -= a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r[i++] = this.DV+c; - else if(c > 0) r[i++] = c; - r.t = i; - r.clamp(); -} - -// (protected) r = this * a, r != this,a (HAC 14.12) -// "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger.ZERO.subTo(r,r); -} - -// (protected) r = this^2, r != this (HAC 14.16) -function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x[i],r,2*i,0,1); - if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r[i+x.t] -= x.DV; - r[i+x.t+1] = 1; - } - } - if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); - r.s = 0; - r.clamp(); -} - -// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) -// r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } - else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2; - var i = r.t, j = i-ys, t = (q==null)?nbi():q; - y.dlShiftTo(j,t); - if(r.compareTo(t) >= 0) { - r[r.t++] = 1; - r.subTo(t,r); - } - BigInteger.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); - if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger.ZERO.subTo(r,r); -} - -// (public) this mod a -function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); - return r; -} - -// Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } -function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; -} -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -Classic.prototype.convert = cConvert; -Classic.prototype.revert = cRevert; -Classic.prototype.reduce = cReduce; -Classic.prototype.mulTo = cMulTo; -Classic.prototype.sqrTo = cSqrTo; - -// (protected) return "-1/this % 2^DB"; useful for Mont. reduction -// justification: -// xy == 1 (mod m) -// xy = 1+km -// xy(2-xy) = (1+km)(1-km) -// x[y(2-xy)] = 1-k^2m^2 -// x[y(2-xy)] == 1 (mod m^2) -// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 -// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. -// JS multiply "overflows" differently from C/C++, so care is needed here. -function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; -} - -// Montgomery reduction -function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; -} - -// xR mod m -function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); - return r; -} - -// x/R mod m -function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; -} - -// x = x/R mod m (HAC 14.32) -function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x[i]*mp mod DV - var j = x[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Montgomery.prototype.convert = montConvert; -Montgomery.prototype.revert = montRevert; -Montgomery.prototype.reduce = montReduce; -Montgomery.prototype.mulTo = montMulTo; -Montgomery.prototype.sqrTo = montSqrTo; - -// (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } - -// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1<<i)) > 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); -} - -// (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); -} - -// protected -BigInteger.prototype.copyTo = bnpCopyTo; -BigInteger.prototype.fromInt = bnpFromInt; -BigInteger.prototype.fromString = bnpFromString; -BigInteger.prototype.clamp = bnpClamp; -BigInteger.prototype.dlShiftTo = bnpDLShiftTo; -BigInteger.prototype.drShiftTo = bnpDRShiftTo; -BigInteger.prototype.lShiftTo = bnpLShiftTo; -BigInteger.prototype.rShiftTo = bnpRShiftTo; -BigInteger.prototype.subTo = bnpSubTo; -BigInteger.prototype.multiplyTo = bnpMultiplyTo; -BigInteger.prototype.squareTo = bnpSquareTo; -BigInteger.prototype.divRemTo = bnpDivRemTo; -BigInteger.prototype.invDigit = bnpInvDigit; -BigInteger.prototype.isEven = bnpIsEven; -BigInteger.prototype.exp = bnpExp; - -// public -BigInteger.prototype.toString = bnToString; -BigInteger.prototype.negate = bnNegate; -BigInteger.prototype.abs = bnAbs; -BigInteger.prototype.compareTo = bnCompareTo; -BigInteger.prototype.bitLength = bnBitLength; -BigInteger.prototype.mod = bnMod; -BigInteger.prototype.modPowInt = bnModPowInt; - -// "constants" -BigInteger.ZERO = nbv(0); -BigInteger.ONE = nbv(1); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn2.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn2.js deleted file mode 100644 index e53e00b49808..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/jsbn2.js +++ /dev/null @@ -1,648 +0,0 @@ -// Copyright (c) 2005-2009 Tom Wu -// All Rights Reserved. -// See "LICENSE" for details. - -// Extended JavaScript BN functions, required for RSA private ops. - -// Version 1.1: new BigInteger("0", 10) returns "proper" zero - -// (public) -function bnClone() { var r = nbi(); this.copyTo(r); return r; } - -// (public) return value as integer -function bnIntValue() { - if(this.s < 0) { - if(this.t == 1) return this[0]-this.DV; - else if(this.t == 0) return -1; - } - else if(this.t == 1) return this[0]; - else if(this.t == 0) return 0; - // assumes 16 < DB < 32 - return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0]; -} - -// (public) return value as byte -function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; } - -// (public) return value as short (assumes DB>=16) -function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; } - -// (protected) return x s.t. r^x < DV -function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); } - -// (public) 0 if this == 0, 1 if this > 0 -function bnSigNum() { - if(this.s < 0) return -1; - else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0; - else return 1; -} - -// (protected) convert to radix string -function bnpToRadix(b) { - if(b == null) b = 10; - if(this.signum() == 0 || b < 2 || b > 36) return "0"; - var cs = this.chunkSize(b); - var a = Math.pow(b,cs); - var d = nbv(a), y = nbi(), z = nbi(), r = ""; - this.divRemTo(d,y,z); - while(y.signum() > 0) { - r = (a+z.intValue()).toString(b).substr(1) + r; - y.divRemTo(d,y,z); - } - return z.intValue().toString(b) + r; -} - -// (protected) convert from radix string -function bnpFromRadix(s,b) { - this.fromInt(0); - if(b == null) b = 10; - var cs = this.chunkSize(b); - var d = Math.pow(b,cs), mi = false, j = 0, w = 0; - for(var i = 0; i < s.length; ++i) { - var x = intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-" && this.signum() == 0) mi = true; - continue; - } - w = b*w+x; - if(++j >= cs) { - this.dMultiply(d); - this.dAddOffset(w,0); - j = 0; - w = 0; - } - } - if(j > 0) { - this.dMultiply(Math.pow(b,j)); - this.dAddOffset(w,0); - } - if(mi) BigInteger.ZERO.subTo(this,this); -} - -// (protected) alternate constructor -function bnpFromNumber(a,b,c) { - if("number" == typeof b) { - // new BigInteger(int,int,RNG) - if(a < 2) this.fromInt(1); - else { - this.fromNumber(a,c); - if(!this.testBit(a-1)) // force MSB set - this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this); - if(this.isEven()) this.dAddOffset(1,0); // force odd - while(!this.isProbablePrime(b)) { - this.dAddOffset(2,0); - if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this); - } - } - } - else { - // new BigInteger(int,RNG) - var x = new Array(), t = a&7; - x.length = (a>>3)+1; - b.nextBytes(x); - if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0; - this.fromString(x,256); - } -} - -// (public) convert to bigendian byte array -function bnToByteArray() { - var i = this.t, r = new Array(); - r[0] = this.s; - var p = this.DB-(i*this.DB)%8, d, k = 0; - if(i-- > 0) { - if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p) - r[k++] = d|(this.s<<(this.DB-p)); - while(i >= 0) { - if(p < 8) { - d = (this[i]&((1<<p)-1))<<(8-p); - d |= this[--i]>>(p+=this.DB-8); - } - else { - d = (this[i]>>(p-=8))&0xff; - if(p <= 0) { p += this.DB; --i; } - } - if((d&0x80) != 0) d |= -256; - if(k == 0 && (this.s&0x80) != (d&0x80)) ++k; - if(k > 0 || d != this.s) r[k++] = d; - } - } - return r; -} - -function bnEquals(a) { return(this.compareTo(a)==0); } -function bnMin(a) { return(this.compareTo(a)<0)?this:a; } -function bnMax(a) { return(this.compareTo(a)>0)?this:a; } - -// (protected) r = this op a (bitwise) -function bnpBitwiseTo(a,op,r) { - var i, f, m = Math.min(a.t,this.t); - for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]); - if(a.t < this.t) { - f = a.s&this.DM; - for(i = m; i < this.t; ++i) r[i] = op(this[i],f); - r.t = this.t; - } - else { - f = this.s&this.DM; - for(i = m; i < a.t; ++i) r[i] = op(f,a[i]); - r.t = a.t; - } - r.s = op(this.s,a.s); - r.clamp(); -} - -// (public) this & a -function op_and(x,y) { return x&y; } -function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; } - -// (public) this | a -function op_or(x,y) { return x|y; } -function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; } - -// (public) this ^ a -function op_xor(x,y) { return x^y; } -function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; } - -// (public) this & ~a -function op_andnot(x,y) { return x&~y; } -function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; } - -// (public) ~this -function bnNot() { - var r = nbi(); - for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i]; - r.t = this.t; - r.s = ~this.s; - return r; -} - -// (public) this << n -function bnShiftLeft(n) { - var r = nbi(); - if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r); - return r; -} - -// (public) this >> n -function bnShiftRight(n) { - var r = nbi(); - if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r); - return r; -} - -// return index of lowest 1-bit in x, x < 2^31 -function lbit(x) { - if(x == 0) return -1; - var r = 0; - if((x&0xffff) == 0) { x >>= 16; r += 16; } - if((x&0xff) == 0) { x >>= 8; r += 8; } - if((x&0xf) == 0) { x >>= 4; r += 4; } - if((x&3) == 0) { x >>= 2; r += 2; } - if((x&1) == 0) ++r; - return r; -} - -// (public) returns index of lowest 1-bit (or -1 if none) -function bnGetLowestSetBit() { - for(var i = 0; i < this.t; ++i) - if(this[i] != 0) return i*this.DB+lbit(this[i]); - if(this.s < 0) return this.t*this.DB; - return -1; -} - -// return number of 1 bits in x -function cbit(x) { - var r = 0; - while(x != 0) { x &= x-1; ++r; } - return r; -} - -// (public) return number of set bits -function bnBitCount() { - var r = 0, x = this.s&this.DM; - for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x); - return r; -} - -// (public) true iff nth bit is set -function bnTestBit(n) { - var j = Math.floor(n/this.DB); - if(j >= this.t) return(this.s!=0); - return((this[j]&(1<<(n%this.DB)))!=0); -} - -// (protected) this op (1<<n) -function bnpChangeBit(n,op) { - var r = BigInteger.ONE.shiftLeft(n); - this.bitwiseTo(r,op,r); - return r; -} - -// (public) this | (1<<n) -function bnSetBit(n) { return this.changeBit(n,op_or); } - -// (public) this & ~(1<<n) -function bnClearBit(n) { return this.changeBit(n,op_andnot); } - -// (public) this ^ (1<<n) -function bnFlipBit(n) { return this.changeBit(n,op_xor); } - -// (protected) r = this + a -function bnpAddTo(a,r) { - var i = 0, c = 0, m = Math.min(a.t,this.t); - while(i < m) { - c += this[i]+a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - if(a.t < this.t) { - c += a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c += a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += a.s; - } - r.s = (c<0)?-1:0; - if(c > 0) r[i++] = c; - else if(c < -1) r[i++] = this.DV+c; - r.t = i; - r.clamp(); -} - -// (public) this + a -function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; } - -// (public) this - a -function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; } - -// (public) this * a -function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; } - -// (public) this / a -function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; } - -// (public) this % a -function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; } - -// (public) [this/a,this%a] -function bnDivideAndRemainder(a) { - var q = nbi(), r = nbi(); - this.divRemTo(a,q,r); - return new Array(q,r); -} - -// (protected) this *= n, this >= 0, 1 < n < DV -function bnpDMultiply(n) { - this[this.t] = this.am(0,n-1,this,0,0,this.t); - ++this.t; - this.clamp(); -} - -// (protected) this += n << w words, this >= 0 -function bnpDAddOffset(n,w) { - if(n == 0) return; - while(this.t <= w) this[this.t++] = 0; - this[w] += n; - while(this[w] >= this.DV) { - this[w] -= this.DV; - if(++w >= this.t) this[this.t++] = 0; - ++this[w]; - } -} - -// A "null" reducer -function NullExp() {} -function nNop(x) { return x; } -function nMulTo(x,y,r) { x.multiplyTo(y,r); } -function nSqrTo(x,r) { x.squareTo(r); } - -NullExp.prototype.convert = nNop; -NullExp.prototype.revert = nNop; -NullExp.prototype.mulTo = nMulTo; -NullExp.prototype.sqrTo = nSqrTo; - -// (public) this^e -function bnPow(e) { return this.exp(e,new NullExp()); } - -// (protected) r = lower n words of "this * a", a.t <= n -// "this" should be the larger one if appropriate. -function bnpMultiplyLowerTo(a,n,r) { - var i = Math.min(this.t+a.t,n); - r.s = 0; // assumes a,this >= 0 - r.t = i; - while(i > 0) r[--i] = 0; - var j; - for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t); - for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i); - r.clamp(); -} - -// (protected) r = "this * a" without lower n words, n > 0 -// "this" should be the larger one if appropriate. -function bnpMultiplyUpperTo(a,n,r) { - --n; - var i = r.t = this.t+a.t-n; - r.s = 0; // assumes a,this >= 0 - while(--i >= 0) r[i] = 0; - for(i = Math.max(n-this.t,0); i < a.t; ++i) - r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n); - r.clamp(); - r.drShiftTo(1,r); -} - -// Barrett modular reduction -function Barrett(m) { - // setup Barrett - this.r2 = nbi(); - this.q3 = nbi(); - BigInteger.ONE.dlShiftTo(2*m.t,this.r2); - this.mu = this.r2.divide(m); - this.m = m; -} - -function barrettConvert(x) { - if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m); - else if(x.compareTo(this.m) < 0) return x; - else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; } -} - -function barrettRevert(x) { return x; } - -// x = x mod m (HAC 14.42) -function barrettReduce(x) { - x.drShiftTo(this.m.t-1,this.r2); - if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); } - this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3); - this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2); - while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1); - x.subTo(this.r2,x); - while(x.compareTo(this.m) >= 0) x.subTo(this.m,x); -} - -// r = x^2 mod m; x != r -function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); } - -// r = x*y mod m; x,y != r -function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } - -Barrett.prototype.convert = barrettConvert; -Barrett.prototype.revert = barrettRevert; -Barrett.prototype.reduce = barrettReduce; -Barrett.prototype.mulTo = barrettMulTo; -Barrett.prototype.sqrTo = barrettSqrTo; - -// (public) this^e % m (HAC 14.85) -function bnModPow(e,m) { - var i = e.bitLength(), k, r = nbv(1), z; - if(i <= 0) return r; - else if(i < 18) k = 1; - else if(i < 48) k = 3; - else if(i < 144) k = 4; - else if(i < 768) k = 5; - else k = 6; - if(i < 8) - z = new Classic(m); - else if(m.isEven()) - z = new Barrett(m); - else - z = new Montgomery(m); - - // precomputation - var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1; - g[1] = z.convert(this); - if(k > 1) { - var g2 = nbi(); - z.sqrTo(g[1],g2); - while(n <= km) { - g[n] = nbi(); - z.mulTo(g2,g[n-2],g[n]); - n += 2; - } - } - - var j = e.t-1, w, is1 = true, r2 = nbi(), t; - i = nbits(e[j])-1; - while(j >= 0) { - if(i >= k1) w = (e[j]>>(i-k1))&km; - else { - w = (e[j]&((1<<(i+1))-1))<<(k1-i); - if(j > 0) w |= e[j-1]>>(this.DB+i-k1); - } - - n = k; - while((w&1) == 0) { w >>= 1; --n; } - if((i -= n) < 0) { i += this.DB; --j; } - if(is1) { // ret == 1, don't bother squaring or multiplying it - g[w].copyTo(r); - is1 = false; - } - else { - while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; } - if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; } - z.mulTo(r2,g[w],r); - } - - while(j >= 0 && (e[j]&(1<<i)) == 0) { - z.sqrTo(r,r2); t = r; r = r2; r2 = t; - if(--i < 0) { i = this.DB-1; --j; } - } - } - return z.revert(r); -} - -// (public) gcd(this,a) (HAC 14.54) -function bnGCD(a) { - var x = (this.s<0)?this.negate():this.clone(); - var y = (a.s<0)?a.negate():a.clone(); - if(x.compareTo(y) < 0) { var t = x; x = y; y = t; } - var i = x.getLowestSetBit(), g = y.getLowestSetBit(); - if(g < 0) return x; - if(i < g) g = i; - if(g > 0) { - x.rShiftTo(g,x); - y.rShiftTo(g,y); - } - while(x.signum() > 0) { - if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x); - if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y); - if(x.compareTo(y) >= 0) { - x.subTo(y,x); - x.rShiftTo(1,x); - } - else { - y.subTo(x,y); - y.rShiftTo(1,y); - } - } - if(g > 0) y.lShiftTo(g,y); - return y; -} - -// (protected) this % n, n < 2^26 -function bnpModInt(n) { - if(n <= 0) return 0; - var d = this.DV%n, r = (this.s<0)?n-1:0; - if(this.t > 0) - if(d == 0) r = this[0]%n; - else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n; - return r; -} - -// (public) 1/this % m (HAC 14.61) -function bnModInverse(m) { - var ac = m.isEven(); - if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO; - var u = m.clone(), v = this.clone(); - var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); - while(u.signum() != 0) { - while(u.isEven()) { - u.rShiftTo(1,u); - if(ac) { - if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); } - a.rShiftTo(1,a); - } - else if(!b.isEven()) b.subTo(m,b); - b.rShiftTo(1,b); - } - while(v.isEven()) { - v.rShiftTo(1,v); - if(ac) { - if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); } - c.rShiftTo(1,c); - } - else if(!d.isEven()) d.subTo(m,d); - d.rShiftTo(1,d); - } - if(u.compareTo(v) >= 0) { - u.subTo(v,u); - if(ac) a.subTo(c,a); - b.subTo(d,b); - } - else { - v.subTo(u,v); - if(ac) c.subTo(a,c); - d.subTo(b,d); - } - } - if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO; - if(d.compareTo(m) >= 0) return d.subtract(m); - if(d.signum() < 0) d.addTo(m,d); else return d; - if(d.signum() < 0) return d.add(m); else return d; -} - -var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509]; -var lplim = (1<<26)/lowprimes[lowprimes.length-1]; - -// (public) test primality with certainty >= 1-.5^t -function bnIsProbablePrime(t) { - var i, x = this.abs(); - if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) { - for(i = 0; i < lowprimes.length; ++i) - if(x[0] == lowprimes[i]) return true; - return false; - } - if(x.isEven()) return false; - i = 1; - while(i < lowprimes.length) { - var m = lowprimes[i], j = i+1; - while(j < lowprimes.length && m < lplim) m *= lowprimes[j++]; - m = x.modInt(m); - while(i < j) if(m%lowprimes[i++] == 0) return false; - } - return x.millerRabin(t); -} - -// (protected) true if probably prime (HAC 4.24, Miller-Rabin) -function bnpMillerRabin(t) { - var n1 = this.subtract(BigInteger.ONE); - var k = n1.getLowestSetBit(); - if(k <= 0) return false; - var r = n1.shiftRight(k); - t = (t+1)>>1; - if(t > lowprimes.length) t = lowprimes.length; - var a = nbi(); - for(var i = 0; i < t; ++i) { - a.fromInt(lowprimes[i]); - var y = a.modPow(r,this); - if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { - var j = 1; - while(j++ < k && y.compareTo(n1) != 0) { - y = y.modPowInt(2,this); - if(y.compareTo(BigInteger.ONE) == 0) return false; - } - if(y.compareTo(n1) != 0) return false; - } - } - return true; -} - -// protected -BigInteger.prototype.chunkSize = bnpChunkSize; -BigInteger.prototype.toRadix = bnpToRadix; -BigInteger.prototype.fromRadix = bnpFromRadix; -BigInteger.prototype.fromNumber = bnpFromNumber; -BigInteger.prototype.bitwiseTo = bnpBitwiseTo; -BigInteger.prototype.changeBit = bnpChangeBit; -BigInteger.prototype.addTo = bnpAddTo; -BigInteger.prototype.dMultiply = bnpDMultiply; -BigInteger.prototype.dAddOffset = bnpDAddOffset; -BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo; -BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo; -BigInteger.prototype.modInt = bnpModInt; -BigInteger.prototype.millerRabin = bnpMillerRabin; - -// public -BigInteger.prototype.clone = bnClone; -BigInteger.prototype.intValue = bnIntValue; -BigInteger.prototype.byteValue = bnByteValue; -BigInteger.prototype.shortValue = bnShortValue; -BigInteger.prototype.signum = bnSigNum; -BigInteger.prototype.toByteArray = bnToByteArray; -BigInteger.prototype.equals = bnEquals; -BigInteger.prototype.min = bnMin; -BigInteger.prototype.max = bnMax; -BigInteger.prototype.and = bnAnd; -BigInteger.prototype.or = bnOr; -BigInteger.prototype.xor = bnXor; -BigInteger.prototype.andNot = bnAndNot; -BigInteger.prototype.not = bnNot; -BigInteger.prototype.shiftLeft = bnShiftLeft; -BigInteger.prototype.shiftRight = bnShiftRight; -BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit; -BigInteger.prototype.bitCount = bnBitCount; -BigInteger.prototype.testBit = bnTestBit; -BigInteger.prototype.setBit = bnSetBit; -BigInteger.prototype.clearBit = bnClearBit; -BigInteger.prototype.flipBit = bnFlipBit; -BigInteger.prototype.add = bnAdd; -BigInteger.prototype.subtract = bnSubtract; -BigInteger.prototype.multiply = bnMultiply; -BigInteger.prototype.divide = bnDivide; -BigInteger.prototype.remainder = bnRemainder; -BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder; -BigInteger.prototype.modPow = bnModPow; -BigInteger.prototype.modInverse = bnModInverse; -BigInteger.prototype.pow = bnPow; -BigInteger.prototype.gcd = bnGCD; -BigInteger.prototype.isProbablePrime = bnIsProbablePrime; - -// BigInteger interfaces not implemented in jsbn: - -// BigInteger(int signum, byte[] magnitude) -// double doubleValue() -// float floatValue() -// int hashCode() -// long longValue() -// static BigInteger valueOf(long val) diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/prng4.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/prng4.js deleted file mode 100644 index 3034f3f1158d..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/prng4.js +++ /dev/null @@ -1,45 +0,0 @@ -// prng4.js - uses Arcfour as a PRNG - -function Arcfour() { - this.i = 0; - this.j = 0; - this.S = new Array(); -} - -// Initialize arcfour context from key, an array of ints, each from [0..255] -function ARC4init(key) { - var i, j, t; - for(i = 0; i < 256; ++i) - this.S[i] = i; - j = 0; - for(i = 0; i < 256; ++i) { - j = (j + this.S[i] + key[i % key.length]) & 255; - t = this.S[i]; - this.S[i] = this.S[j]; - this.S[j] = t; - } - this.i = 0; - this.j = 0; -} - -function ARC4next() { - var t; - this.i = (this.i + 1) & 255; - this.j = (this.j + this.S[this.i]) & 255; - t = this.S[this.i]; - this.S[this.i] = this.S[this.j]; - this.S[this.j] = t; - return this.S[(t + this.S[this.i]) & 255]; -} - -Arcfour.prototype.init = ARC4init; -Arcfour.prototype.next = ARC4next; - -// Plug in your RNG constructor here -function prng_newstate() { - return new Arcfour(); -} - -// Pool size must be a multiple of 4 and greater than 32. -// An array of bytes the size of the pool will be passed to init() -var rng_psize = 256; diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rng.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rng.js deleted file mode 100644 index 03afc3a9fe75..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rng.js +++ /dev/null @@ -1,68 +0,0 @@ -// Random number generator - requires a PRNG backend, e.g. prng4.js - -// For best results, put code like -// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'> -// in your main HTML document. - -var rng_state; -var rng_pool; -var rng_pptr; - -// Mix in a 32-bit integer into the pool -function rng_seed_int(x) { - rng_pool[rng_pptr++] ^= x & 255; - rng_pool[rng_pptr++] ^= (x >> 8) & 255; - rng_pool[rng_pptr++] ^= (x >> 16) & 255; - rng_pool[rng_pptr++] ^= (x >> 24) & 255; - if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; -} - -// Mix in the current time (w/milliseconds) into the pool -function rng_seed_time() { - rng_seed_int(new Date().getTime()); -} - -// Initialize the pool with junk if needed. -if(rng_pool == null) { - rng_pool = new Array(); - rng_pptr = 0; - var t; - if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { - // Extract entropy (256 bits) from NS4 RNG if available - var z = window.crypto.random(32); - for(t = 0; t < z.length; ++t) - rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; - } - while(rng_pptr < rng_psize) { // extract some randomness from Math.random() - t = Math.floor(65536 * Math.random()); - rng_pool[rng_pptr++] = t >>> 8; - rng_pool[rng_pptr++] = t & 255; - } - rng_pptr = 0; - rng_seed_time(); - //rng_seed_int(window.screenX); - //rng_seed_int(window.screenY); -} - -function rng_get_byte() { - if(rng_state == null) { - rng_seed_time(); - rng_state = prng_newstate(); - rng_state.init(rng_pool); - for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) - rng_pool[rng_pptr] = 0; - rng_pptr = 0; - //rng_pool = null; - } - // TODO: allow reseeding after first request - return rng_state.next(); -} - -function rng_get_bytes(ba) { - var i; - for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); -} - -function SecureRandom() {} - -SecureRandom.prototype.nextBytes = rng_get_bytes; diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa.js deleted file mode 100644 index 9f8664037c4e..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa.js +++ /dev/null @@ -1,112 +0,0 @@ -// Depends on jsbn.js and rng.js - -// Version 1.1: support utf-8 encoding in pkcs1pad2 - -// convert a (hex) string to a bignum object -function parseBigInt(str,r) { - return new BigInteger(str,r); -} - -function linebrk(s,n) { - var ret = ""; - var i = 0; - while(i + n < s.length) { - ret += s.substring(i,i+n) + "\n"; - i += n; - } - return ret + s.substring(i,s.length); -} - -function byte2Hex(b) { - if(b < 0x10) - return "0" + b.toString(16); - else - return b.toString(16); -} - -// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint -function pkcs1pad2(s,n) { - if(n < s.length + 11) { // TODO: fix for utf-8 - alert("Message too long for RSA"); - return null; - } - var ba = new Array(); - var i = s.length - 1; - while(i >= 0 && n > 0) { - var c = s.charCodeAt(i--); - if(c < 128) { // encode using utf-8 - ba[--n] = c; - } - else if((c > 127) && (c < 2048)) { - ba[--n] = (c & 63) | 128; - ba[--n] = (c >> 6) | 192; - } - else { - ba[--n] = (c & 63) | 128; - ba[--n] = ((c >> 6) & 63) | 128; - ba[--n] = (c >> 12) | 224; - } - } - ba[--n] = 0; - var rng = new SecureRandom(); - var x = new Array(); - while(n > 2) { // random non-zero pad - x[0] = 0; - while(x[0] == 0) rng.nextBytes(x); - ba[--n] = x[0]; - } - ba[--n] = 2; - ba[--n] = 0; - return new BigInteger(ba); -} - -// "empty" RSA key constructor -function RSAKey() { - this.n = null; - this.e = 0; - this.d = null; - this.p = null; - this.q = null; - this.dmp1 = null; - this.dmq1 = null; - this.coeff = null; -} - -// Set the public key fields N and e from hex strings -function RSASetPublic(N,E) { - if(N != null && E != null && N.length > 0 && E.length > 0) { - this.n = parseBigInt(N,16); - this.e = parseInt(E,16); - } - else - alert("Invalid RSA public key"); -} - -// Perform raw public operation on "x": return x^e (mod n) -function RSADoPublic(x) { - return x.modPowInt(this.e, this.n); -} - -// Return the PKCS#1 RSA encryption of "text" as an even-length hex string -function RSAEncrypt(text) { - var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); - if(m == null) return null; - var c = this.doPublic(m); - if(c == null) return null; - var h = c.toString(16); - if((h.length & 1) == 0) return h; else return "0" + h; -} - -// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string -//function RSAEncryptB64(text) { -// var h = this.encrypt(text); -// if(h) return hex2b64(h); else return null; -//} - -// protected -RSAKey.prototype.doPublic = RSADoPublic; - -// public -RSAKey.prototype.setPublic = RSASetPublic; -RSAKey.prototype.encrypt = RSAEncrypt; -//RSAKey.prototype.encrypt_b64 = RSAEncryptB64; diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa2.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa2.js deleted file mode 100644 index 1dfdb701f75d..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/jsbn/rsa2.js +++ /dev/null @@ -1,132 +0,0 @@ -// Depends on rsa.js and jsbn2.js - -// Version 1.1: support utf-8 decoding in pkcs1unpad2 - -// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext -function pkcs1unpad2(d,n) { - var b = d.toByteArray(); - var i = 0; - while(i < b.length && b[i] == 0) ++i; - if(b.length-i != n-1 || b[i] != 2) - return null; - ++i; - while(b[i] != 0) - if(++i >= b.length) return null; - var ret = ""; - while(++i < b.length) { - var c = b[i] & 255; - if(c < 128) { // utf-8 decode - ret += String.fromCharCode(c); - } - else if((c > 191) && (c < 224)) { - ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63)); - ++i; - } - else { - ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63)); - i += 2; - } - } - return ret; -} - -// Set the private key fields N, e, and d from hex strings -function RSASetPrivate(N,E,D) { - if(N != null && E != null && N.length > 0 && E.length > 0) { - this.n = parseBigInt(N,16); - this.e = parseInt(E,16); - this.d = parseBigInt(D,16); - } - else - alert("Invalid RSA private key"); -} - -// Set the private key fields N, e, d and CRT params from hex strings -function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) { - if(N != null && E != null && N.length > 0 && E.length > 0) { - this.n = parseBigInt(N,16); - this.e = parseInt(E,16); - this.d = parseBigInt(D,16); - this.p = parseBigInt(P,16); - this.q = parseBigInt(Q,16); - this.dmp1 = parseBigInt(DP,16); - this.dmq1 = parseBigInt(DQ,16); - this.coeff = parseBigInt(C,16); - } - else - alert("Invalid RSA private key"); -} - -// Generate a new random private key B bits long, using public expt E -function RSAGenerate(B,E) { - var rng = new SecureRandom(); - var qs = B>>1; - this.e = parseInt(E,16); - var ee = new BigInteger(E,16); - for(;;) { - for(;;) { - this.p = new BigInteger(B-qs,1,rng); - if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break; - } - for(;;) { - this.q = new BigInteger(qs,1,rng); - if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break; - } - if(this.p.compareTo(this.q) <= 0) { - var t = this.p; - this.p = this.q; - this.q = t; - } - var p1 = this.p.subtract(BigInteger.ONE); - var q1 = this.q.subtract(BigInteger.ONE); - var phi = p1.multiply(q1); - if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) { - this.n = this.p.multiply(this.q); - this.d = ee.modInverse(phi); - this.dmp1 = this.d.mod(p1); - this.dmq1 = this.d.mod(q1); - this.coeff = this.q.modInverse(this.p); - break; - } - } -} - -// Perform raw private operation on "x": return x^d (mod n) -function RSADoPrivate(x) { - if(this.p == null || this.q == null) - return x.modPow(this.d, this.n); - - // TODO: re-calculate any missing CRT params - var xp = x.mod(this.p).modPow(this.dmp1, this.p); - var xq = x.mod(this.q).modPow(this.dmq1, this.q); - - while(xp.compareTo(xq) < 0) - xp = xp.add(this.p); - return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq); -} - -// Return the PKCS#1 RSA decryption of "ctext". -// "ctext" is an even-length hex string and the output is a plain string. -function RSADecrypt(ctext) { - var c = parseBigInt(ctext, 16); - var m = this.doPrivate(c); - if(m == null) return null; - return pkcs1unpad2(m, (this.n.bitLength()+7)>>3); -} - -// Return the PKCS#1 RSA decryption of "ctext". -// "ctext" is a Base64-encoded string and the output is a plain string. -//function RSAB64Decrypt(ctext) { -// var h = b64tohex(ctext); -// if(h) return this.decrypt(h); else return null; -//} - -// protected -RSAKey.prototype.doPrivate = RSADoPrivate; - -// public -RSAKey.prototype.setPrivate = RSASetPrivate; -RSAKey.prototype.setPrivateEx = RSASetPrivateEx; -RSAKey.prototype.generate = RSAGenerate; -RSAKey.prototype.decrypt = RSADecrypt; -//RSAKey.prototype.b64_decrypt = RSAB64Decrypt; diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth.js deleted file mode 100644 index caeb3091e7d2..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth.js +++ /dev/null @@ -1,23 +0,0 @@ -function tx_rsaauth_encryptUserSetup() { - - var rsa = new RSAKey(); - rsa.setPublic(document.usersetup.n.value, document.usersetup.e.value); - - var password = document.getElementById('field_password').value; - var password2 = document.getElementById('field_password2').value; - var passwordCurrent = document.getElementById('field_passwordCurrent').value; - - if (password || password2 || passwordCurrent) { - var res; - if (res = rsa.encrypt(password)) { - document.getElementById('field_password').value = 'rsa:' + hex2b64(res); - } - if (res = rsa.encrypt(password2)) { - document.getElementById('field_password2').value = 'rsa:' + hex2b64(res); - } - if (res = rsa.encrypt(passwordCurrent)) { - document.getElementById('field_passwordCurrent').value = 'rsa:' + hex2b64(res); - } - } - return false; -} diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth_min.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth_min.js deleted file mode 100644 index fe707d947234..000000000000 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/rsaauth_min.js +++ /dev/null @@ -1 +0,0 @@ -function tx_rsaauth_encryptUserSetup(){var e=new RSAKey;e.setPublic(document.usersetup.n.value,document.usersetup.e.value);var t=document.getElementById("field_password").value;var n=document.getElementById("field_password2").value;var r=document.getElementById("field_passwordCurrent").value;if(t||n||r){var i;if(i=e.encrypt(t)){document.getElementById("field_password").value="rsa:"+hex2b64(i)}if(i=e.encrypt(n)){document.getElementById("field_password2").value="rsa:"+hex2b64(i)}if(i=e.encrypt(r)){document.getElementById("field_passwordCurrent").value="rsa:"+hex2b64(i)}}return false} diff --git a/typo3/sysext/rsaauth/ext_localconf.php b/typo3/sysext/rsaauth/ext_localconf.php index d3ba763c0d74..ea37b58d4759 100644 --- a/typo3/sysext/rsaauth/ext_localconf.php +++ b/typo3/sysext/rsaauth/ext_localconf.php @@ -31,11 +31,15 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['displ FALSE ); +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerAjaxHandler( + 'RsaEncryption::getRsaPublicKey', + \TYPO3\CMS\Rsaauth\RsaEncryptionEncoder::class . '->getRsaPublicKeyAjaxHandler', + FALSE +); + // eID for FrontendLoginRsaPublicKey $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['FrontendLoginRsaPublicKey'] = 'EXT:rsaauth/Resources/PHP/FrontendLoginRsaPublicKey.php'; -$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructPostProcess'][] = \TYPO3\CMS\Rsaauth\Hook\BackendHookForAjaxLogin::class . '->addRsaJsLibraries'; - \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class)->connect( \TYPO3\CMS\Backend\LoginProvider\UsernamePasswordLoginProvider::class, \TYPO3\CMS\Backend\LoginProvider\UsernamePasswordLoginProvider::SIGNAL_getPageRenderer, diff --git a/typo3/sysext/setup/Classes/Controller/SetupModuleController.php b/typo3/sysext/setup/Classes/Controller/SetupModuleController.php index f22f537dee5f..73a1abd70c28 100644 --- a/typo3/sysext/setup/Classes/Controller/SetupModuleController.php +++ b/typo3/sysext/setup/Classes/Controller/SetupModuleController.php @@ -538,6 +538,7 @@ class SetupModuleController { if ($type === 'password') { $value = ''; $noAutocomplete = 'autocomplete="off" '; + $more .= ' data-rsa-encryption=""'; } $html = '<input id="field_' . $fieldName . '" type="' . $type . '" -- GitLab