19.05.2018

Шифрация

Хочу показать, как можно слегка улучшить простенькие алгоритмы шифрации на основе обычных, не криптостойких ГПСЧ.
Такой типичный простенький алгоритм выглядит примерно так:
Ei = Ri Ci,
где Ei ‒ зашифрованный символ;
  Ri ‒ i случайное число;
  Ci ‒ i-е исходный символ;
  ‒ обычно операция исключающее ИЛИ.
По большому счету, наверное, все равно, но лучше вместо побитовой операции исключающее ИЛИ использовать полноценное сложение. Использование ИЛИ оправдывается только тем, что на примитивных процессорах эта операция выполняется быстрее сложения. Но сложение дает более непредсказуемые результаты из-за наличия переносов.
В любом случае такой простой алгоритм при наличии открытого и шифрованного теста вскрывается очень легко. Также легко он вскрывается, если есть только несколько шифрованных сообщений, содержащих одинаковые последовательности шифротекста.
В этом случае криптоаналитик может сделать предположение о том, какой открытый текст может содержаться в этом месте сообщения и путем несложного перебора найти ключ.
Например, очень часто в начале текстовых сообщений содержится приветствие, а в конце прощание. Одинаковое приветствие в случае такого алгоритма всегда будет кодироваться одинаково, а прощание только в том случае, если в двух сообщениях оно расположено на одном и том же расстоянии от начала текста.
Рассмотрим сначала, как можно избавиться от проблемы одинаковых суффиксов в исходном тексте.
Для этого воспользуемся тем фактом, что энтропия открытого текста, хоть и не бесконечна, но тем не менее обычно существенно выше нуля. Поэтому некоторую случайность в открытом тексте можно использовать для того, что бы сделать ГПСЧ более непредсказуемым.
Например, обычный ЛКГ можно описать следующим образом:
Xn = a × Xn-1 + c,
где
  Xn, Xn-1 текущее и предыдущее случайное число;
  a, cконстанты метода;
Для использования энтропии шифруемого текста ЛКГ может выглядеть следующим образом:
Xn = a × (Xn-1 + Ln-1)+ c,
где
  Ln-1 код предыдущего символа кодируемого текста;
Добавления подобного смещения в случае неудачных параметров метода может ухудшить свойства генератора с одной стороны. С другой стороны, может их и улучшить. Оба исхода на мой взгляд, равновероятны, поэтому на длинных сообщениях не смогут привести к вырождению шифра.
В результате даже одинаковые суффиксы будут шифроваться по-разному, если префиксы различные.
Тем не менее, остается проблема одинаковых префиксов, например, начальных приветствий в текстовых сообщениях, а также полностью идентичных сообщений, например, служебных сообщений протоколов передачи данных.
Для решения этой проблемы нужно добавить к открытому тексту случайный префикс, после чего эту общий текст подвергнуть процессу шифрации.  После дешифрации случайную строку, естественно, надо удалить.
Таким образом, даже два совершенно одинаковых сообщения будут после шифрации дадут два совершенно разных шифротекста.
Тем не менее, криптоаналитик, при наличии у него как открытого, так и шифрованного текста, может ускорить полный перебор, отбрасывая те варианты ключей, начало дешифрованного текста которых не совпадает с исходным. Для большей криптостойкости алгоритмы было бы более выгодно, что бы в случае полного перебора криптоаналитик был вынужден каждый раз дешифровывать сообщение до конца.
Первоначально у меня возникла идея использовать для этого замену алфавита в исходном сообщении. Тут возможны различные варианты реализации. Одним из них является применение какого-либо алгоритма энтропийного сжатия с динамической моделью над открытым текстом со случайным префиксом. Наличие случайного префикса будет приводить к генерации каждый раз немного разного алфавита даже для одного и того же сообщения, что потребует при криптоанализе перебором полной дешифрации. Но использование энтропийного сжатия достаточно затратная операция, хоть в случае кодирования/декодирования издержки не так уж значительны.
Тем не менее, как-то в очередной раз мучаясь от приступа бессонницы и язвы желудка😄, мне пришла в голову более производительная идея.
Просто нужно, используя тот же ГСПЧ c подмешиванием , с тем же ключом, перемешать открытый текст со случайным префиксом. Это тоже своеобразный метод шифрации, тем не менее, очень слабый. Исходное сообщение относительно легко восстанавливается перебором, после чего криптоаналитик получает ключ на блюдечке с голубой каемочкой.
После чего необходимо зашифровать полученную "кашу" из символов с помощью вышеописанного метода с ГПСЧ с подмешиванием. Такое шифрование в два прохода существенно увеличит криптостойкость метода.
Такой метод использования простых некриптостойких ГПСЧ я предлагаю для "любительского" шифрования. На первый взгляд, получается достаточно неплохо. Но я, естественно, не проводил обзор публикаций по этой теме, так что не могу утверждать, что описанный алгоритм оригинален. Скорее всего, что-то подобное уже приходило кому-нибудь в голову. Если же алгоритм все же нигде и никогда не использовался, то можно утверждать, что он пока никем не вскрыт, по аналогии с неуловимым Джо😄.
Также я не могу ни доказать криптостойкость данного алгоритма, ни опровергнуть ее, банально из-за недостаточности математических знаний. Поэтому, естественно, его нельзя использовать для шифрации критически важной информации.
Скорее данное описание можно трактовать не как заявку на что-то серьезное в области шифрации, а лишь как мое небольшое увлечение, забаву, не более того.

