saveToAsciiSafeString(), \hash(Core::HASH_FUNCTION_NAME, $password, true), true ); return new KeyProtectedByPassword($encrypted_key); } /** * Loads a KeyProtectedByPassword from its encoded form. * * @param string $saved_key_string * * @throws Ex\BadFormatException * * @return KeyProtectedByPassword */ public static function loadFromAsciiSafeString($saved_key_string) { $encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString( self::PASSWORD_KEY_CURRENT_VERSION, $saved_key_string ); return new KeyProtectedByPassword($encrypted_key); } /** * Encodes the KeyProtectedByPassword into a string of printable ASCII * characters. * * @throws Ex\EnvironmentIsBrokenException * * @return string */ public function saveToAsciiSafeString() { return Encoding::saveBytesToChecksummedAsciiSafeString( self::PASSWORD_KEY_CURRENT_VERSION, $this->encrypted_key ); } /** * Decrypts the protected key, returning an unprotected Key object that can * be used for encryption and decryption. * * @throws Ex\EnvironmentIsBrokenException * @throws Ex\WrongKeyOrModifiedCiphertextException * * @return Key */ public function unlockKey($password) { try { $inner_key_encoded = Crypto::decryptWithPassword( $this->encrypted_key, \hash(Core::HASH_FUNCTION_NAME, $password, true), true ); return Key::loadFromAsciiSafeString($inner_key_encoded); } catch (Ex\BadFormatException $ex) { /* This should never happen unless an attacker replaced the * encrypted key ciphertext with some other ciphertext that was * encrypted with the same password. We transform the exception type * here in order to make the API simpler, avoiding the need to * document that this method might throw an Ex\BadFormatException. */ throw new Ex\WrongKeyOrModifiedCiphertextException( "The decrypted key was found to be in an invalid format. " . "This very likely indicates it was modified by an attacker." ); } } /** * Constructor for KeyProtectedByPassword. * * @param string $encrypted_key */ private function __construct($encrypted_key) { $this->encrypted_key = $encrypted_key; } }