1<?php
2
3/**
4 * Observium
5 *
6 *   This file is part of Observium.
7 *
8 * @package    observium
9 * @subpackage encrypt
10 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited
11 *
12 */
13
14function encrypt_sodium($string, $key, $nonce = NULL)
15{
16  // https://dev.to/paragonie/libsodium-quick-reference#crypto-secretbox
17
18  $key_len = strlen($key); // mb_strlen($key, '8bit');
19  //logfile('debug_wui.log', 'Encrypt requested. Key: '.$key.', size: '.$key_len);
20  if ($key_len > SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
21  {
22    return FALSE;
23  }
24  else if ($key_len < SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
25  {
26    $key = sodium_pad($key, SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
27    //logfile('debug_wui.log', 'Padded Key: '.$key.', size: '.strlen($key));
28  }
29
30  if (!$nonce)
31  {
32    // Sodium encrypt require $nonce
33    // if not set use server unique id
34    $nonce = get_unique_id();
35  }
36  // Fix nonce length
37  $nonce_len = strlen($nonce); // mb_strlen($nonce, '8bit');
38  if ($nonce_len > SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)
39  {
40    $nonce = substr($nonce, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
41  }
42  else if ($nonce_len < SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)
43  {
44    $nonce = sodium_pad($nonce, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
45  }
46
47  try {
48    $encrypted = safe_base64_encode(sodium_crypto_secretbox($string, $nonce, $key));
49  } catch (SodiumException $ex) {
50    //var_dump($key);
51    $encrypted = FALSE;
52  }
53  //var_dump($encrypted);
54  return $encrypted;
55}
56
57function decrypt_sodium($encrypted, $key, $nonce = NULL)
58{
59  // https://dev.to/paragonie/libsodium-quick-reference#crypto-secretbox
60
61  $key_len = strlen($key); // mb_strlen($key, '8bit');
62  //logfile('debug_wui.log', 'Decrypt requested. Key: '.$key.', size: '.$key_len);
63  if ($key_len > SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
64  {
65    return FALSE;
66  }
67  else if ($key_len < SODIUM_CRYPTO_SECRETBOX_KEYBYTES)
68  {
69    $key = sodium_pad($key, SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
70    //logfile('debug_wui.log', 'Padded Key: '.$key.', size: '.strlen($key));
71  }
72
73  if (!$nonce)
74  {
75    // Sodium encrypt require $nonce
76    // if not set use server unique id
77    $nonce = get_unique_id();
78  }
79  // Fix nonce length
80  $nonce_len = strlen($nonce); // mb_strlen($nonce, '8bit');
81  if ($nonce_len > SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)
82  {
83    $nonce = substr($nonce, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
84  }
85  else if ($nonce_len < SODIUM_CRYPTO_SECRETBOX_NONCEBYTES)
86  {
87    $nonce = sodium_pad($nonce, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
88  }
89
90  try {
91    $string = sodium_crypto_secretbox_open(safe_base64_decode($encrypted), $nonce, $key);
92  }
93  catch (SodiumException $ex) {
94    //var_dump($key);
95    $string = FALSE;
96  }
97  return $string;
98}
99
100function encrypt_mcrypt($string, $key)
101{
102  // Mcrypt deprecated in php > 7.0
103  $key = pad_key($key);
104  $encrypted = safe_base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $string, MCRYPT_MODE_ECB));
105  return $encrypted;
106}
107
108function decrypt_mcrypt($encrypted, $key)
109{
110  // Mcrypt deprecated in php > 7.0
111  $key = pad_key($key);
112  return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, safe_base64_decode($encrypted), MCRYPT_MODE_ECB), "\t\n\r\0\x0B");
113}
114
115// DOCME needs phpdoc block
116function safe_base64_encode($string)
117{
118  $data = base64_encode($string);
119  $data = str_replace(array('+','/','='), array('-','_',''), $data);
120  return $data;
121}
122
123// DOCME needs phpdoc block
124function safe_base64_decode($string)
125{
126  $data = str_replace(array('-','_'), array('+','/'), $string);
127  $mod4 = strlen($data) % 4;
128  if ($mod4)
129  {
130    $data .= substr('====', $mod4);
131  }
132  return base64_decode($data);
133}
134
135// DOCME needs phpdoc block
136function encrypt($string, $key, $nonce = NULL)
137{
138  //logfile('debug_wui.log', 'Encrypt requested');
139
140  if (!OBS_ENCRYPT)
141  {
142    print_debug("Encrypt unsupported. Please install mcrypt extension for php less than 7.2 or enable sodium extension for php 7.2 and greater!");
143    return FALSE;
144  }
145
146  switch (OBS_ENCRYPT_MODULE)
147  {
148    case 'sodium':
149      return encrypt_sodium($string, $key, $nonce);
150      break;
151    case 'mcrypt':
152      return encrypt_mcrypt($string, $key);
153      break;
154  }
155}
156
157// DOCME needs phpdoc block
158function decrypt($encrypted, $key, $nonce = NULL)
159{
160  //logfile('debug_wui.log', 'Decrypt requested');
161
162  if (!OBS_ENCRYPT)
163  {
164    print_debug("Encrypt unsupported. Please install mcrypt extension for php less than 7.2 or enable sodium extension for php 7.2 and greater!");
165    return FALSE;
166  }
167
168  switch (OBS_ENCRYPT_MODULE)
169  {
170    case 'sodium':
171      return decrypt_sodium($encrypted, $key, $nonce);
172      break;
173    case 'mcrypt':
174      return decrypt_mcrypt($encrypted, $key);
175      break;
176  }
177}
178
179// This function required for encrypt/decrypt, since php 5.6
180// see: http://stackoverflow.com/questions/27254432/mcrypt-decrypt-error-change-key-size
181function pad_key($key)
182{
183  // key is too large
184  if (strlen($key) > 32) { return FALSE; }
185
186  // set sizes
187  $sizes = array(16, 24, 32);
188
189  // loop through sizes and pad key
190  foreach($sizes as $s)
191  {
192    while (strlen($key) < $s)
193    {
194      $key = $key . "\0";
195    }
196    if (strlen($key) == $s) { break; } // finish if the key matches a size
197  }
198
199  // return
200  return $key;
201}
202
203// EOF