问题
I am currently in the process of replacing Mcrypt with OpenSSL since Mcrypt will be deprecated in PHP 7.1. I need is a way to get the blocksize per algorithm like mcrypt_get_block_size().
I am wondering if there is an equivalent function to mcrypt_get_block_size()
but it's pretty badly documented can't seem to find it.
回答1:
php-openssl unfortunately doesn't have an API that would give you the cipher blockSize. If you really need it, you'd have to hard-code the blockSize (per algorithm).
However, typical applications would only need to support a single encryption algorithm, and in that case you should already know what the block size is for your case.
And also, the only use cases I've had for mcrypt_get_block_size()
, mcrypt_enc_get_block_size()
is PKCS#7 padding, which OpenSSL already does by default for block cipher algorithms. So it may be the case that you don't need this at all.
回答2:
The following function can be used as a replacement for PHP >= 5.4.0.
It just bruteforces the block length out of openssl_encrypt()
.
if (!function_exists('openssl_cipher_block_length')) {
/**
* Returns the block length for a given cipher.
*
* @param string $cipher
* A cipher method (see openssl_get_cipher_methods()).
*
* @retval int
* The cipher's block length.
* Returns false if the actual length cannot be determined.
* Returns 0 for some cipher modes that do not use blocks
* to encrypt data.
*
* @note
* PHP >= 5.4.0 is required for this function to work.
*/
function openssl_cipher_block_length($cipher)
{
$ivSize = @openssl_cipher_iv_length($cipher);
// Invalid or unsupported cipher.
if (false === $ivSize) {
return false;
}
$iv = str_repeat("a", $ivSize);
// Loop over possible block sizes, from 1 upto 1024 bytes.
// The upper limit is arbitrary but high enough that is
// sufficient for any current & foreseeable cipher.
for ($size = 1; $size < 1024; $size++) {
$output = openssl_encrypt(
// Try varying the length of the raw data
str_repeat("a", $size),
// Cipher to use
$cipher,
// OpenSSL expands the key as necessary,
// so this value is actually not relevant.
"a",
// Disable data padding: php_openssl will return false
// if the input data's length is not a multiple
// of the block size.
//
// We also pass OPENSSL_RAW_DATA so that PHP does not
// base64-encode the data (since we just throw it away
// afterwards anyway)
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
// Feed it with an IV to avoid nasty warnings.
// The actual value is not relevant as long as
// it has the proper length.
$iv
);
if (false !== $output) {
return $size;
}
}
// Could not determine the cipher's block length.
return false;
}
}
回答3:
I think you can do something like that:
$method = 'AES-256-CBC';
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($method));
$block_size = strlen(openssl_encrypt('', $method, '', OPENSSL_RAW_DATA, $iv));
It's basically encrypting an empty string and, as the data will be padded to the block size, check the result length.
I've tested it with some different methods, and it seems to work properly.
来源:https://stackoverflow.com/questions/42350165/openssl-equivalent-to-mcrypt-get-block-size