Ключи доступа: что за чертовщина и почему?

Ключи доступа: что за чертовщина и почему?

Эти вещи называются пароли уверен, делают раунды в эти дни. Они были главной достопримечательностью Конференция W3C TPAC 2022, получили поддержку в Safari 16, находят путь в macOS и iOS, и планируется будущее за менеджерами паролей, такими как 1Password, Они есть уже поддерживается в Android и скоро появятся в Chrome OS и Windows в будущих выпусках.

Гиковские улучшения безопасности ОС не вызывают больших заголовков в сообществе разработчиков интерфейсов, но само собой разумеется, что ключи доступа станут «вещью». И учитывая, как пароли и приложения для паролей влияют на пользовательский опыт таких вещей, как аутентификация и обработка форм, мы, возможно, захотим хотя бы обдумать их, чтобы знать, что нас ждет.

В этом суть этой статьи. Я изучаю и экспериментирую с ключами доступа — и WebAuthn API, на основе которого они созданы — уже некоторое время. Позвольте мне поделиться тем, что я узнал.

Содержание

Терминология

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

  • Проверяющая сторона: сервер, на котором вы будете проходить аутентификацию. В этой статье мы будем использовать слово «сервер» для обозначения доверяющей стороны.
  • Клиент: в нашем случае веб-браузер или операционная система.
  • Аутентификатор: Программные и/или аппаратные устройства, позволяющие генерировать и хранить пары открытых ключей.
  • FIDO: орган открытых стандартов, который также создает спецификации для учетных данных FIDO.
  • WebAuthn: базовый протокол для ключей доступа, также известный как FIDO2 учетные данные или учетные данные FIDO для одного устройства.
  • пароли: WebAuthn, но с облачной синхронизацией (также называемой учетными данными FIDO для нескольких устройств, обнаруживаемыми учетными данными или резидентными учетными данными).
  • Криптография с открытым ключом: Сгенерированная пара ключей, которая включает закрытый и открытый ключи. В зависимости от алгоритма он должен использоваться либо для подписи и проверки, либо для шифрования и дешифрования. Это также известно как асимметричная криптография.
  • ЮАР: Акроним имен создателей, Ривест Шамир и Адель. RSA — это старое, но все еще полезное семейство криптографии с открытым ключом, основанное на факторинге простых чисел.
  • Криптография эллиптических кривых (ECC): Новое семейство криптографии на основе эллиптических кривых.
  • ES256: Открытый ключ эллиптической кривой, использующий алгоритм подписи ECDSA (PDF) С SHA256 для хеширования.
  • РС256: Как и ES256, но использует RSA с RSASSA-PKCS1-v1.5 и SHA256.

Что такое пароли?

Прежде чем мы сможем говорить конкретно о ключах доступа, нам нужно поговорить о другом протоколе, называемом WebAuthn (также известный как FIDO2). Ключи доступа — это спецификация, созданная поверх WebAuthn. WebAuthn позволяет использовать криптографию с открытым ключом для замены паролей. Мы используем какое-то защитное устройство, такое как аппаратный ключ или Модуль Trusted Platform Module (TPM) для создания закрытых и открытых ключей.

Открытый ключ может использовать каждый. Однако закрытый ключ нельзя удалить с устройства, которое его сгенерировало. Это была одна из проблем с WebAuthn; если вы потеряете устройство, вы потеряете доступ.

Passkeys решает эту проблему, обеспечивая облачную синхронизацию ваших учетных данных. Другими словами, то, что вы создаете на своем компьютере, теперь также можно использовать на вашем телефоне (хотя, как ни странно, есть учетные данные для одного устройства).

В настоящее время, на момент написания, только iOS, macOS и Android обеспечивают полную поддержку ключей доступа, синхронизированных с облаком, и даже в этом случае они ограничены используемым браузером. Google и Apple предоставляют интерфейс для синхронизации через свои Менеджер паролей Google и Связка ключей Apple iCloud услуги соответственно.

Как пароли заменяют пароли?

В криптографии с открытым ключом вы можете выполнить то, что известно как подписание. Подписание берет часть данных, а затем пропускает ее через алгоритм подписи с закрытым ключом, где затем ее можно проверить с помощью открытого ключа.

Любой может сгенерировать пару открытых ключей, и она не может быть связана с кем-либо, поскольку любой человек мог сгенерировать ее в первую очередь. Что делает его полезным, так это то, что только данные, подписанные с помощью закрытого ключа, могут быть проверены с помощью открытого ключа. Это та часть, которая заменяет пароль — сервер хранит открытый ключ, и мы входим в систему, подтверждая, что у нас есть другая половина (например, закрытый ключ), подписывая случайный вызов.

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

Больше никаких забытых электронных писем и связанных с ними паролей! Браузер запомнит, какие учетные данные вы использовали для какого веб-сайта — все, что вам нужно сделать, это сделать пару кликов, и вы вошли в систему. Вы можете предоставить дополнительные средства проверки для использования пароля, такие как биометрические данные или пин-код. , но они все еще намного быстрее, чем пароли прошлых лет.