13.05.2018

Криптография

Тема интересная, поэтому решил вынести из комментариев.
Почему в России ГОСТ, а не AES. Не совсем корректно так говорить, потому что российскими ГОСТами покрывается несколько алгоритмов шифрования, как симметричных, так и асимметричных, в то время как AES - это лишь симметричный, хоть и самый современный на текущий момент алгоритм шифрования, используемый правительством США.
Наши ГОСТы не отстают от американских, их постоянно совершенствуют и в общем, они, по крайней мере теоретически, нисколько не уступают зарубежным аналогам.
А вот причины разработки собственных алгоритмов более интересны. По крайней мере одна из них связана с параноидальностью российского общества. Русские власти боятся даже не того, что враг (то бишь американцы) знает уязвимость и молчит. Власти уверены, что в американские алгоритмы шифрования заложены закладки. Впрочем, их опасения не беспочвенны.
Одни из недостатков ГОСТов является большое неудобство их использования разработчиками по сравнению с зарубежными аналогами.
О паранойи. Лирическое отступление. Приведу один несколько отвлеченный от темы пример. Несколько лет назад в российском обществе ходила страшилка о закладке в американских процессорах, позволявшей получить контроль над компьютером по сигналу из США. Какой контроль и по какому сигналу, не уточнялось, но страшилка была достаточно популярна в СМИ. На мой взгляд, как человека, имеющего какое-то отношение к ИТ - это бред сивой кобылы.Тем не менее, как-то зашла об этом речь при общении с коллегами на бывшей уже кафедре ИТМ. Так вот один очень известный в узких кругах сотрудник согласился с этой идеей.
За давностью лет уже не помню, на каком уровне паранойи он остановился. Точно утверждал, что для перехвата управления не нужно сетевое подключение и сетевой интерфейс в компьютере. Вроде бы и компьютер может быть не включен, главное, что бы он был подключен к электричеству. Но вот точно не помню, утверждал ли этот в общем-то очень умный и уважаемый человек, что можно перехватить управление компьютером, если он вообще не подключен к источнику питания. В принципе, батарейка-то там есть! Ой, а ведь не спроста ее туда установили! 😉
А вы верите в такие страшилки?
Вторая волна. Почти насильственное внедрение ГОСТов не только в критически важные области государственной тайны, но и в гражданские приложения порождает вторичную паранойю. Теперь уже многие внутренние пользователи подозревают, что в ГОСТах есть закладки, позволяющие при необходимости ФСБ легко вскрывать шифрованные сообщения. Подогревают ее бессмысленные и беспощадные подзаконные акты к закону о персональных данных, требование хранить персональные данные россиян только на территории России и закон "Яровой".
Всё это оправдывается заботой о нашей безопасности. Ведь в импортных криптосистемах возможны утечки через закладки. А самописные приложения для шифрования без получения лицензии от регулятора так и вообще запрещены, насколько я знаю, под страхом уголовного преследования. Опять же из-за той же заботы. Ведь в самописном приложении вряд ли разработчики озаботятся доказательством его криптостойкости.
Открытый и известный алгоритм. Его преимущества очевидны. Но есть ли недостатки? Да, есть, на мой взгляд. Если уязвимость алгоритма очень трудна для обнаружения, не получится ли так, что те, кто сможет ее все-таки обнаружить, воспользуются этим? Раскрытие таких уязвимостей дело достаточно хлопотное и дорогое, позволить себе такие исследования могут гос. конторы или крупные корпорации. Естественно, вложив крупные средства в работу, они попытаются их отбить в виде финансовых или политических дивидендов.
Абсолютно неуязвимых алгоритмов, насколько я знаю, на практике сейчас нет. Популярные асимметричные алгоритмы построены на предположении об отсутствии  быстрого решения некой математической задачи. Но это не говорит, что такого решения нет в принципе, и возможно, в будущем оно будет найдено.
Создание достаточно мощного квантового компьютера также скорее всего позволит очень легко и быстро вскрывать асимметричные ключи. Что приведет к краху сложившейся системы безопасности в ИТ-технологиях, так как будет потеряна возможность надежной передачи ключей симметричного шифрования.
Самая большая опасность раскрытия стандартных алгоритмов шифрования, на мой взгляд, состоит в том, что, так как алгоритм стандартный и им пользуются все, то команда криптоаналитиков после взлома больше не нужна. Достаточна техников, которые по команде, грубо говоря, нажмут кнопку и расшифруют необходимые данные. Но безнаказанность порождает вседозволенность. Не захочет ли кто из техников узнать, например, интимные пристрастия симпатичной соседки? Или сколько денег на счете у рядом живущего господина? Мотивов может быть сколько угодно. В результате под ударом может оказаться любой человек.
Получается, что можно сколько угодно пользоваться стандартными шифрованными каналами связи, полагаясь на их достаточную защищенность, а потом выяснится, что кто-то нашел (или встроил) уязвимость и уже не один год сливает молчком себе все конфиденциальные данные.
Принцип Керкгоффса. Собственно, я и не утверждал, что алгоритм шифрования должен быть секретным. Я говорил лишь о том, что для попытки вскрытия нестандартного алгоритма требуется гораздо больше усилий. Если для стандартного алгоритма уязвимость найдена, то нет потребности содержать большое количество криптоаналитиков, достаточно техников. С учетом того, что построить относительно неплохой алгоритм не очень сложно, то, при наличии большого количества разных алгоритмов, ресурсов для вскрытия их всех может просто не хватить. Собственно, в этом одна из причин запрета на использования не сертифицированных алгоритмов шифрования в России.
Сам принцип Керкгоффса не исключает использование секретных алгоритмов. В частности, военные любят использовать отличающиеся от стандартных алгоритмы, что затрудняет их вскрытие. Тем не менее, в соответствии с принципом, знание алгоритма не должно упрощать вскрытие шифра. Но его незнание делает вскрытие в принципе невозможным. В этом фишка.
Timing attack. Классная идея. Но у меня сложилось впечатление, что это очень близко к сферическому коню в вакууме. То есть это отлично работает, если удалось установить программу-агент на взламываемый комп. Правда, в этом случае возникает вопрос: не проще ли просто украсть открытый текст, или сам секретный ключ?
Вроде метод хорошо работает и из-за сетевого интерфейса, то есть в случае если наш агент сидит в локальной сети. И даже работает через несколько маршрутизаторов. Вот только авторы обычно обходят стороной вопрос загруженности этой сети и взламываемого сервера. Если сеть и/или сервер сильно загружены пакетами/запросами, то успешность такой атаки очень сильно снижается, так как полученные временные данные оказываются сильно зашумлены случайными помехами.
Но самое главное состоит в том, что эта атака хороша на алгоритмы типа RSA, где используются сложны точные операции, такие как многобитные операции возведения в степень, скорость выполнения которых зависит от сложности ключа.
В случае симметричных алгоритмов, вроде того, что я рассматривал, скорость его работы никак не зависит от сложности ключа, поэтому такой подход для взлома вообще не приемлем.

