Безопасность и Криптография
Прошлогодня лекция о безопасности и конфиденциальности была сфокусирована на том, как вы можете обезопасить свой компьютер с точки зрения пользователя. В этом году, мы сфокусируемся на концепциях безопасности и криптографии, которые that are связаны с пониманием инструментов, обсужденных ранее, такие как использование хэш-функции в Git или such as the use of hash functions in Git или функции получения ключей и симметричные/асимметричные криптосистемы в SSH.
Данная лекция не является заменой более полному курсу по безопасности компьютерных систем (6.858) или криптографии (6.857 и 6.875). Не выполняйте задачи в сфере безопасности без формального обучения безопасности. Если вы не эксперт не запускайте свою крипту. Тот же принцип применим и к системной безопасности.
В этой лекции очень неформально (но, как нам кажется, практично) рассматриваются основные понятия криптографии. Данной лекции не будет достаточно, чтобы научить вас как проектировать безопасные системы или криптографические протоколы, но мы надеемся этого будет достаточно, чтобы у вас было общее представление о программах и протоколах вы уже используете.
Энтропия
Энтропия - мера случайности. Это полезно, например, когда мы хотим определить надежность пароля.
В вышеприведенном XKCD комиксе показано, что пароль типа “correcthorsebatterystaple” более безопасен, чем “Tr0ub4dor&3”. Но как можно посчитать что-то вроде такого?
Энтропия измеряется в битах, и когда вы случайно равновероятно выбираем из
множества возможных исходов, энтропия равняется log_2(# of possibilities)
.
Бросок честной монетки дает 1 бит энтропии. Бросок кубика с 6 гранями имеет
~2.58 бита энтропии.
Вам следует считать, что злоумышленник знает модель пароля, но не его случайность (например использование броска кубика для выбора пароля.)
Сколько битов энтропии достаточно? Зависит от модели угроз. Для онлайн угадывания, как в XKCD комиксе, ~40 битов энтропии более чем достаточно. Чтобы быть устойчивым к оффлайн подбору, более сильный пароль необходим (например 80 или больше бит).
Хэш-функции
криптографическая хэш-функция соотносит данные произвольного размера к фиксированному размеру, и имеет несколько специальных свойств. Грубо говоря, интерфейс хэш-функции следующий:
hash(value: array<byte>) -> vector<byte, N> (for some fixed N)
Примером хэш-функции является SHA1,
которая используется в Git. Она соотносит вход произвольного размера к 160-битному выходу (который
может быть представлен как 40 шестнадцатеричных символов). Мы можем попробовать SHA1 хэш-функцию
на входе, используя команду sha1sum
:
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'hello' | sha1sum
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ printf 'Hello' | sha1sum
f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0
Верхнеуровнево, про хэш-функцию можно думать как про функцию, к которой тяжело подобрать обратную, а также функцию, которая выглядит случайной (но является детерменистической) (и это идеальная модель хэш-функции). Хэш-функция имеет следующие свойства:
- Детерминистическая: одинаковый вход приводит к одинаковому выходу.
- Не обратима: сложно найти вход
m
такой чтоhash(m) = h
для фиксированного выходаh
. - Устойчива к выходным колизиям: при входе
m_1
, сложно найти другой входm_2
такой чтоhash(m_1) = hash(m_2)
. - Устойчива к колизиям: сложно найти 2 входа
m_1
иm_2
, такие чтоhash(m_1) = hash(m_2)
(заметьте, что это свойство строже, чем предыдущее).
Заметим: SHA-1 больше не является сильной криптографической хэш-функцией. Вы можете найти таблицу жизни криптографических хэш-функций. Однако рекомендация определенных хэш-функций выходит за пределы данной лекции. Если вы выполняете работу, где выбор хэш-функции имеет значение, вам следует пройти формальное обучение по безопасности/криптографии.
Приложения
- Git, для хранения данных с адресацией по содержимому. Идея хэш-функции является более общим концептом (существуют не криптографические хэш-функции). Почему Git использует криптографическую версию?
- Краткое содержание файла. Программное обеспечение часто можно скачать с (потенциально менее надежных) зеркал, например, ISO-образов Linux, и было бы неплохо не доверять им. Официальные сайты обычно публикуют хэши рядом с ссылками на скачивание (которые ведут на сторонние зеркала), чтобы можно было проверить хэш после скачивания файла.
- Схема обязательства.
Предположим, вы хотите обязаться к определенному значению, но раскрыть само значение позже.
Например, я хочу провести честный бросок монеты “в уме”,
без доверенной общей монеты, которую могли бы видеть две стороны. Я мог бы выбрать значение
r = random()
, а затем поделитьсяh = sha256(r)
. Затем вы могли бы назвать орел или решку (мы договоримся, что четноеr
означает орел, а нечетноеr
- решку). После вашего выбора я могу раскрыть мое значениеr
, и вы можете подтвердить, что я не жульничал, проверив, чтоsha256(r)
совпадает с хешем, который я поделился ранее.
Функция формирования ключа
Понятие, связанное с криптографическими хэшами, Функция формирования ключа (KDF) используются для большого числа приложений, включая генерацию выхода фиксированной длины для использования в качестве ключа в других криптографических алгоритмах. Обычно, KDF специально медленны, для того, чтобы замедлить оффлайн атаки подбором (brute-force attacks).
Приложения
- Создание ключей из ключевых фраз (passphrases) для использования в других криптографических алгоритмах (например, симметричная криптография).
- Сохранение информации о пользователе. Сохранять пароль в текстовом файле плохо; правильный
подход заключается в генерации и сохранении случайной
salt
salt = random()
для каждого пользователя, и сохранениеKDF(password + salt)
; для подтверждения попытки логина используется повторное вычисление KDF при введенном пароле и сохраненном значении salt.
Симметричная криптография
Скрытие сообщений, возможно, первый концепт, который приходит в голову, когда думаешь о криптографии. Симметричная криптография достигает этого со следующим набором функций:
keygen() -> key (this function is randomized)
encrypt(plaintext: array<byte>, key) -> array<byte> (the ciphertext)
decrypt(ciphertext: array<byte>, key) -> array<byte> (the plaintext)
Функция encrypt
имеет свойство, что при данном выходе (ciphertext) сложно
понять без ключа, какой был вход (plaintext). Функция decrypt
имеет очевидное свойство корректности: decrypt(encrypt(m, k), k) = m
.
Пример симметричной криптосистемы, имеющий широкое использование сегодня - AES.
Приложения
- Шифрование файлов для хранения их в облачных сервисах, которым вы не доверяете. Это может быть
скомбинировано с KDF, чтобы вы шифровали ваши файлы с passphrase. Сгенерируйте
key = KDF(passphrase)
, и затем сохранитеencrypt(file, key)
.
Асимметричная криптография
Термин “асимметричнай” относится к наличию 2х ключей с двумя разными ролями. Приватный ключ, как подразумевает имя, предназначен для того, чтобы его держали в приватном месте, в то время как публичный ключ может быть публично распространен и это не повлияет на безопасность (в отличии от распространения ключа в симметричной криптосистеме). Асимметричная криптосистема предоставляет следующий набор функций для шифровки(encrypt)/дешифровки(decrypt) и для подписи(sign)/удостоверения(verify):
keygen() -> (public key, private key) (this function is randomized)
encrypt(plaintext: array<byte>, public key) -> array<byte> (the ciphertext)
decrypt(ciphertext: array<byte>, private key) -> array<byte> (the plaintext)
sign(message: array<byte>, private key) -> array<byte> (the signature)
verify(message: array<byte>, signature: array<byte>, public key) -> bool (whether or not the signature is valid)
Функции encrypt/decrypt имеют свойства похожие на их аналоги в
симметричных системах. Сообщение может быть зашифровано с использованием публичного ключа.
При конкретном выходе (ciphertext), сложно определить вход (plaintext)
без приватного ключа. Функция decrypt имеет свойство корректности:
decrypt(encrypt(m, public key), private key) = m
.
Симметричное и асимметричное шифрование можно сравнить с физическими замками. Симметричная криптосистема похожа на дверной замок: любой с ключом может окрыть его. Асимметричное шифрование похожа на навесной замок с ключем. Вы можете дать открытый замок кому-то (публичный ключ), они положат сообщение в коробку и затем наденут на нее ващ замок, после этого, только вы сможете открыть замок, потому что вы храните ключ при себе (приватный ключ).
Функции sign/verify имеют те же свойства, что и
физические подписи, в том смысле, что трудно подделать подпись. В независимости от
сообщения, без приватного ключа, сложно сделать такую подпись, что
verify(message, signature, public key)
вернет true. И конечно, функция
verify имеет свойство корректности
verify(message, sign(message, private key), public key) = true
.
Приложения
- PGP шифрование сообщений. Люди могут постить свой публичные ключи онлайн (например на сервере PGP или в Keybase). Любой сможет отправить им зашифрованное письмо
- Приватная переписка. Такие приложения как Signal и Keybase используют асимметричные ключу, чтобы создать приватные каналы связи
- Подпись програмного обеспечения. Git может иметь GPG-подписанные коммиты и тэги. С опубликованным публичным ключем, любой может подтвердить оригинальность скачанного програмного обеспечения.
Распределение ключей
Асимметричная криптография - это замечательно, но она имеет большую проблему распространения публичных ключей / соотнесения публичного ключа к реальному человеку Есть много решений этой проблемы. Signal имеет простое решение: доверять при первом использовании, и поддерживать out-of-band обмен публичными ключами (вы подтверждаете “безопасные номера” ваших друзей при личной встрече). PGP имеет другое рещенеи, которое называется web of trust. Keybase имеет еще одно решение, которое называется social proof. Каждая модель имеет свои преимущества; Мы (инструкторы) предпочитаем модель Keybase.
Изучение на примерах
Менеджер паролей
Это инструмент, который каждый должен попробовать использовать (напрмер KeePassXC, pass, и 1Password). Менеджеры паролей делают удобным использование уникальных, случайно сгенерированных паролей с высокой энтропией для каждого из ваших логинов, и они сохраняют все ваши пароли в одном месте, которое зашифрованно с помощью симметричного шифра с ключем, который сгенерирован из passphrase с использованием KDF.
Использование менеджера паролей позволяет вам избежать переиспользования паролей (вы меньше подвержены, если какой-то из веб-сайтов оказался скомпрометированным), использовать высоко энтропийные пароли ( вас сложнее взломать ), а также вам будет неообходимо запоминать только 1 пароль (passphrase).
Двухфакторная аутентификация
Двухфакторная аутентификация (2FA) требует, чтобы вы использовали passphrase (“что-то что вы знаете”) вместе с 2FA аутентификатором (например YubiKey, “что-то что у вас есть”) для того, чтобы защить вас от кражи паролей и фишинговых атак.
Шифрование диска
Полное шифрование диска вашего компьютера - простой способ обезопасить ваши данные в случае, если ваш компьютер будет украден. Вы можете использовать cryptsetup + LUKS на Linux, BitLocker на Windows, или FileVault на macOS. Они зашифруют весь диск с помощью симметричного шифра, с ключем защищенным с помощью passphrase.
Приватные переписки
Используйте Signal или Keybase. Сквозная защита обеспечивается с помощью асимметричного шифрования. Получение публичных ключей ваших контактов самый важный шаг. Если вы хотите высокой степени безопасности, вам надо верифицировать публичные ключи out-of-band (с Signal или Keybase), или довериться социальным доказательствам (Keybase).
SSH
Мы обсудили использование SSH в предыдущих лекциях. Давайте посмотрим на его криптографические аспекты.
Когда вы запускаете ssh-keygen
, он генерирует асимметричную пару
ключей public_key, private_key
. Она генерируется случайно,
используя энтропию, предоставленную операционной системой
(которая складывается из событий в железе и т.д.). Публичный ключ сохраняется
as-is (он публичный, поэтому не надо его шифровать), однако
приватный ключ должен быть зашифрован на диске. ssh-keygen
программа
предлагает пользователю использовать passphrase, и она используется для KDF функции
для генерации ключа, который затем использует для шифровки приватного ключа
симметричным шифром.
При использовании, как только сервер узнает публичный ключ клиента (
сохраняется в файл .ssh/authorized_keys
), подключающийся клиент может доказать a connecting client can prove its идентичность использую асимметричную
подпись. Это исполняется с помощью
challenge-response.
Верхнеуровнево, сервер выбирает случайное число и посылает его клиенту.
Клиент подписывает это сообщение и отсылает подпись обратно на сервер,
который проверяет подпись с записанным публичным ключем. Это доказывает,
что клиент обладает приватным ключем, который соответствует публичному ключу,
записанному на сервере в файле .ssh/authorized_keys
поэтому
сервер позволяет клиенту залогиниться
Источники
- Записи прошлого года: лекция была сфокусирована на безопасности и конфиденциальности пользователя компьютера
- Cryptographic Right Answers: отвечает на вопросы “какую криптографию я должен использовать для X?” для многих различных X.
Упражнения
- Энтропия.
- Предположим пароль был выбран как конкатенация 4 слов из словаря в нижнем регистре,
каждое слово выбрано равновероятно из словаря размера
100,000. Пример такого пароля будет
correcthorsebatterystaple
. Сколько бит энтропии имеет такой пароль? - Рассмотрим другую схему, где пароль выбирается как последовательность
из 8 случайных символов алфавита или цифр (включая нижний
и верхний регистры). Пример:
rg8Ql34g
. Сколько бит энтропии будет в этом случае? - Какой пароль сильнее?
- Предположим, злоумышленник может проверять 10,000 паролей в секунды. В среднем, как много времени уйдет на взлом данных паролей?
- Предположим пароль был выбран как конкатенация 4 слов из словаря в нижнем регистре,
каждое слово выбрано равновероятно из словаря размера
100,000. Пример такого пароля будет
- Криптографические хэш-функции. Скачайте Debian image с
зеркала (например с этого Аргентинского зеркала).
Перепроверьте хэш (например используя
sha256sum
) с хэшем, полученным с оффициального сайта Debian (например этот файл расположенный наdebian.org
, если вы скачале файл по ссылке из Аргентинского зеркала). - Симметричная криптография. Зашифруйте файл с помощью AES, используя
OpenSSL:
openssl aes-256-cbc -salt -in {input filename} -out {output filename}
. Посмотрите содержимое, используяcat
илиhexdump
. Расшифруйте его с помощьюopenssl aes-256-cbc -d -in {input filename} -out {output filename}
и проверьте, что содержимое совпадает с оригиналом, используяcmp
. - Асимметричная криптография.
- Настройте SSH ключи на компьютере, до которого у вас есть доступ. Вместо использования RSA ключей, как в прикрепленном туториале, используйте более безопасные ED25519 ключи. Убедитесь, что ваш приватный ключ зашифрован с passphrase.
- настройте GPG
- Отправьте Anish зашифрованное письмо (public key).
- Подпишите Git коммит с
git commit -S
или создайте подписанный Git тэгgit tag -s
. Проверьте подпись коммитаgit show --show-signature
или тэгаgit tag -v
.
Лицензия CC BY-NC-SA.