Pure-PHP implementation of Blowfish.
author | Jim Wigginton terrafrost@php.net |
---|---|
author | Hans-Juergen Petrich petrich@tronic-media.com |
package | Default |
__construct(string $mode)
$mode could be:
ecb
cbc
ctr
cfb
cfb8
ofb
ofb8
Throws |
|
---|
string
bcrypt_hash(string $sha2pass,string $sha2salt): string
access | private |
---|
string
string
string
bcrypt_pbkdf(string $pass,string $salt,integer $keylen,integer $rounds): string
access | public |
---|
string
string
integer
integer
string
createInlineCryptFunction(array $cipher_code): string
Internally for phpseclib developers:
_createInlineCryptFunction():
merge the $cipher_code [setup'ed by _setupInlineCrypt()] with the current [$this->]mode of operation code
create the $inline function, which called by encrypt() / decrypt() as its replacement to speed up the en/decryption operations.
return the name of the created $inline callback function
used to speed up en/decryption
The main reason why can speed up things [up to 50%] this way are:
using variables more effective then regular. (ie no use of expensive arrays but integers $k_0, $k_1 ... or even, for example, the pure $key[] values hardcoded)
avoiding 1000's of function calls of ie _encryptBlock() but inlining the crypt operations. in the mode of operation for() loop.
full loop unroll the (sometimes key-dependent) rounds avoiding this way ++$i counters and runtime-if's etc...
The basic code architectur of the generated $inline en/decrypt() lambda function, in pseudo php, is:
+----------------------------------------------------------------------------------------------+ |
callback $inline = create_function: | lambda_function_0001_crypt_ECB($action, $text) | { | INSERT PHP CODE OF: | $cipher_code['init_crypt']; // general init code. | // ie: $sbox'es declarations used for | // encrypt and decrypt'ing. | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
switch ($action) { | |||||||||||||
case 'encrypt': | |||||||||||||
INSERT PHP CODE OF: | |||||||||||||
$cipher_code['init_encrypt']; // encrypt sepcific init code. | |||||||||||||
ie: specified $key or $box | |||||||||||||
declarations for encrypt'ing. | |||||||||||||
foreach ($ciphertext) { | |||||||||||||
$in = $block_size of $ciphertext; | |||||||||||||
INSERT PHP CODE OF: | |||||||||||||
$cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: | |||||||||||||
// strlen($in) == $this->block_size | |||||||||||||
// here comes the cipher algorithm in action | |||||||||||||
// for encryption. | |||||||||||||
// $cipher_code['encrypt_block'] has to | |||||||||||||
// encrypt the content of the $in variable | |||||||||||||
$plaintext .= $in; | |||||||||||||
} | |||||||||||||
return $plaintext; | |||||||||||||
case 'decrypt': | |||||||||||||
INSERT PHP CODE OF: | |||||||||||||
$cipher_code['init_decrypt']; // decrypt sepcific init code | |||||||||||||
ie: specified $key or $box | |||||||||||||
declarations for decrypt'ing. | |||||||||||||
foreach ($plaintext) { | |||||||||||||
$in = $block_size of $plaintext; | |||||||||||||
INSERT PHP CODE OF: | |||||||||||||
$cipher_code['decrypt_block']; // decrypt's (string) $in, which is always | |||||||||||||
// strlen($in) == $this->block_size | |||||||||||||
// here comes the cipher algorithm in action | |||||||||||||
// for decryption. | |||||||||||||
// $cipher_code['decrypt_block'] has to | |||||||||||||
// decrypt the content of the $in variable | |||||||||||||
$ciphertext .= $in; | |||||||||||||
} | |||||||||||||
return $ciphertext; | |||||||||||||
} | |||||||||||||
} |
+----------------------------------------------------------------------------------------------+
See also the \phpseclib3\Crypt*::_setupInlineCrypt()'s for productive inline $cipher_code's how they works.
Structure of:
$cipher_code = [
'init_crypt' => (string) '', // optional
'init_encrypt' => (string) '', // optional
'init_decrypt' => (string) '', // optional
'encrypt_block' => (string) '', // required
'decrypt_block' => (string) '' // required
];
see | self::setupInlineCrypt()\phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|
array
string
(the name of the created callback function)
decrypt(string $ciphertext): string
If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until it is.
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\SymmetricKey::encrypt() |
---|---|
Throws |
|
string
string
$plaintext
decryptBlock(string $in): string
Note: Must be extended by the child \phpseclib3\Crypt* class
string
string
disableContinuousBuffer()
The default behavior.
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer() |
---|---|
disablePadding()
enableContinuousBuffer()
Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets will yield different outputs:
echo $rijndael->encrypt(substr($plaintext, 0, 16));
echo $rijndael->encrypt(substr($plaintext, 16, 16));
echo $rijndael->encrypt($plaintext);
The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates another, as demonstrated with the following:
$rijndael->encrypt(substr($plaintext, 0, 16));
echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different outputs. The reason is due to the fact that the initialization vector's change after every encryption / decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt*() object changes after each encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), however, they are also less intuitive and more likely to cause you problems.
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer() |
---|---|
enablePadding()
Block ciphers working by encrypting between their specified [$this->]block_size at a time If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to pad the input so that it is of the proper length.
Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH, where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is transmitted separately)
see | \phpseclib3\Crypt\Common\SymmetricKey::disablePadding() |
---|---|
enablePoly1305()
Once enabled Poly1305 cannot be disabled.
Throws |
|
---|
encrypt(string $plaintext): string
$plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following URL:
http://www.di-mgt.com.au/cryptopad.html
An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does. strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that length.
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|
string
string
$ciphertext
encryptBlock(string $in): string
Note: Must be extended by the child \phpseclib3\Crypt* class
string
string
encryptBlockHelperFast(integer $x0,integer $x1,array<mixed,integer> $sbox0,array<mixed,integer> $sbox1,array<mixed,integer> $sbox2,array<mixed,integer> $sbox3,array<mixed,integer> $p): array<mixed,integer>
access | private |
---|
integer
integer
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
encryptBlockHelperSlow(integer $x0,integer $x1,array<mixed,integer> $sbox0,array<mixed,integer> $sbox1,array<mixed,integer> $sbox2,array<mixed,integer> $sbox3,array<mixed,integer> $p): array<mixed,integer>
access | private |
---|
integer
integer
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
array<mixed,integer>
getBlockLength(): integer
integer
getBlockLengthInBytes(): integer
integer
getEngine()
getIV(string $iv): string
mcrypt requires an IV even if ECB is used
see | \phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|
string
string
getKeyLength(): integer
integer
getMode(): string
You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode
string
getTag(integer $length = 16): string
Only used in GCM or Poly1305 mode
see | \phpseclib3\Crypt\Common\SymmetricKey::encrypt() |
---|---|
Throws |
|
integer
optional
string
ghash(string $x): string
See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20 for more info
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt()\phpseclib3\Crypt\Common\SymmetricKey::encrypt() |
---|
string
string
initialize_static_variables()
isValidEngine(string $engine): boolean
isValidEngineHelper(integer $engine): boolean
len64(string $str): string
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt()\phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::setupGCM() |
---|
string
string
nullPad128(string $str): string
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt()\phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::setupGCM() |
---|
string
string
openssl_ctr_process(string $plaintext,string &$encryptIV,array &$buffer): string
PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this function will emulate CTR with ECB when necessary.
see | \phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|
string
string
array
string
openssl_ofb_process(string $plaintext,string &$encryptIV,array &$buffer): string
PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt() and SymmetricKey::decrypt().
see | \phpseclib3\Crypt\Common\SymmetricKey::encrypt()\phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|
string
string
array
string
openssl_translate_mode(): string
May need to be overwritten by classes extending this one in some cases
string
pad(string $text): string
Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize. $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to chr($this->block_size - (strlen($text) % $this->block_size)
If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless and padding will, hence forth, be enabled.
see | \phpseclib3\Crypt\Common\SymmetricKey::unpad() |
---|---|
Throws |
|
string
string
pkcs12helper(integer $n,\phpseclib3\Crypt\Hash $hashObj,string $i,string $d,integer $count): string
As discussed here:
see | \phpseclib3\Crypt\Common\SymmetricKey::setPassword() |
---|
integer
\phpseclib3\Crypt\Hash
string
string
integer
string
$a
poly1305(string $text): string
On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation it takes 1.2s.
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt()\phpseclib3\Crypt\Common\SymmetricKey::encrypt() |
---|
string
string
safe_intval(string $x): integer
On ARM CPUs converting floats to ints doesn't always work
string
integer
safe_intval_inline(): string
string
setAAD(string $aad)
setAAD() is only used by gcm or in poly1305 mode
Throws |
|
---|
string
setEngine()
setIV(string $iv)
setIV() is not required when ecb or gcm modes are being used.
{@internal Can be overwritten by a sub class, but does not have to be}
Throws |
|
---|
string
setKey(string $key)
The min/max length(s) of the key depends on the cipher which is used. If the key not fits the length(s) of the cipher it will paded with null bytes up to the closest valid key length. If the key is more than max length, we trim the excess bits.
If the key is not explicitly set, it'll be assumed to be all null bytes.
{@internal Could, but not must, extend by the child Crypt_* class}
string
setKeyLength(integer $length)
Keys with explicitly set lengths need to be treated accordingly
integer
setNonce(string $nonce)
setNonce() is only required when gcm is used
Throws |
|
---|
string
setPassword(string $password,string $method = 'pbkdf2',array<mixed,string> $func_args): boolean
Depending on what $method is set to, setPassword()'s (optional) parameters are as follows: pbkdf2 or pbkdf1: $hash, $salt, $count, $dkLen
Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
[bcypt](https://en.wikipedia.org/wiki/Bcrypt):
$salt, $rounds, $keylen
This is a modified version of bcrypt used by OpenSSH.
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\Crypt/Hash.php |
---|---|
Throws |
|
string
string
array<mixed,string>
boolean
setPoly1305Key(string $key = null)
Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key will be made.
Throws |
|
---|
string
optional
setPreferredEngine(string $engine)
Currently, $engine could be:
libsodium[very fast]
OpenSSL [very fast]
mcrypt [fast]
Eval [slow]
If the preferred crypt engine is not available the fastest available one will be used
see | \phpseclib3\Crypt\Common\SymmetricKey::__construct() |
---|---|
string
setTag(string $tag)
Only used in GCM mode
see | \phpseclib3\Crypt\Common\SymmetricKey::decrypt() |
---|---|
Throws |
|
string
setup()
(re)init, if necessary, the internal cipher $engine and flush all $buffers Used (only) if $engine == self::ENGINE_INTERNAL
_setup() will be called each time if $changed === true typically this happens when using one or more of following public methods:
setKey()
setIV()
disableContinuousBuffer()
{@internal setup() is always called before en/decryption.}
{@internal Could, but not must, extend by the child Crypt_* class}
see | \phpseclib3\Crypt\Common\SymmetricKey::setKey()\phpseclib3\Crypt\Common\SymmetricKey::setIV()\phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer() |
---|---|
setupGCM()
See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23 for more info
setupInlineCrypt()
see | \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt() |
---|---|
setupKey()
Only used if $engine == self::ENGINE_INTERNAL
Note: Must extend by the child \phpseclib3\Crypt* class
see | \phpseclib3\Crypt\Common\SymmetricKey::setup() |
---|---|
unpad(string $text): string
If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong and false will be returned.
see | \phpseclib3\Crypt\Common\SymmetricKey::pad() |
---|---|
Throws |
|
string
string
usesIV(): boolean
boolean
usesNonce(): boolean
boolean
MODE_CTR
Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
link | http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29 |
---|---|
see | |
MODE_ECB
MODE_CBC
MODE_CFB
MODE_CFB8
see | |
---|---|
MODE_OFB8
see | |
---|---|
MODE_OFB
MODE_GCM
MODE_STREAM
see | |
---|---|
MODE_MAP
see | |
---|---|
ENGINE_INTERNAL
see | |
---|---|
ENGINE_EVAL
see | |
---|---|
ENGINE_MCRYPT
see | |
---|---|
ENGINE_OPENSSL
see | |
---|---|
ENGINE_LIBSODIUM
see | |
---|---|
ENGINE_OPENSSL_GCM
see | |
---|---|
ENGINE_MAP
see | |
---|---|
block_size :integer
var |
---|
integer
cipher_name_mcrypt :string
Only used if $engine == self::ENGINE_MCRYPT
link | |
---|---|
see | |
var |
string
cfb_init_len :integer
Only relevant if $continuousBuffer enabled and $engine == self::ENGINE_MCRYPT
It's faster to re-init $enmcrypt if $buffer bytes > $cfb_init_len than using the $ecb resource furthermore.
This value depends of the chosen cipher and the time it would be needed for it's initialization [by mcrypt_generic_init()] which, typically, depends on the complexity on its internaly Key-expanding algorithm.
see | |
---|---|
var |
integer
sbox0 :array
S-Box 0
var |
---|
array
sbox1 :array
var |
---|
array
sbox2 :array
var |
---|
array
sbox3 :array
var |
---|
array
parray :array
var |
---|
array
bctx :array
Holds the expanded key [p] and the key-depended s-boxes [sb]
var |
---|
array
kl :array
var |
---|
array
key_length :integer
see | |
---|---|
var |
integer
mode :integer
see | |
---|---|
var |
integer
key :string
see | |
---|---|
var |
string
hKey :\phpseclib3\Crypt\Common\?string
see | |
---|---|
var |
\phpseclib3\Crypt\Common\?string
iv :string
see | |
---|---|
var |
string
encryptIV :string
see | |
---|---|
var |
string
decryptIV :string
see | |
---|---|
var |
string
continuousBuffer :boolean
see | |
---|---|
var |
boolean
enbuffer :array
see | |
---|---|
var |
array
debuffer :array
see | |
---|---|
var |
array
enmcrypt :resource
The mcrypt resource can be recreated every time something needs to be created or it can be created just once. Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
see | |
---|---|
var |
resource
demcrypt :resource
The mcrypt resource can be recreated every time something needs to be created or it can be created just once. Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
see | |
---|---|
var |
resource
enchanged :boolean
see | |
---|---|
var |
boolean
dechanged :boolean
see | |
---|---|
var |
boolean
ecb :resource
mcrypt's CFB mode, in (and only in) buffered context, is broken, so phpseclib implements the CFB mode by it self, even when the mcrypt php extension is available.
In order to do the CFB-mode work (fast) phpseclib use a separate ECB-mode mcrypt resource.
link | |
---|---|
see | |
var |
resource
changed :boolean
see | |
---|---|
var |
boolean
nonIVChanged :boolean
see | |
---|---|
var |
boolean
padding :boolean
see | |
---|---|
var |
boolean
paddable :boolean
see | |
---|---|
var |
boolean
engine :integer
Currently available $engines are:
see | |
---|---|
var |
integer
preferredEngine :integer
see | |
---|---|
var |
integer
cipher_name_openssl :string
Only used if $engine == self::ENGINE_OPENSSL
link | |
---|---|
var |
string
cipher_name_openssl_ecb :string
If OpenSSL does not support the mode we're trying to use (CTR) it can still be emulated with ECB mode.
link | |
---|---|
var |
string
password_default_salt :string
see | |
---|---|
var |
string
inline_crypt :Callback
Used by encrypt() / decrypt() only if $engine == self::ENGINE_INTERNAL
see | |
---|---|
var |
Callback
openssl_emulate_ctr :boolean
see | |
---|---|
var |
boolean
skip_key_adjustment :boolean
see | |
---|---|
var |
boolean
explicit_key_length :boolean
see | |
---|---|
var |
boolean
h :\phpseclib3\Math\BinaryField\Integer
aad :string
var |
---|
string
newtag :string
var |
---|
string
oldtag :string
var |
---|
string
gcmField :\phpseclib3\Math\BinaryField
poly1305Field :\phpseclib3\Math\PrimeField
use_reg_intval :boolean
see | |
---|---|
var |
boolean
poly1305Key :string
see | |
---|---|
var |
string
usePoly1305 :boolean
see | |
---|---|
var |
boolean
origIV :string
GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived IV's and user-set IV's
see | |
---|---|
var |
string
nonce :string
Only used with GCM. We could re-use setIV() but nonce's can be of a different length and toggling between GCM and other modes could be more complicated if we re-used setIV()
see | |
---|---|
var |
string