Заключение. К чему это я все писал?
  1. Легкость создания достаточно стойких систем шифрования делает бессмысленным запрет на не сертифицированные системы. Кому надо - тот легко сделает нестандартный алгоритм шифрации.
  2. Хотел показать, что отсутствие криптостойкости ЛКГ не обязательно приводит к легкости вскрытия шифра. Но об этом в следующий раз.
  3. Даже не скомпрометированный стандартный алгоритм шифрования практически бесполезен в случае наличия СОРМ в ЦОДе. Спецслужбы просто заберут себе уже расшифрованные данные. Именно поэтому их так бесит Телеграмм. Кстати, он до сих пор работает, несмотря на все усилия Роскомнадзора.

06.05.2018

Печальный криптоаналитик

Приведу в своем маленьком бложике свои наивные рассуждения о криптоанализе.
Итак, почему же криптоаналитик печальный? А вот представьте, сидит криптоаналитик на работе, никого не трогает и вообще, примус починяет для разнообразия. А тут ему раз, начальство такое и подсовывает зашифрованный файлик для работы. То есть для его дешифрования.
И ладно бы файлик был зашифрован каким-нибудь простым шифром, типа замены символов. Но так уже давно никто не делает, поэтому успешный статистический анализ не возможен. И вот тут криптоаналитик становится очень печален. Ведь у него есть один шифротекст и всё! Он не знает ни ключ, ни алгоритм шифрования.
В этой ситуации криптоаналитик подобен беспомощному котенку. И помочь ему могут только крепкие, бравые парни-разведчики. Проведя сложную и опасную операцию они стырили у объекта слежки алгоритм шифрования.