Подробнее о криптографии

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

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

Бывают случаи, когда нам нужно убедиться, что сообщение действительно пришло от его отправителя. В этих случаях мы используем подпись и проверку подписи, чтобы убедиться, что отправитель является тем, за кого он себя выдает (также известно как подлинность). В открытом ключе (также называемом асимметричный) криптография, это обычно делается путем подписания хэша сообщения, так что только открытый ключ может правильно проверить его. Хэш и закрытый ключ отправителя создают подпись после прохождения алгоритма, а затем любой может проверить, что сообщение пришло от отправителя с помощью открытого ключа отправителя.

Как мы получаем доступ к паролям?

Чтобы получить доступ к паролям, нам сначала нужно их где-то сгенерировать и сохранить. Некоторые из этих функций могут быть обеспечены аутентификатором. Ан аутентификатор это любое аппаратное или программное устройство, обеспечивающее возможность генерации криптографического ключа. Подумайте об этих одноразовых паролях, которые вы получаете от Google Authenticator1Passwordили LastPassи др.

Например, средство проверки подлинности программного обеспечения может использовать доверенный платформенный модуль (TPM) или безопасный анклав устройства для создания учетных данных. Затем учетные данные можно хранить удаленно и синхронизировать между устройствами, например ключами доступа. Аппаратный аутентификатор будет чем-то вроде YubiKey, который может генерировать и хранить ключи на самом устройстве.

Чтобы получить доступ к аутентификатору, браузер должен иметь доступ к оборудованию, а для этого нам нужен интерфейс. Интерфейс, который мы здесь используем, — это протокол Client to Authenticator (CTAP). Он позволяет получить доступ к разным аутентификаторам по разным механизмам. Например, мы можем получить доступ к аутентификатору через NFC, USB и Bluetooth, используя CTAP.

Один из наиболее интересных способов использования ключей доступа — подключение телефона через Bluetooth к другому устройству, которое может не поддерживать ключи доступа. Когда устройства сопряжены через Bluetooth, я могу войти в браузер на своем компьютере, используя свой телефон в качестве посредника!

Разница между паролями и WebAuthn

Ключи доступа и ключи WebAuthn различаются по нескольким параметрам. Во-первых, пароли считаются учетными данными для нескольких устройств и могут синхронизироваться между устройствами. Напротив, ключи WebAuthn — это учетные данные для одного устройства — причудливый способ сказать, что вы привязаны к одному устройству для проверки.

Во-вторых, для аутентификации на сервере ключи WebAuthn должны предоставить дескриптор пользователя для входа в систему, после чего allowCredentials list возвращается клиенту с сервера, который сообщает, какие учетные данные можно использовать для входа в систему. Ключи доступа пропускают этот шаг и используют доменное имя сервера, чтобы показать, какие ключи уже привязаны к этому сайту. Вы можете выбрать ключ доступа, связанный с этим сервером, так как он уже известен вашей системе.

В остальном ключи криптографически одинаковы; они отличаются только тем, как они хранятся и какую информацию они используют для запуска процесса входа в систему.

Процесс… в двух словах

Процесс генерации WebAuthn или ключа доступа очень похож: получите запрос от сервера, а затем используйте navigator.credentials.create веб-API для создания пары открытых ключей. Затем отправьте вызов и открытый ключ обратно на сервер для сохранения.

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

У пользователя есть еще один шаг — получить еще один вызов с сервера и использовать navigator.credentials.get API для подписания вызова. Мы отправляем обратно подписанный вызов на сервер, и сервер проверяет вызов, а затем регистрирует нас, если подпись проходит.

Конечно, на каждом шагу есть еще немного. Но обычно именно так мы входим на веб-сайт, используя WebAuthn или пароли.

Мясо и картофель

Парольные ключи используются в два этапа: засвидетельствование и утверждение фазы.

Этап аттестации также можно рассматривать как этап регистрации. Вы зарегистрируетесь с адресом электронной почты и паролем для нового веб-сайта, однако в этом случае мы будем использовать наш пароль.

Фаза утверждения аналогична тому, как вы входите на веб-сайт после регистрации.

засвидетельствование

Passkeys: What the Heck and Why? PlatoBlockchain Data Intelligence. Vertical Search. Ai.
Посмотреть в полном размере

Ассоциация navigator.credentials.create API находится в центре нашего внимания на этапе аттестации. Мы зарегистрированы как новый пользователь в системе и нам нужно сгенерировать новую пару открытых ключей. Однако нам нужно указать, какую пару ключей мы хотим сгенерировать. Это означает, что нам нужно предоставить опции для navigator.credentials.create.

