Subversion Repositories oidplus

Rev

Rev 1085 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. namespace ViaThinkSoft\OIDplus;
  21.  
  22. // phpcs:disable PSR1.Files.SideEffects
  23. \defined('INSIDE_OIDPLUS') or die;
  24. // phpcs:enable PSR1.Files.SideEffects
  25.  
  26. class OIDplusAuthPluginPhpGenericSaltedHex extends OIDplusAuthPlugin {
  27.  
  28.         private function getBinaryHash($s_authmethod, $hashalgo, $salt, $check_password) {
  29.                 if ($s_authmethod == 'A1a') {
  30.                         // This auth method can be used by you if you migrate users from another software solution into OIDplus
  31.                         // A1a#hashalgo:X with X being H(salt+password) in hex- or base64-notation
  32.                         // Attention: With some hash algorithms, prepending the salt makes it vulnerable against length-extension-attacks
  33.                         return hash($hashalgo, $salt.$check_password, true);
  34.                 } else if ($s_authmethod == 'A1b') {
  35.                         // This auth method can be used by you if you migrate users from another software solution into OIDplus
  36.                         // A1b#hashalgo:X with X being H(password+salt) in hex- or base64-notation
  37.                         return hash($hashalgo, $check_password.$salt, true);
  38.                 } else if ($s_authmethod == 'A1c') {
  39.                         // This auth method can be used by you if you migrate users from another software solution into OIDplus
  40.                         // A1c#hashalgo:X with X being H(salt+password+salt) in hex- or base64-notation
  41.                         return hash($hashalgo, $salt.$check_password.$salt, true);
  42.                 } else if ($s_authmethod == 'A1d') {
  43.                         // This auth method can be used by you if you migrate users from another software solution into OIDplus
  44.                         // A1d#hashalgo:X with X being H_HMAC(password,salt) in hex- or base64-notation
  45.                         return hash_hmac($hashalgo, $check_password, $salt, true);
  46.                 } else {
  47.                         // Invalid auth code
  48.                         return false;
  49.                 }
  50.         }
  51.  
  52.         public function verify(OIDplusRAAuthInfo $authInfo, $check_password) {
  53.                 $authKey = $authInfo->getAuthKey();
  54.                 $salt = $authInfo->getSalt();
  55.                 @list($s_authmethod, $s_authkey) = explode('#', $authKey, 2);
  56.  
  57.                 $hashalgo = explode(':', $s_authkey, 2)[0];
  58.  
  59.                 $bindata = $this->getBinaryHash($s_authmethod, $hashalgo, $salt, $check_password);
  60.                 if ($bindata === false) return false;
  61.  
  62.                 return hash_equals($s_authkey, $hashalgo.':'.strtolower(bin2hex($bindata)))
  63.                     || hash_equals($s_authkey, $hashalgo.':'.base64_encode($bindata))
  64.                     || hash_equals($s_authkey, $hashalgo.':'.rtrim(base64_encode($bindata),'='));
  65.         }
  66.  
  67.         public function generate($password): OIDplusRAAuthInfo {
  68.                 $preferred_hash_algos = array(
  69.                     // sorted by priority
  70.                     'sha3-512',
  71.                     'sha3-384',
  72.                     'sha3-256',
  73.                     'sha3-224',
  74.                     'sha512',
  75.                     'sha512/256',
  76.                     'sha512/224',
  77.                     'sha384',
  78.                     'sha256',
  79.                     'sha224',
  80.                     'sha1',
  81.                     'md5'
  82.                 );
  83.  
  84.                 $s_authmethod = 'A1c';
  85.  
  86.                 $algos = hash_algos();
  87.                 $hashalgo = null;
  88.                 foreach ($preferred_hash_algos as $a) {
  89.                         if (in_array($a, $algos)) {
  90.                                 $hashalgo = $a;
  91.                                 break;
  92.                         }
  93.                 }
  94.                 if (is_null($hashalgo)) {
  95.                         throw new OIDplusException(_L('No fitting hash algorithm found'));
  96.                 }
  97.                 $salt = bin2hex(OIDplus::authUtils()->getRandomBytes(50)); // DB field ra.salt is limited to 100 chars (= 50 bytes)
  98.  
  99.                 $bindata = $this->getBinaryHash($s_authmethod, $hashalgo, $salt, $password);
  100.                 if ($bindata === false) throw new OIDplusException(_L('Invalid hash auth method'));
  101.  
  102.                 $calc_authkey = $s_authmethod.'#'.$hashalgo.':'.strtolower(bin2hex($bindata));
  103.  
  104.                 if (strlen($calc_authkey) > 100) {
  105.                         // Since our database field is limited to 100 bytes, use base64 instead of hex
  106.                         $calc_authkey = $s_authmethod.'#'.$hashalgo.':'.base64_encode($bindata);
  107.                         $calc_authkey = rtrim($calc_authkey,'=');
  108.                         /*
  109.                         [Base64] sha3-512   authkey length in hex is 141 and length in base64 is 99
  110.                         [Base64] sha3-384   authkey length in hex is 109 and length in base64 is 77
  111.                         [Hex]    sha3-256   authkey length in hex is  77 and length in base64 is 56
  112.                         [Hex]    sha3-224   authkey length in hex is  69 and length in base64 is 51
  113.                         [Base64] sha512     authkey length in hex is 139 and length in base64 is 97
  114.                         [Hex]    sha512/256 authkey length in hex is  79 and length in base64 is 58
  115.                         [Hex]    sha512/224 authkey length in hex is  71 and length in base64 is 53
  116.                         [Base64] sha384     authkey length in hex is 107 and length in base64 is 75
  117.                         [Hex]    sha256     authkey length in hex is  75 and length in base64 is 54
  118.                         [Hex]    sha224     authkey length in hex is  67 and length in base64 is 49
  119.                         [Hex]    sha1       authkey length in hex is  49 and length in base64 is 36
  120.                         [Hex]    md5        authkey length in hex is  40 and length in base64 is 30
  121.                         */
  122.                 }
  123.  
  124.                 return new OIDplusRAAuthInfo($salt, $calc_authkey);
  125.         }
  126.  
  127. }
  128.