TCPDFの暗号化PDFの作成において、SetProtection設定時の権限パスワードである$owner_passを空白にするとデフォルトでランダムのパスワードが選択されるとあります。実際のところどんな文字列が選ばれているのか気になりましたのでソースで確認してみました。TCPDFのバージョンは最新の6.3.5です。
tcpdf.phpを見ると、10939行目付近に
if ($owner_pass === null) { $owner_pass = md5(TCPDF_STATIC::getRandomSeed()); }
との処理があり、空白の場合はTCPDF_STATIC::getRandomSeed()のmd5ハッシュ値がパスワードの文字列になるようです。
TCPDF_STATIC::getRandomSeed()はというとincludeディレクトリ内のtcpdf_static.phpで定義されており、408行目から
$rnd = uniqid(rand().microtime(true), true); if (function_exists('posix_getpid')) { $rnd .= posix_getpid(); } if (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // this is not used on windows systems because it is very slow for a know bug $rnd .= openssl_random_pseudo_bytes(512); } else { for ($i = 0; $i < 23; ++$i) { $rnd .= uniqid('', true); } } return $rnd.$seed.__FILE__.serialize($_SERVER).microtime(true);
と、uniqid関数、posix_getpid関数があればその値、openssl_random_pseudo_bytes関数があればその値、ない場合はuniqidを23回ぶん、最後にファイルのフルパスとファイル名、serialize関数の値、microtime関数の値が連結されたものになります。これらの複雑かつランダムな文字列を上記md5関数にて得られた文字列$owner_passに、AES-256じゃない場合は最終的にtcpdf.phpの10811行目で
$this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'].TCPDF_STATIC::$enc_padding, 0, 32);
と、TCPDF_STATIC::$enc_paddingで特殊文字を付加されて最終的にPDFの最大パスワード文字数の32文字となります。
AES-256の場合は最大127文字まで可能ですが、特に付加される文字列なし。すなわちmd5の32文字が_fixAES256Password関数で処理されます。
ここでふと思ったのですが、AES-256じゃない場合、TCPDF_STATIC::$enc_paddingで
\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A
の特殊文字を付加されたとしても先にmd5による文字列が16進数の32文字ぶんあるので、substrでmd5の32文字しか最終的に残りません。ということはowner_passwordには数字とabcdefの16種類しか使われていませんね。このAES-256以外の場合で付加される特殊文字ですが、他の実装でも同じ文字列ですのでAES-256以前のPDFのパスワードでの決まりみたいです。
32文字数としても使われる文字種が16種類じゃ不安な感じもしますが、16の32乗は3.4x1038通り。例えばBitcoinの総ハッシュレートは最近で1.3x1020H/sぐらい。このBitcoinに振り分けられている計算資源を総当りにすべて使ったとして割り算すると2.6x1018秒。すなわち830億年となります。これは全部を総当りしたときの最大時間なので、この半分や最初のほうで当たりを引く可能性もありますが、それでも億年単位ですから十分に強いパスワードを使っていると言っていいでしょう。
AES-256は最大127文字可能なところ、$owner_passを指定しない場合、AES-256以前と同じでmd5で出力される数字とabcdefの16種類による32文字からしかパスワードを生成していません。気になる方はSetProtectionで$owner_passを空白にするのではなく、アルファベット大文字、小文字と記号も含めて自前で作った十分に長い文字列を指定することをおすすめします。ちなみに文字種を数字とabcdefの16種類でも127文字では上記計算資源で2x10125年、宇宙の寿命とされている1400億年が1.4x10114回ぶんかかります。
まあそもそもPDFの場合、権限の処理は実装するアプリケーションに依存しますので、いくら権限パスワードを強力にしてもアプリケーション側で権限を無視すればどうにでもなるんですけどね。Ghostscriptのps2pdfコマンドとかソースを確認ください。