Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F1102460
SecurityEncrypter.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Aug 19, 2:07 AM
Size
5 KB
Mime Type
text/x-php
Expires
Thu, Aug 21, 2:07 AM (1 d, 11 h)
Engine
blob
Format
Raw Data
Handle
714186
Attached To
rINP In-Portal
SecurityEncrypter.php
View Options
<?php
/**
* @version $Id: SecurityEncrypter.php 16771 2023-11-21 09:17:12Z alex $
* @package In-Portal
* @copyright Copyright (C) 1997 - 2018 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined
(
'FULL_PATH'
)
or
die
(
'restricted access!'
);
class
SecurityEncrypter
extends
kBase
{
const
HASHING_ALGORITHM
=
'sha256'
;
const
HASHING_KEY_LENGTH
=
32
;
const
ENCRYPTION_METHOD
=
'aes-128-cbc'
;
// Or 'aes-256-cbc'.
const
ENCRYPTION_KEY_LENGTH
=
16
;
// Or 32.
/**
* The HMAC key.
*
* @var string
*/
protected
$hmacKey
;
/**
* The encryption key.
*
* @var string
*/
protected
$encryptionKey
;
/**
* SecurityEncrypter constructor.
*/
public
function
__construct
()
{
parent
::
__construct
();
$vars
=
kUtil
::
getSystemConfig
()->
getData
();
// In the config data is encoded stored to avoid corruption.
$this
->
hmacKey
=
base64_decode
(
$vars
[
'SecurityHmacKey'
]);
// Equivalent of "hex2bin" for PHP < 5.4.
$this
->
encryptionKey
=
pack
(
'H*'
,
$vars
[
'SecurityEncryptionKey'
]);
}
/**
* Remove security-related info from serialized object version.
*
* @return array
*/
public
function
__sleep
()
{
return
array
(
'Prefix'
,
'Special'
,
'prefixSpecial'
);
}
/**
* Creates signature.
*
* @param string $string String.
* @param boolean $raw_output Return raw signature version.
* @param string|null $key_override Override key.
*
* @return string
*/
public
function
createSignature
(
$string
,
$raw_output
=
false
,
$key_override
=
null
)
{
return
hash_hmac
(
self
::
HASHING_ALGORITHM
,
$string
,
$this
->
_getHmacKey
(
$key_override
),
$raw_output
);
}
/**
* Returns HMAC key.
*
* @param string|null $key_override Key override.
*
* @return string
* @throws InvalidArgumentException When HMAC key is empty.
*/
private
function
_getHmacKey
(
$key_override
=
null
)
{
$key
=
$this
->
doGetHmacKey
(
$key_override
);
if
(
empty
(
$key
)
)
{
throw
new
InvalidArgumentException
(
'The HMAC key is empty.'
);
}
if
(
mb_strlen
(
$key
,
'8bit'
)
===
self
::
HASHING_KEY_LENGTH
)
{
return
$key
;
}
return
$this
->
deriveKey
(
$key
,
self
::
HASHING_KEY_LENGTH
);
}
/**
* Returns HMAC key.
*
* @param string|null $key_override Key override.
*
* @return string
*/
protected
function
doGetHmacKey
(
$key_override
=
null
)
{
return
isset
(
$key_override
)
?
$key_override
:
$this
->
hmacKey
;
}
/**
* Returns encryption key.
*
* @param string|null $key_override Key override.
*
* @return string
* @throws InvalidArgumentException When encryption key is empty.
*/
private
function
_getEncryptionKey
(
$key_override
=
null
)
{
$key
=
$this
->
doGetEncryptionKey
(
$key_override
);
if
(
empty
(
$key
)
)
{
throw
new
InvalidArgumentException
(
'The encryption key is empty.'
);
}
if
(
mb_strlen
(
$key
,
'8bit'
)
===
self
::
ENCRYPTION_KEY_LENGTH
)
{
return
$key
;
}
return
$this
->
deriveKey
(
$key
,
self
::
ENCRYPTION_KEY_LENGTH
);
}
/**
* Returns encryption key.
*
* @param string|null $key_override Key override.
*
* @return string
*/
protected
function
doGetEncryptionKey
(
$key_override
=
null
)
{
return
isset
(
$key_override
)
?
$key_override
:
$this
->
encryptionKey
;
}
/**
* Derives given key.
*
* @param string $key Key.
* @param integer $length Length.
*
* @return string
*/
final
public
function
deriveKey
(
$key
,
$length
)
{
$salt
=
SecurityGenerator
::
generateBytes
(
16
,
true
);
return
hash_pbkdf2
(
self
::
HASHING_ALGORITHM
,
$key
,
$salt
,
80000
,
$length
,
true
);
}
/**
* Encrypts a plain text.
*
* @param string $plaintext Plain text.
* @param string|null $key_override Key override.
*
* @return string
*/
final
public
function
encrypt
(
$plaintext
,
$key_override
=
null
)
{
$iv_size
=
openssl_cipher_iv_length
(
self
::
ENCRYPTION_METHOD
);
$iv
=
openssl_random_pseudo_bytes
(
$iv_size
);
$ciphertext
=
openssl_encrypt
(
$plaintext
,
self
::
ENCRYPTION_METHOD
,
$this
->
_getEncryptionKey
(
$key_override
),
OPENSSL_RAW_DATA
,
$iv
);
// Note: We cover the IV in our HMAC.
$hmac
=
$this
->
createSignature
(
$iv
.
$ciphertext
,
true
);
return
base64_encode
(
$hmac
.
$iv
.
$ciphertext
);
}
/**
* Decrypts a cipher text.
*
* @param string $ciphertext Cipher text.
* @param string|null $key_override Key override.
*
* @return string|false
* @throws LogicException When signature verification has failed.
*/
final
public
function
decrypt
(
$ciphertext
,
$key_override
=
null
)
{
$iv_size
=
openssl_cipher_iv_length
(
self
::
ENCRYPTION_METHOD
);
$decoded
=
base64_decode
(
$ciphertext
);
$hmac
=
mb_substr
(
$decoded
,
0
,
self
::
HASHING_KEY_LENGTH
,
'8bit'
);
$iv
=
mb_substr
(
$decoded
,
self
::
HASHING_KEY_LENGTH
,
$iv_size
,
'8bit'
);
$ciphertext
=
mb_substr
(
$decoded
,
self
::
HASHING_KEY_LENGTH
+
$iv_size
,
null
,
'8bit'
);
$calculated
=
$this
->
createSignature
(
$iv
.
$ciphertext
,
true
);
if
(
!
hash_equals
(
$hmac
,
$calculated
)
)
{
throw
new
LogicException
(
'Signature verification of ciphertext failed.'
);
}
return
openssl_decrypt
(
$ciphertext
,
self
::
ENCRYPTION_METHOD
,
$this
->
_getEncryptionKey
(
$key_override
),
OPENSSL_RAW_DATA
,
$iv
);
}
/**
* Determines if used cipher is available.
*
* @return boolean
*/
final
public
function
cipherAvailable
()
{
return
in_array
(
self
::
ENCRYPTION_METHOD
,
openssl_get_cipher_methods
(),
true
);
}
}
Event Timeline
Log In to Comment