А чего его тырить? Чего бы объекту не использовать стандартный? Можно, и даже нужно использовать, если шифруемые данные не слишком уж конфиденциальны. В противном случае выгодней использовать нестандартный алгоритм шифрования. Неочевидная выгода здесь в том, что к стандартному алгоритму шифрования у криптоаналитика может иметься готовый (и, естественно, не опубликованный) метод взлома. Использование индивидуального алгоритма несколько усложнит задачу криптоаналитика, заставив его понервничать. Благо реализация простенького симметричного алгоритма шифрования доступна практически любому студенту-программисту.

Ну так вот, смотрит криптоаналитик этот алгоритм, и видит там банальный ЛКГ. Уже ведь смешно, правда? В каждой википедии написано, что ЛКГ не криптостоек и ломается левой пяткой. Я вот прочитал и тоже подумал так себе, и в самом деле, очень простой, наверное, и правда легко вскрывается.
А потом решил найти готовое решение или подробный алгоритм. И что-то не нашел ничего. Как обычно, наверное, плохо искал.
На поверхности лежит лишь тот факт, что зная последовательность, сгенерированную ЛКГ, можно легко восстановить параметры генератора, и, соответственно, легко вскрыть шифр.
Но у нашего аналитика кроме одного шифрованного файла больше ничего нет. Как же он вскроет шифр?
Похоже, в этой ситуации другого пути, кроме грубой силы нет.
Вы можете мне возразить, что, так как ЛКГ очень прост, то он легко взламывается прямым перебором. Отчасти это так. Но есть у этой простоты и другая сторона. Так как ЛКГ очень прост, то можно очень легко увеличить его разрядность, лишь слегка замедлив процесс шифрации. В то время как взлом грубой силой при этом замедлиться катастрофически.

