protected function computeUValue($encryptionKey)
    {
        $revision = $this->revision;
        // Algorithm 4: Computing the encryption dictionary’s U (user password)
        // value (Security handlers of revision 2)
        if ($revision < 3) {
            return $this->arcfour($encryptionKey, $this->padding);
        }

        // Algorithm 5: Computing the encryption dictionary’s U (user password)
        // value (Security handlers of revision 3 or greater)

        // a) Create an encryption key based on the user password string, as described
        //    in "Algorithm 2: Computing an encryption key".
        //    passed through $encryptionKey-parameter

        // b) Initialize the MD5 hash function and pass the 32-byte padding string shown
        //    in step (a) of "Algorithm 2: Computing an encryption key" as input to
        //    this function.
        $s = $this->padding;

        // c) Pass the first element of the file’s file identifier array (the value of
        //    the ID entry in the document’s trailer dictionary; see Table 15) to the
        //    hash function and finish the hash.
        $s .= $this->fileIdentifier;
        $s = md5($s, true);

        // d) Encrypt the 16-byte result of the hash, using an RC4 encryption function
        //    with the encryption key from step (a).
        $s = $this->arcfour($encryptionKey, $s);

        // e) Do the following 19 times: Take the output from the previous invocation
        //    of the RC4 function and pass it as input to a new invocation of the function;
        //    use an encryption key generated by taking each byte of the original encryption
        //    key obtained in step (a) and performing an XOR (exclusive or) operation
        //    between that byte and the single-byte value of the iteration counter (from 1 to 19).
        $length = strlen($encryptionKey);
        for($i = 1; $i <= 19; $i++) {
            $tmp = array();
            for($j = 0; $j < $length; $j++) {
                $tmp[$j] = ord($encryptionKey[$j]) ^ $i;
                $tmp[$j] = chr($tmp[$j]);
            }
            $s = $this->arcfour(join('', $tmp), $s);
        }

        // f) Append 16 bytes of arbitrary padding to the output from the final invocation
        //    of the RC4 function and store the 32-byte result as the value of the U entry
        //    in the encryption dictionary.
        return $s . str_repeat("\0", 16);
    }