Несколько PDF-реализаций оказались уязвимы не из-за слабого шифра, а из-за плохой генерации случайных ключей. Формально документ защищён AES-256, но сам ключ создаётся из такого небольшого набора состояний, что его можно просто перебрать.
В PDF пароль не шифрует содержимое напрямую. Случайный 32-байтовый ключ защищает документ, а уже этот ключ шифруется значением, полученным из пароля. Такая схема должна была повысить безопасность, но она бессмысленна, если «случайный» файл-ключ предсказуем.
Самый яркий случай нашли в MuPDF до версии 1.28.5. Генератор drand48 запускался от текущего времени в секундах, а особенности выбора выходных битов оставляли лишь девять значимых бит состояния. Всего получалось 512 разных потоков, причём одинаковые ключи повторялись каждые 512 секунд. Неоптимизированный Python-скрипт подобрал правильный ключ за 11 миллисекунд — без пользовательского и владельческого пароля.
Foxit PDF Reader вычисляет ключ как SHA-256 от времени, 32 фактически нулевых байтов и константы. Известный блок /Perms позволяет быстро проверять кандидатов. Реализация на Rust перебрала все секунды от 1970 года до настоящего времени менее чем за пять секунд; недавний документ раскрывается за миллисекунды. Похожий код присутствовал ещё в первом публичном коммите PDFium в 2014 году, поэтому проблема могла перейти и в другие редакторы.
OpenPDF и iText используют ARC4, запускаемый от миллисекунд и свободной памяти JVM. Вариантов больше, но криптографически стойким такой источник тоже не является.
Производителей уведомили, MuPDF исправлен. Однако ранее созданные документы задним числом защитить нельзя.
Даже намеренно медленное хеширование пароля в шестой ревизии PDF здесь не помогает: атакующий идёт напрямую к файловому ключу. Исследователи опубликовали дешифраторы для MuPDF и Foxit, чтобы проблему можно было проверить независимо.
А ограничения прав владельца документа всё равно зависят от честности PDF-читалки.