Когда же криптоаналитик с таким простым шифром станет счастливым? Лишь тогда, когда бравые разведчики добудут ему не только алгоритм, но и пару файлов: открытого текста и соответствующего ему шифротекста.
Вот тогда аналитик вскроет шифр в самом деле практически мгновенно.
Впрочем, радость его будет не долгой. Небольшие изменения в процесс шифрации сделают его работу трудновыполнимой. Но об этом в следующий раз.

А пока расскажите мне, может, я где-то ошибся в своих рассуждениях?

23.03.2018

Случайные числа

всякий, кто питает слабость
к арифметическим методам
получения случайных чисел,
грешен вне всяких сомнений
Джон фон Нейман

Некоторое время назад мне вдруг заинтересовала тема генерации случайных чисел. Уже не вспомню, что явилось причиной, однако я с удивлением обнаружил очень простой и интересный запаздывающий генератор Фибоначчи.
Подобные генераторы вычислительно эффективны, но требовательны к памяти. Однако память сейчас очень дешева и доступна, так что это не проблема.

Красивая идея, красивая реализация. Но на самом деле выясняется, что генераторы Фибоначчи на основе сложения выдают не очень хорошие случайные числа. А вот генераторы на основе умножения просто идеальны. Правда, они всегда генерируют только нечетные числа, поэтому требуют дополнительной, в принципе,очень простой, обработки перед использованием.

Я же попробовал обойти недостатки генератора на основе сложения использованием вот такого составного генератора
Xi = Fib1i⊕*Fib2i⊕+Fib3i⊕.
Как мне кажется, такое сочетание трех независимых генераторов Фибоначчи в духе ЛКГ должно сделать его статистические свойства более хорошими. Одно время было желание затестировать его на самые распространенные ошибки, но не осилил методику 😊. Также у подобного генератора просто огромный период, равный P(Fib1⊕)*P(Fib2⊕)*P(Fib3⊕).

У таких генераторов есть особенность. Их нужно как-то предварительно инициализировать, от качества инициализации зависит и качество генерируемых случайных чисел. Сложность состоит в том, что таких чисел надо достаточно много, в зависимости от параметров запаздывания генератора. Однако если следовать достаточно простым правилам, то подобные генераторы гарантированно после прогона будут выдавать хорошие псевдослучайные последовательности.
В случае генератора на основе сложения необходимо, что бы хотя бы одно число было нечетным. В случае генератора на основе умножения нужно что бы все числа были нечетны, и хотя бы одно больше единицы.
Если же инициализировать буфер генератора псевдослучайными числами с учетом вышеописанных ограничений, то генератор Фибоначчи сразу будет выдавать хорошие результаты.

Сделал генератор, потестил ну и ради смеха сделал к нему web-интерфейс. Бывает, нужно что-то случайное получить, писать каждый раз лень, так что пусть лежит, пару раз уже пригождался.

Ну и по поводу начальной цитаты. Хочу заметить, что те, кто питает слабость к аппаратным методам генерации случайных чисел, грешны не менее. Читал критическую статейку про аппаратный генератор, встроенный в современные процессоры Intel. Масса нюансов и нет гарантии, что он абсолютно точно не имеет каких-то статических значимых паразитных зависимостей.
Одним из идеальных генераторов случайных чисел на текущий момент считается построенный на основе датчиков радиоактивного распада. Однако же не выясниться ли в дальнейшем, что и на нем могут образовываться неслучайные зависимости от каких-либо глобальных процессов, происходящих в далеком космосе? Ведь вроде как по современным квантовым представлениям при перемещении условной частицы из точки А в точку Б она на самом деле проходит по всем возможным траекториям во всей вселенной...
Псевдослучайный же генератор хорош тем, что при желании его всегда может изучить и удостовериться, насколько он хорошо подходит для того или иного применения.

