Представьте мир, где вы никогда не забудете пароль, потому что его просто нет. Где фишинг физически невозможен, а взлом аккаунта требует физического доступа к вашему устройству. Это не фантастика – технология уже здесь и называется passkeys.
В 2024-2025 годах Apple, Google и Microsoft синхронизировали усилия и развернули поддержку passkeys на миллиардах устройств. Amazon, PayPal, GitHub, Shopify уже перевели миллионы пользователей на новую систему. Это самая значительная революция в аутентификации за последние 20 лет.
Пароли были изобретены в 1960-х для мэйнфреймов MIT. Проблема в том, что они основаны на знании (something you know), а знание можно:
Статистика 2024-2025:
SMS-коды перехватываются через SIM-swapping. TOTP-коды (Google Authenticator) защищены лучше, но:
Passkeys основаны на стандарте WebAuthn (Web Authentication) и протоколе FIDO2. Это асимметричная криптография в чистом виде.
Когда вы регистрируетесь на сайте с passkey:
Генерация ключей (локально на устройстве):
Приватный ключ (ed25519/ES256) → Secure Enclave/TPM
Публичный ключ → Отправляется серверу
Сервер сохраняет:
Критически важно: Приватный ключ никогда не покидает устройство в классическом FIDO или экосистему провайдера в синхронизированных passkeys (об этом ниже).
При входе на сайт:
Сервер отправляет challenge:
{
"challenge": "случайная_строка_32_байта",
"rpId": "example.com",
"allowCredentials": [{"id": "credential_id_base64"}]
}
Устройство запрашивает биометрию/PIN
Криптографическая подпись:
signature = sign(challenge + rpId + clientData, privateKey)
Сервер проверяет:
verify(signature, challenge + rpId + clientData, publicKey)
Если подпись верна – вы аутентифицированы. Никакого секрета не передаётся по сети.
Технически passkey – это:
{
credentialId: "Base64(random_bytes)",
publicKey: "-----BEGIN PUBLIC KEY-----...",
algorithm: "ES256" или "RS256",
counter: 42, // Защита от replay-атак
userHandle: "user_id_hash"
}
Классический фишинг:
При создании passkey в его параметрах жёстко прописан Relying Party ID (rpId) – домен сайта:
// Passkey для google.com
rpId: "google.com"
Когда браузер получает запрос на аутентификацию:
Это защита на уровне протокола, а не "осторожности пользователя".
Традиционно FIDO2 предполагал привязку ключа к "железу" (YubiKey). Проблема: потеряли ключ – потеряли доступ ко всем аккаунтам.
Apple (2022):
Google (2023):
Microsoft (2024):
Что изменилось:
Атака на синхронизированный passkey требует:
Это на порядки сложнее, чем угадать "Password123", но технически менее безопасно, чем YubiKey.
Для хардкорной защиты: Используйте физические security keys (YubiKey, Titan) без синхронизации. Для всех остальных синхронизированные passkeys – отличный баланс удобства и безопасности.
GitHub включил passkeys в марте 2023. Результаты через год:
Shopify развернул passkeys для покупателей:
Базовый пример регистрации passkey:
// Регистрация
async function registerPasskey() {
const options = {
challenge: Uint8Array.from(randomChallenge, c => c.charCodeAt(0)),
rp: { name: "My Site", id: "example.com" },
user: {
id: Uint8Array.from("user123", c => c.charCodeAt(0)),
name: "user@example.com",
displayName: "John Doe"
},
pubKeyCredParams: [
{ type: "public-key", alg: -7 }, // ES256
{ type: "public-key", alg: -257 } // RS256
],
authenticatorSelection: {
authenticatorAttachment: "platform", // Face ID/Touch ID
userVerification: "required"
}
};
const credential = await navigator.credentials.create({
publicKey: options
});
// Отправляем credential.response на сервер для сохранения
await fetch('/api/passkeys/register', {
method: 'POST',
body: JSON.stringify({
id: credential.id,
publicKey: credential.response.getPublicKey(),
challenge: options.challenge
})
});
}
// Аутентификация
async function authenticatePasskey() {
const options = {
challenge: Uint8Array.from(serverChallenge, c => c.charCodeAt(0)),
rpId: "example.com",
userVerification: "required"
};
const assertion = await navigator.credentials.get({
publicKey: options
});
// КРИТИЧНО: Передаём clientDataJSON для проверки origin
const response = await fetch('/api/passkeys/authenticate', {
method: 'POST',
body: JSON.stringify({
id: assertion.id,
signature: assertion.response.signature,
authenticatorData: assertion.response.authenticatorData,
clientDataJSON: assertion.response.clientDataJSON
})
});
if (response.ok) {
console.log("Authenticated!");
}
}
Критический момент безопасности: Сервер обязан проверить поле origin в clientDataJSON. Без этого возможна подмена домена.
import json
import hashlib
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.exceptions import InvalidSignature
def verify_passkey(credential_id, signature, authenticator_data, client_data_json):
# 0. КРИТИЧНО: Валидация Origin (защита от replay на другом домене)
client_data = json.loads(client_data_json)
if client_data['origin'] != "https://example.com":
raise ValueError("Invalid origin - possible attack!")
if client_data['type'] != "webauthn.get":
raise ValueError("Invalid ceremony type")
# 1. Получаем публичный ключ из БД
public_key_pem = db.get_public_key(credential_id)
public_key = serialization.load_pem_public_key(public_key_pem)
# 2. Формируем данные для верификации
# authData + hash(clientDataJSON)
client_data_hash = hashlib.sha256(client_data_json.encode()).digest()
verification_data = authenticator_data + client_data_hash
# 3. Проверяем подпись
try:
public_key.verify(
signature,
verification_data,
ec.ECDSA(hashes.SHA256())
)
return True
except InvalidSignature:
return False
Почему проверка origin критична: Без неё злоумышленник может:
evil.comexample.comПлюсы: Не ломает UX
Минусы: Медленная адаптация
Плюсы: Быстрая адаптация
Минусы: Недовольство консервативных пользователей
Пользователь на Windows/Linux без passkey:
Под капотом: Bluetooth Low Energy + encrypted channel для передачи assertion.
Вы на чужом компьютере. Нужно войти в Gmail:
Безопасность:
Проблема: Passkeys в iCloud не работают с Android (и наоборот).
Решение:
Вопрос: Что если потеряны все устройства?
Текущие решения:
Проблема: Не решена идеально. Если потеряли всё → можете потерять аккаунт.
Проблема: Как дать доступ к корпоративному аккаунту 5 сотрудникам?
Решение: Каждый создаёт свой passkey. Сервер разрешает multiple passkeys для одного аккаунта.
// На сервере
user.passkeys = [
{ id: "alice_passkey", publicKey: "..." },
{ id: "bob_passkey", publicKey: "..." },
{ id: "charlie_passkey", publicKey: "..." }
]
Проблема: Старые сайты/приложения не поддерживают WebAuthn.
Реальность: В 2025 это становится меньше проблемой. Основные frameworks (Django, Rails, Express.js) имеют готовые библиотеки.
Passwordless everywhere
Корпоративное внедрение
Госсервисы
Текущие алгоритмы (ECDSA) уязвимы к квантовым компьютерам. План:
Изучите WebAuthn:
Используйте библиотеки:
@simplewebauthn/browser + @simplewebauthn/serverwebauthngithub.com/go-webauthn/webauthnТестируйте:
Начните с дополнительного фактора:
ROI расчёт:
Метрики успеха:
Passkeys – это не инкрементальное улучшение, это смена парадигмы. Впервые за 50+ лет мы можем реалистично говорить о мире без паролей.
Что делает passkeys революционными:
Через 5-10 лет мы будем вспоминать пароли так же, как сейчас вспоминаем модемы dial-up – "Помните, как мы набирали 16-символьные комбинации вручную? Как мы вообще с этим жили?"
Технология готова. Инфраструктура развёрнута. Стандарты утверждены. Осталось только начать использовать.
Первый шаг: зайдите прямо сейчас на github.com/settings/security и добавьте passkey. Займёт 30 секунд. После этого вы никогда не захотите возвращаться к паролям.
Будущее без паролей не наступит само – его создают те, кто внедряет новые технологии сегодня. Станьте частью этой революции.
Автор: root@shifry.local