* openssl_decrypt() expects the encrypted string you give it to be the
exact one that came out of openssl_encrypt(), it doesn't expect you to
pre-decode the base64 encoding. So don't do that.
* Use the same IV when re-encrypting the underlying hash for comparison.
* Check the return value of OpenSSL functions, and report meaningful
error messages, for sysadmin convenience and to avoid e.g. giving all
users the same hash if an invalid cipher method was chosen (which was
the previous behaviour).
* Fix EncryptedPassword::update(). Tested it with eval.php since there
doesn't seem to be any callers.
Change-Id: I3a39de152d0329f93d16aa4ed43faf08f665b8e2
public function crypt( $password ) {
$secret = $this->config['secrets'][$this->params['secret']];
public function crypt( $password ) {
$secret = $this->config['secrets'][$this->params['secret']];
+ // Clear error string
+ while ( openssl_error_string() !== false );
+
- $underlyingPassword = $this->factory->newFromCiphertext( openssl_decrypt(
- base64_decode( $this->hash ), $this->params['cipher'],
- $secret, 0, base64_decode( $this->args[0] )
- ) );
+ $decrypted = openssl_decrypt(
+ $this->hash, $this->params['cipher'],
+ $secret, 0, base64_decode( $this->args[0] ) );
+ if ( $decrypted === false ) {
+ throw new PasswordError( 'Error decrypting password: ' . openssl_error_string() );
+ }
+ $underlyingPassword = $this->factory->newFromCiphertext( $decrypted );
} else {
$underlyingPassword = $this->factory->newFromType( $this->config['underlying'] );
}
$underlyingPassword->crypt( $password );
} else {
$underlyingPassword = $this->factory->newFromType( $this->config['underlying'] );
}
$underlyingPassword->crypt( $password );
- $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+ if ( count( $this->args ) ) {
+ $iv = base64_decode( $this->args[0] );
+ } else {
+ $iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
+ }
$this->hash = openssl_encrypt(
$underlyingPassword->toString(), $this->params['cipher'], $secret, 0, $iv );
$this->hash = openssl_encrypt(
$underlyingPassword->toString(), $this->params['cipher'], $secret, 0, $iv );
+ if ( $this->hash === false ) {
+ throw new PasswordError( 'Error encrypting password: ' . openssl_error_string() );
+ }
$this->args = [ base64_encode( $iv ) ];
}
$this->args = [ base64_encode( $iv ) ];
}
* @return bool True if the password was updated
*/
public function update() {
* @return bool True if the password was updated
*/
public function update() {
- if ( count( $this->args ) != 2 || $this->params == $this->getDefaultParams() ) {
+ if ( count( $this->args ) != 1 || $this->params == $this->getDefaultParams() ) {
// Hash does not need updating
return false;
}
// Hash does not need updating
return false;
}
+ // Clear error string
+ while ( openssl_error_string() !== false );
+
// Decrypt the underlying hash
$underlyingHash = openssl_decrypt(
// Decrypt the underlying hash
$underlyingHash = openssl_decrypt(
- base64_decode( $this->args[1] ),
$this->params['cipher'],
$this->config['secrets'][$this->params['secret']],
0,
base64_decode( $this->args[0] )
);
$this->params['cipher'],
$this->config['secrets'][$this->params['secret']],
0,
base64_decode( $this->args[0] )
);
+ if ( $underlyingHash === false ) {
+ throw new PasswordError( 'Error decrypting password: ' . openssl_error_string() );
+ }
// Reset the params
$this->params = $this->getDefaultParams();
// Check the key size with the new params
$iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
// Reset the params
$this->params = $this->getDefaultParams();
// Check the key size with the new params
$iv = MWCryptRand::generate( openssl_cipher_iv_length( $this->params['cipher'] ), true );
- $this->hash = base64_encode( openssl_encrypt(
+ $this->hash = openssl_encrypt(
$underlyingHash,
$this->params['cipher'],
$this->config['secrets'][$this->params['secret']],
0,
$iv
$underlyingHash,
$this->params['cipher'],
$this->config['secrets'][$this->params['secret']],
0,
$iv
+ );
+ if ( $this->hash === false ) {
+ throw new PasswordError( 'Error encrypting password: ' . openssl_error_string() );
+ }
+
$this->args = [ base64_encode( $iv ) ];
return true;
$this->args = [ base64_encode( $iv ) ];
return true;