19.02.2018

Паспорта

Недавно узнал, что сервис проверки российских паспортов на недействительность является очень популярным. 😊
Самым актуальным вариантом является сервис МВД, но он закрыт капчей, что не всегда бывает удобно пользователям. Поэтому многие организации скачивают с сайта МВД файл с данными и работают уже с ним.
Традиционно программисты, не мудрствуя лукаво, просто сохраняют данные о паспортах в БД, пользуясь тем SQL-сервером, который используют для основного проекта.
Тут правда, возникает проблемка. Дело в том, что данные о недействительных паспортах достаточно часто обновляются (в среднем пару раз в неделю), а загрузка их в БД занимает время, причем достаточно значительное. Ну просто потому, что сейчас в России имеется более 110 млн. недействительных паспортов.

Меня этот момент заинтересовал, особенно если вспомнить, какой курс я читал, занимаясь преподаванием в СибГИУ.😉
Естественно, я захотел попробовать, с учетом особенности задачи, реализовать ее более оптимально. Идея тут очень простая: объем данных хоть и большой, но оперативная память  сейчас относительно дешевая. Поэтому надо попытаться воспользоваться этой особенностью.
Нужно просто выбрать подходящие для этой задачи структуры данных и их реализовать. Впрочем, по большому счету, особо размышлять над этим вопросом мне не пришлось, так как в одной из самых первых ссылок на тему недействительных паспортов все уже было разложено по полочкам.

Тем не менее, я все же поэкспериментировал с различными вариантами, опишу просто более подробно обоснование выбора структур данных.
Одна из самых быстрых структур для поиска (да и добавления)  данных является хэш-таблицы. Правда, только в том случае, когда ключевое поле данных имеет небольшой размер. Недостатком же хэш-таблиц является коллизии, а также связанная с этим некоторая избыточность памяти. Когда память очень хочется сэкономить (а это именно наш случай), то хэш-таблицы могут быть не самым подходящим вариантом.

Идея использовать в качестве ключа серию и номер паспорта как единое число не очень хороша. Во-первых, потому что ключ получается слишком длинный, а во-вторых, возникает проблема коллизий.
Серия и номер паспорта можно сохранить как пятизначное беззнаковое целое число. Но такого типа среди напрямую поддерживаемых современными процессорами нет. Поэтому либо придется городить свой тип, что чревато некоторой потерей производительности. Либо использовать стандартное восьмибайтовое целое, но при этом иметь значительный перерасход памяти.
Еще больше усугубит проблему памяти необходимость разрешения коллизий, так как выделить массив, покрывающий все пространство возможных значений ключей нереально. Он потребует под себя 5e10 байт, или 46 Гбайт ОЗУ, что несколько многовато для такой простой задачи.
При использовании меньшего размера хэш-таблицы потребуется место для разрешения коллизий. В случае использовании открытой адресации для сохранения приемлемой скорости работы потребуется размер хэш-таблицы примерно на 25% больший количества ключей. Таким образом, потребуется примерно 5*110e6*1.25 байт, или 655 Мбайт ОЗУ. Однако если сформируется достаточно длинная очередь проб для какого-либо подмножества ключей (а скорее всего так и произойдет), то в некоторых случаях производительность будет не очень высокой.
В случае использования закрытой адресации можно ограничиться хэш-таблицей размером в два раза меньше общего количества элементов, но потребуется дополнительная память для связи элементов в линейный список. Таким образом, общий объем памяти можно оценить на текущий момент так: 8*55e6+5*110e6 байт или 944 Мбайт ОЗУ. Т. е. закрытая адресация потребует больше памяти, но даст в среднем несколько более высокую производительность. А нам надо стараться экономить память, особенно в случае закрытой адресации. Во-первых, на вырост, а во-вторых, что бы как можно дольше оставаться в рамках 32-разрядной адресации.