// The `challenge` is random and has to come from the server
const publicKey: PublicKeyCredentialCreationOptions = { challenge: safeEncode(challenge), rp: { id: window.location.host, name: document.title, }, user: { id: new TextEncoder().encode(crypto.randomUUID()), // Why not make it random? name: 'Your username', displayName: 'Display name in browser', }, pubKeyCredParams: [ { type: 'public-key', alg: -7, // ES256 }, { type: 'public-key', alg: -256, // RS256 }, ], authenticatorSelection: { userVerification: 'preferred', // Do you want to use biometrics or a pin? residentKey: 'required', // Create a resident key e.g. passkey }, attestation: 'indirect', // indirect, direct, or none timeout: 60_000,
};
const pubKeyCredential: PublicKeyCredential = await navigator.credentials.create({ publicKey
});
const { id // the key id a.k.a. kid
} = pubKeyCredential;
const pubKey = pubKeyCredential.response.getPublicKey();
const { clientDataJSON, attestationObject } = pubKeyCredential.response;
const { type, challenge, origin } = JSON.parse(new TextDecoder().decode(clientDataJSON));
// Send data off to the server for registration

Мы получим PublicKeyCredential который содержит AuthenticatorAttestationResponse который возвращается после создания. Учетные данные содержат идентификатор сгенерированной пары ключей.

Ответ содержит пару битов полезной информации. Во-первых, в этом ответе есть наш открытый ключ, и нам нужно отправить его на сервер для сохранения. Во-вторых, мы также возвращаем clientDataJSON свойство, которое мы можем декодировать, и оттуда получить обратно typechallengeи origin ключа доступа.

Для аттестации мы хотим подтвердить typechallengeи origin на сервере, а также хранить публичный ключ с его идентификатором, например kid. Мы также можем дополнительно хранить attestationObject если мы хотим. Еще одним полезным свойством для хранения является COSE алгоритм, который определен выше в нашем  PublicKeyCredentialCreationOptions   alg: -7 or alg: -256, чтобы легко проверить любые подписанные вызовы на этапе утверждения.

Утверждение

Passkeys: What the Heck and Why? PlatoBlockchain Data Intelligence. Vertical Search. Ai.
Посмотреть в полном размере

Ассоциация navigator.credentials.get API будет в центре внимания на этапе утверждения. Концептуально, это место, где пользователь входит в веб-приложение после регистрации.

// The `challenge` is random and has to come from the server
const publicKey: PublicKeyCredentialRequestOptions = { challenge: new TextEncoder().encode(challenge), rpId: window.location.host, timeout: 60_000,
};
const publicKeyCredential: PublicKeyCredential = await navigator.credentials.get({ publicKey, mediation: 'optional',
});
const { id // the key id, aka kid
} = pubKeyCredential;
const { clientDataJSON, attestationObject, signature, userHandle } = pubKeyCredential.response;
const { type, challenge, origin } = JSON.parse(new TextDecoder().decode(clientDataJSON));
// Send data off to the server for verification

Мы снова получим PublicKeyCredential с AuthenticatorAssertionResponse на этот раз. Учетные данные снова включают идентификатор ключа.

Мы также получаем typechallengeи origin из clientDataJSON еще раз. В signature теперь включен в ответ, а также authenticatorData. Нам понадобятся те и clientDataJSON чтобы убедиться, что это было подписано закрытым ключом.

Ассоциация authenticatorData включает некоторые свойства, которые стоит отслеживать. Во-первых, это хэш SHA256 источника, который вы используете, расположенный в первых 32 байтах, что полезно для проверки того, что запрос исходит от того же сервера-источника. Во-вторых, signCount, то есть с 33 по 37 байт. Это генерируется аутентификатором и должно сравниваться с его предыдущим значением, чтобы убедиться, что с ключом не происходит ничего подозрительного. Значение всегда должно быть равно 0, если это ключ доступа для нескольких устройств, и должно быть случайным образом больше, чем предыдущее значение signCount, если это ключ доступа для одного устройства.

После того, как вы подтвердили свой логин, вы должны войти в систему — Поздравляю! Ключи доступа — отличный протокол, но с некоторыми оговорками.

Некоторые недостатки

У Passkeys есть много преимуществ, однако на момент написания этой статьи с ним были некоторые проблемы. Во-первых, ключи доступа все еще находятся на ранней стадии поддержки, поскольку в Windows разрешены учетные данные только для одного устройства и очень мало поддержки для систем Linux. Ключи доступа.dev обеспечивает хорошая таблица, похожая на Caniuse этого протокола.

Кроме того, платформы паролей Google и Apple не взаимодействуют друг с другом. Если вы хотите перенести свои учетные данные с телефона Android на iPhone… что ж, пока вам не повезло. Это не значит, что нет совместимости! Вы можете войти на свой компьютер, используя телефон в качестве аутентификатора. Но было бы намного чище, если бы он был встроен в операционную систему и синхронизировался без блокировки на уровне поставщика.

Куда идут дела?

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

Ключи доступа ни в коем случае не поддерживаются только в Интернете. Android и iOS оба будут поддерживать собственные ключи доступа как граждане первого класса. Мы все еще находимся на заре всего этого, но ожидайте, что об этом будут упоминать все больше и больше.

Ведь мы устраняем необходимость в паролях и тем самым делаем мир для него безопаснее!

Полезные ресурсы

Вот еще несколько ресурсов, если вы хотите узнать больше о ключах доступа. Также есть репозиторий и демонстрация, которые я собрал для этой статьи.

Отметка времени:

Больше от CSS хитрости