1 <?php
  2 /**
  3  * @package     Joomla.Platform
  4  * @subpackage  Crypt
  5  *
  6  * @copyright   Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
  7  * @license     GNU General Public License version 2 or later; see LICENSE
  8  */
  9 
 10 defined('JPATH_PLATFORM') or die;
 11 
 12 /**
 13  * JCrypt cipher for Simple encryption, decryption and key generation.
 14  *
 15  * @since       12.1
 16  * @deprecated  4.0 (CMS)
 17  */
 18 class JCryptCipherSimple implements JCryptCipher
 19 {
 20     /**
 21      * Method to decrypt a data string.
 22      *
 23      * @param   string     $data  The encrypted string to decrypt.
 24      * @param   JCryptKey  $key   The key[/pair] object to use for decryption.
 25      *
 26      * @return  string  The decrypted data string.
 27      *
 28      * @since   12.1
 29      * @throws  InvalidArgumentException
 30      */
 31     public function decrypt($data, JCryptKey $key)
 32     {
 33         // Validate key.
 34         if ($key->type != 'simple')
 35         {
 36             throw new InvalidArgumentException('Invalid key of type: ' . $key->type . '.  Expected simple.');
 37         }
 38 
 39         $decrypted = '';
 40         $tmp = $key->public;
 41 
 42         // Convert the HEX input into an array of integers and get the number of characters.
 43         $chars = $this->_hexToIntArray($data);
 44         $charCount = count($chars);
 45 
 46         // Repeat the key as many times as necessary to ensure that the key is at least as long as the input.
 47         for ($i = 0; $i < $charCount; $i = strlen($tmp))
 48         {
 49             $tmp = $tmp . $tmp;
 50         }
 51 
 52         // Get the XOR values between the ASCII values of the input and key characters for all input offsets.
 53         for ($i = 0; $i < $charCount; $i++)
 54         {
 55             $decrypted .= chr($chars[$i] ^ ord($tmp[$i]));
 56         }
 57 
 58         return $decrypted;
 59     }
 60 
 61     /**
 62      * Method to encrypt a data string.
 63      *
 64      * @param   string     $data  The data string to encrypt.
 65      * @param   JCryptKey  $key   The key[/pair] object to use for encryption.
 66      *
 67      * @return  string  The encrypted data string.
 68      *
 69      * @since   12.1
 70      * @throws  InvalidArgumentException
 71      */
 72     public function encrypt($data, JCryptKey $key)
 73     {
 74         // Validate key.
 75         if ($key->type != 'simple')
 76         {
 77             throw new InvalidArgumentException('Invalid key of type: ' . $key->type . '.  Expected simple.');
 78         }
 79 
 80         $encrypted = '';
 81         $tmp = $key->private;
 82 
 83         // Split up the input into a character array and get the number of characters.
 84         $chars = preg_split('//', $data, -1, PREG_SPLIT_NO_EMPTY);
 85         $charCount = count($chars);
 86 
 87         // Repeat the key as many times as necessary to ensure that the key is at least as long as the input.
 88         for ($i = 0; $i < $charCount; $i = strlen($tmp))
 89         {
 90             $tmp = $tmp . $tmp;
 91         }
 92 
 93         // Get the XOR values between the ASCII values of the input and key characters for all input offsets.
 94         for ($i = 0; $i < $charCount; $i++)
 95         {
 96             $encrypted .= $this->_intToHex(ord($tmp[$i]) ^ ord($chars[$i]));
 97         }
 98 
 99         return $encrypted;
100     }
101 
102     /**
103      * Method to generate a new encryption key[/pair] object.
104      *
105      * @param   array  $options  Key generation options.
106      *
107      * @return  JCryptKey
108      *
109      * @since   12.1
110      */
111     public function generateKey(array $options = array())
112     {
113         // Create the new encryption key[/pair] object.
114         $key = new JCryptKey('simple');
115 
116         // Just a random key of a given length.
117         $key->private = JCrypt::genRandomBytes(256);
118         $key->public  = $key->private;
119 
120         return $key;
121     }
122 
123     /**
124      * Convert hex to an integer
125      *
126      * @param   string   $s  The hex string to convert.
127      * @param   integer  $i  The offset?
128      *
129      * @return  integer
130      *
131      * @since   11.1
132      */
133     private function _hexToInt($s, $i)
134     {
135         $j = (int) $i * 2;
136         $k = 0;
137         $s1 = (string) $s;
138 
139         // Get the character at position $j.
140         $c = substr($s1, $j, 1);
141 
142         // Get the character at position $j + 1.
143         $c1 = substr($s1, $j + 1, 1);
144 
145         switch ($c)
146         {
147             case 'A':
148                 $k += 160;
149                 break;
150             case 'B':
151                 $k += 176;
152                 break;
153             case 'C':
154                 $k += 192;
155                 break;
156             case 'D':
157                 $k += 208;
158                 break;
159             case 'E':
160                 $k += 224;
161                 break;
162             case 'F':
163                 $k += 240;
164                 break;
165             case ' ':
166                 $k += 0;
167                 break;
168             default:
169                 (int) $k = $k + (16 * (int) $c);
170                 break;
171         }
172 
173         switch ($c1)
174         {
175             case 'A':
176                 $k += 10;
177                 break;
178             case 'B':
179                 $k += 11;
180                 break;
181             case 'C':
182                 $k += 12;
183                 break;
184             case 'D':
185                 $k += 13;
186                 break;
187             case 'E':
188                 $k += 14;
189                 break;
190             case 'F':
191                 $k += 15;
192                 break;
193             case ' ':
194                 $k += 0;
195                 break;
196             default:
197                 $k += (int) $c1;
198                 break;
199         }
200 
201         return $k;
202     }
203 
204     /**
205      * Convert hex to an array of integers
206      *
207      * @param   string  $hex  The hex string to convert to an integer array.
208      *
209      * @return  array  An array of integers.
210      *
211      * @since   11.1
212      */
213     private function _hexToIntArray($hex)
214     {
215         $array = array();
216 
217         $j = (int) strlen($hex) / 2;
218 
219         for ($i = 0; $i < $j; $i++)
220         {
221             $array[$i] = (int) $this->_hexToInt($hex, $i);
222         }
223 
224         return $array;
225     }
226 
227     /**
228      * Convert an integer to a hexadecimal string.
229      *
230      * @param   integer  $i  An integer value to convert to a hex string.
231      *
232      * @return  string
233      *
234      * @since   11.1
235      */
236     private function _intToHex($i)
237     {
238         // Sanitize the input.
239         $i = (int) $i;
240 
241         // Get the first character of the hexadecimal string if there is one.
242         $j = (int) ($i / 16);
243 
244         if ($j === 0)
245         {
246             $s = ' ';
247         }
248         else
249         {
250             $s = strtoupper(dechex($j));
251         }
252 
253         // Get the second character of the hexadecimal string.
254         $k = $i - $j * 16;
255         $s = $s . strtoupper(dechex($k));
256 
257         return $s;
258     }
259 }
260