Лирическое отступление. Чем плоха 64-разрядная адресация? Тем, что при активном использовании указателей, на их непродуктивное хранение используется в два раза больше памяти, чем в 32-разрядных системах. Например, если хэш-таблицу с закрытой адресацией перенести в 64-разрядную среду, то на хранение тех же самых данных потребуется уже 16*55e6+5*110e6 байт или 1363 Мбайта ОЗУ. Активное использование длинных указателей также дополнительно загружает шину данных, что немножко снижает производительность.
Поэтому, если объем обрабатываемых данных не превышает 2 Гбайт, то лучше оставаться в рамках 32-разрядного приложения.
Почему 2 Гбайт, а не 4? Этот вопрос лучше задать архитекторам Microsoft. Думаю, ответ имеет ту же природу, что и стародавнее утверждение, что 640 Кбайт хватит всем на всю оставшуюся жизнь.

Кроме варианта использованием одного ключа из серии и номера паспорта, можно использовать два. Сначала, например, ищем по серии, затем по номеру, или наоборот. Давайте посмотрим, к чему это приведет.
Главное, что в этом  случае легко получить идеальную хэш-таблицу, в которой совсем нет коллизий, а поэтому практически не требуется лишняя память.
Номер паспорта отлично укладывается в массив [0..999999], а серия - в массив [0..9999].
Какой же из вариантов взять в качестве первого ключа? Для этого надо понять, какую структуру данных использовать в качестве второго ключа. Очевидно, что обычная хэш-таблица тут будет не очень хороша, так потребует слишком много памяти для реализации. Поэтому в первом приближении лучше использовать обычный сортированный массив, для ускорения операции поиска по вторичному ключу.
Посчитаем требуемый объем памяти. Если в качестве первого ключа взять серию, то объем памяти составит 9999*(4+const)+N*4 (можно ужаться до 3 байт на номер, но сложнее будет реализация, далее увидим, что и так получается неплохо), где const - затраты на организацию 2 ключа, а N - количество паспортов.
Если же в качестве первого ключа использовать номер паспорта, то требуемый объем памяти составит 999999*(4+const)+N*2.
Так как N много больше, чем 999999, то очевидно, что второй вариант гораздо экономичнее использует память. Точнее, при N > (4+const)*495000 будет выгоднее использовать второй вариант. Так как const - число не большее, вряд ли превышающее 20 байт, то второй вариант будет предпочтительным уже при 12 млн. паспортов.
Если рассчитать объем требуемой памяти, то окажется, что для хранения и поиска 110 млн. паспортов потребуется всего 232 Мбайта ОЗУ. В реальности памяти требуется раза так в 2 больше, из-за гранулярности виртуальной памяти и выравнивая границ хранящихся там элементов.

По мере увеличения количества недействительных паспортов, более оптимальной может стать другая структура для второго ключа. Так как нам нужно знать только факт наличия серии для заданного номера, то список серий можно хранить в виде битового массива. Тогда проверка наличии серии будет занимать всего 1 операцию, то есть будет значительно быстрее.
В этом случае для хранения информации уже о всех возможных паспортах потребуется 999999*(4+const+9999/8) или 1215 Мбайт. То есть 32-разрядной системы хватит для заданного формата паспортов навсегда.

Теперь о результатах. На тестах на бюджетном, и, теперь уже достаточно стареньком, процессоре AMD выдает примерно 3 млн. операций поиска что при нахождении паспорта в списке, что при его отсутствии. Загрузка новой информации занимает меньше 5 минут. Думаю, что не один SQL сервер не сможет выдать подобную производительность в таких же условиях.
Для интереса сделал веб-интерфейс к своей системе, хоть подобных сайтов сейчас полным-полно.

А вот если в качестве номера и/или серии паспорта будет использоваться не числа, а строки, то от использования такой организации данных придется отказаться. Это приведет как к увеличению объема требуемой памяти, так и существенному замедлению работы.