Klucze dostępu: co do cholery i dlaczego?

Klucze dostępu: co do cholery i dlaczego?

Te rzeczy tzw klucze dostępu na pewno robią rundy w tych dniach. Stanowiły one główną atrakcję przy ul W3CTPAC 2022, zyskał poparcie w Safari 16, znajdują drogę do macOS i iOSi mają być przyszłość dla menedżerów haseł, takich jak 1Password. Oni są już obsługiwane w Androidzie i wkrótce trafią do Chrome OS i Windows w przyszłych wersjach.

Geekowskie ulepszenia bezpieczeństwa systemu operacyjnego nie trafiają na pierwsze strony gazet w społeczności front-end, ale oczywiste jest, że klucze dostępu będą „czymś”. A biorąc pod uwagę, w jaki sposób hasła i aplikacje do obsługi haseł wpływają na doświadczenia użytkowników w zakresie uwierzytelniania i przetwarzania formularzy, możemy przynajmniej pomyśleć o nich, abyśmy wiedzieli, co nadchodzi.

Taki jest sens tego artykułu. Od jakiegoś czasu studiuję i eksperymentuję z kluczami dostępu — oraz interfejsem API WebAuthn, na którym są one zbudowane. Pozwól, że podzielę się tym, czego się nauczyłem.

Spis treści

Terminologia

Oto obowiązkowa sekcja terminologii, którą będziesz chciał poznać, gdy będziemy się zagłębiać. Podobnie jak większość technologii, klucze dostępu zawierają ezoteryczne słownictwo i akronimy, które często utrudniają zrozumienie. Spróbuję rozwikłać dla ciebie kilka zagadek.

  • Impreza polegająca na: serwer, na którym będziesz uwierzytelniać. W tym artykule użyjemy terminu „serwer”, aby zasugerować Stronę ufającą.
  • Klient: w naszym przypadku przeglądarka internetowa lub system operacyjny.
  • Uwierzytelniacz: Oprogramowanie i/lub urządzenia sprzętowe umożliwiające generowanie i przechowywanie par kluczy publicznych.
  • FIDO: Organ zajmujący się otwartymi standardami, który tworzy również specyfikacje dotyczące poświadczeń FIDO.
  • WebUwierzytelnianie: Podstawowy protokół dla kluczy dostępu, znany również jako FIDO2 poświadczenia lub poświadczenia FIDO pojedynczego urządzenia.
  • Klucze dostępu: WebAuthn, ale z synchronizacją w chmurze (nazywane również poświadczeniami FIDO dla wielu urządzeń, poświadczeniami wykrywalnymi lub poświadczeniami rezydentnymi).
  • Kryptografia klucza publicznego: Wygenerowana para kluczy zawierająca klucz prywatny i klucz publiczny. W zależności od algorytmu powinien być używany do podpisywania i weryfikacji lub szyfrowania i deszyfrowania. Jest to również znane jako kryptografia asymetryczna.
  • RPA: Akronim imion twórców, Rivest Shamir i Adel. RSA to starsza, ale nadal użyteczna rodzina kryptografii klucza publicznego oparta na faktoringu liczb pierwszych.
  • Kryptografia krzywych eliptycznych (ECC): Nowsza rodzina kryptografii na podstawie krzywych eliptycznych.
  • ES256: Klucz publiczny krzywej eliptycznej, który używa algorytmu podpisywania ECDSA (PDF) W SHA256 do haszowania.
  • RS256: Podobnie jak ES256, ale używa RSA z RSASSA-PKCS1-v1.5 i SHA256.

Co to są klucze dostępu?

Zanim będziemy mogli konkretnie porozmawiać o kluczach dostępu, musimy porozmawiać o innym protokole o nazwie WebUwierzytelnianie (znany również jako FIDO2). Klucze dostępu to specyfikacja zbudowana na bazie WebAuthn. WebAuthn umożliwia kryptografię klucza publicznego w celu zastąpienia haseł. Używamy pewnego rodzaju urządzenia zabezpieczającego, takiego jak klucz sprzętowy lub Trusted Platform Module (TPM), do tworzenia kluczy prywatnych i publicznych.

Klucz publiczny jest dostępny dla każdego. Klucza prywatnego nie można jednak usunąć z urządzenia, które go wygenerowało. To był jeden z problemów z WebAuthn; jeśli zgubisz urządzenie, utracisz dostęp.

Passkeys rozwiązuje ten problem, zapewniając synchronizację danych uwierzytelniających w chmurze. Innymi słowy, to, co generujesz na komputerze, może być teraz używane również na telefonie (choć myląco, istnieją również poświadczenia dla jednego urządzenia).

Obecnie, w momencie pisania tego tekstu, tylko iOS, macOS i Android zapewniają pełną obsługę kluczy synchronizowanych w chmurze, a nawet wtedy są one ograniczone przez używaną przeglądarkę. Google i Apple zapewniają interfejs do synchronizacji za ich pośrednictwem Menedżer haseł GoogleBrelok Apple iCloud usługi, odpowiednio.

W jaki sposób klucze dostępu zastępują hasła?

W kryptografii klucza publicznego można wykonać tzw podpisywanie. Podpisywanie pobiera fragment danych, a następnie przepuszcza go przez algorytm podpisywania z kluczem prywatnym, gdzie można go następnie zweryfikować za pomocą klucza publicznego.

Każdy może wygenerować parę kluczy publicznych i nie można jej przypisać żadnej osobie, ponieważ każda osoba mogła ją wygenerować w pierwszej kolejności. Przydatne jest to, że tylko dane podpisane kluczem prywatnym mogą być weryfikowane za pomocą klucza publicznego. To część, która zastępuje hasło — serwer przechowuje klucz publiczny, a my logujemy się, sprawdzając, czy mamy drugą połowę (np. klucz prywatny), podpisując losowe wyzwanie.

Dodatkową korzyścią jest to, że przechowujemy klucze publiczne użytkownika w bazie danych, więc nie ma już obaw o naruszenie haseł dotykające miliony użytkowników. Zmniejsza to liczbę phishingu, naruszeń i wielu innych problemów związanych z bezpieczeństwem, z którymi obecnie boryka się nasz świat zależny od haseł. Jeśli baza danych zostanie naruszona, wszystko, co jest przechowywane w kluczach publicznych użytkownika, czyni ją praktycznie bezużyteczną dla atakującego.

Koniec z zapomnianymi wiadomościami e-mail i powiązanymi z nimi hasłami! Przeglądarka zapamięta, jakich danych użyłeś w której witrynie — wystarczy wykonać kilka kliknięć i jesteś zalogowany. Możesz zapewnić dodatkowy sposób weryfikacji, aby użyć klucza dostępu, na przykład dane biometryczne lub kod PIN , ale wciąż są one znacznie szybsze niż hasła z przeszłości.

Więcej o kryptografii

Kryptografia klucza publicznego polega na posiadaniu klucza prywatnego i publicznego (tzw. pary kluczy). Klucze są generowane razem i mają różne zastosowania. Na przykład klucz prywatny ma być utrzymywany w tajemnicy, a klucz publiczny jest przeznaczony dla każdego, z kim chcesz wymieniać wiadomości.

Jeśli chodzi o szyfrowanie i odszyfrowywanie wiadomości, klucz publiczny odbiorcy jest używany do szyfrowania wiadomości, dzięki czemu tylko klucz prywatny odbiorcy może odszyfrować wiadomość. W żargonie bezpieczeństwa nazywa się to „zapewnieniem poufności”. Nie stanowi to jednak dowodu na to, że nadawca jest tym, za kogo się podaje, ponieważ każdy może potencjalnie użyć klucza publicznego do wysłania komuś zaszyfrowanej wiadomości.

Są przypadki, w których musimy zweryfikować, czy wiadomość rzeczywiście pochodzi od nadawcy. W takich przypadkach używamy podpisu i weryfikacji podpisu, aby upewnić się, że nadawca jest tym, za kogo się podaje (tzw autentyczność). W kluczu publicznym (tzw asymetryczny) kryptografii, odbywa się to zazwyczaj poprzez podpisanie skrótu wiadomości, tak aby tylko klucz publiczny mógł ją poprawnie zweryfikować. Hash i klucz prywatny nadawcy tworzą podpis po przeprowadzeniu go przez algorytm, a następnie każdy może zweryfikować, czy wiadomość pochodzi od nadawcy za pomocą klucza publicznego nadawcy.

Jak uzyskujemy dostęp do kluczy dostępu?

Aby uzyskać dostęp do kluczy dostępu, najpierw musimy je wygenerować i gdzieś przechowywać. Niektóre z tych funkcji można zapewnić za pomocą uwierzytelniania. Jakiś authentator to dowolne urządzenie ze wsparciem sprzętowym lub programowym, które zapewnia możliwość generowania klucza kryptograficznego. Pomyśl o tych jednorazowych hasłach, które otrzymujesz Google Authenticator1Passwordlub LastPass, Między innymi.

Na przykład osoba uwierzytelniająca oprogramowanie może użyć modułu Trusted Platform Module (TPM) lub bezpiecznej enklawy urządzenia do tworzenia poświadczeń. Poświadczenia mogą być następnie przechowywane zdalnie i synchronizowane na różnych urządzeniach, np. klucze dostępu. Autentyfikator sprzętowy byłby czymś w rodzaju a Yubikey, który może generować i przechowywać klucze na samym urządzeniu.

Aby uzyskać dostęp do uwierzytelnienia, przeglądarka musi mieć dostęp do sprzętu, a do tego potrzebujemy interfejsu. Interfejs, którego tutaj używamy, to protokół Client to Authenticator Protocol (CTAP). Umożliwia dostęp do różnych uwierzytelniaczy za pośrednictwem różnych mechanizmów. Na przykład możemy uzyskać dostęp do uwierzytelniacza przez NFC, USB i Bluetooth za pomocą CTAP.

Jednym z ciekawszych sposobów korzystania z kluczy jest połączenie telefonu przez Bluetooth z innym urządzeniem, które może nie obsługiwać kluczy. Kiedy urządzenia są sparowane przez Bluetooth, mogę zalogować się do przeglądarki na moim komputerze, używając telefonu jako pośrednika!

Różnica między kluczami dostępu a WebAuthn

Klucze dostępu i klucze WebAuthn różnią się na kilka sposobów. Po pierwsze, klucze dostępu są uważane za poświadczenia dla wielu urządzeń i można je synchronizować między urządzeniami. Z kolei klucze WebAuthn to poświadczenia dla jednego urządzenia — fantazyjny sposób na powiedzenie, że jesteś przywiązany do jednego urządzenia w celu weryfikacji.

Po drugie, aby uwierzytelnić się na serwerze, klucze WebAuthn muszą zapewnić uchwyt użytkownika do logowania, po czym następuje an allowCredentials z serwera zwracana jest do klienta lista, która informuje, jakimi poświadczeniami można się zalogować. Klucze dostępu pomijają ten krok i używają nazwy domeny serwera, aby pokazać, które klucze są już powiązane z tą witryną. Możesz wybrać klucz dostępu powiązany z tym serwerem, ponieważ jest on już znany Twojemu systemowi.

W przeciwnym razie klucze są kryptograficznie takie same; różnią się jedynie tym, jak są przechowywane i jakich informacji używają do rozpoczęcia procesu logowania.

Proces… w skrócie

Proces generowania WebAuthn lub klucza dostępu jest bardzo podobny: otrzymaj wyzwanie od serwera, a następnie użyj navigator.credentials.create Web API do generowania pary kluczy publicznych. Następnie wyślij wyzwanie i klucz publiczny z powrotem na serwer w celu zapisania.

Po otrzymaniu klucza publicznego i wyzwania serwer sprawdza poprawność wyzwania i sesji, z której zostało utworzone. Jeśli to się sprawdzi, klucz publiczny jest przechowywany w bazie danych, a także wszelkie inne istotne informacje, takie jak identyfikator użytkownika lub dane zaświadczenia.

Użytkownik ma jeszcze jeden krok — pobrać kolejne wyzwanie z serwera i skorzystać z navigator.credentials.get API do podpisania wyzwania. Podpisane wyzwanie odsyłamy z powrotem na serwer, a serwer weryfikuje wyzwanie, a następnie loguje nas, jeśli podpis się powiedzie.

Oczywiście na każdym kroku jest trochę więcej. Ale ogólnie w ten sposób logujemy się do witryny za pomocą WebAuthn lub kluczy dostępu.

Mięso i ziemniaki

Klucze dostępu są używane w dwóch odrębnych fazach: zaświadczenie i twierdzenie Faz.

Faza atestacji może być również traktowana jako faza rejestracji. Rejestrujesz się za pomocą adresu e-mail i hasła do nowej witryny, jednak w tym przypadku używamy naszego klucza dostępu.

Faza potwierdzania jest podobna do tego, jak logujesz się na stronie internetowej po rejestracji.

Zaświadczenie

Klucze dostępu: co do cholery i dlaczego? Inteligencja danych PlatoBlockchain. Wyszukiwanie pionowe. AI.
Zobacz pełny rozmiar

Połączenia navigator.credentials.create API jest głównym przedmiotem naszej fazy atestacji. Jesteśmy zarejestrowani jako nowy użytkownik w systemie i musimy wygenerować nową parę kluczy publicznych. Musimy jednak określić, jaki rodzaj pary kluczy chcemy wygenerować. Oznacza to, że musimy zapewnić opcje 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

Dostaniemy PublicKeyCredential który zawiera AuthenticatorAttestationResponse który powraca po stworzeniu. Poświadczenie zawiera identyfikator wygenerowanej pary kluczy.

Odpowiedź zawiera kilka przydatnych informacji. Po pierwsze, w tej odpowiedzi mamy nasz klucz publiczny i musimy go wysłać na serwer, aby został przechowany. Po drugie, możemy również odzyskać clientDataJSON własność, którą możemy rozszyfrować, a stamtąd odzyskać typechallengeorigin klucza dostępu.

W celu zaświadczenia chcemy zweryfikować plik typechallengeorigin na serwerze, a także przechowywać klucz publiczny wraz z jego identyfikatorem, np. kid. Opcjonalnie możemy również przechowywać plik attestationObject jeśli chcemy. Inną przydatną właściwością do przechowywania jest SZYĆ algorytm, który jest zdefiniowany powyżej w naszym  PublicKeyCredentialCreationOptions w alg: -7 or alg: -256, aby łatwo zweryfikować wszelkie podpisane sprzeciwy w fazie potwierdzania.

twierdzenie

Klucze dostępu: co do cholery i dlaczego? Inteligencja danych PlatoBlockchain. Wyszukiwanie pionowe. AI.
Zobacz pełny rozmiar

Połączenia navigator.credentials.get API będzie głównym tematem fazy potwierdzenia. Koncepcyjnie byłoby to miejsce, w którym użytkownik loguje się do aplikacji internetowej po rejestracji.

// 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

Znowu dostaniemy PublicKeyCredential ze związkiem AuthenticatorAssertionResponse tym razem. Poświadczenie ponownie zawiera identyfikator klucza.

Otrzymujemy również typechallengeorigin z clientDataJSON jeszcze raz. Plik signature jest teraz uwzględniony w odpowiedzi, jak również authenticatorData. Będziemy potrzebować tych i tych clientDataJSON aby sprawdzić, czy zostało to podpisane kluczem prywatnym.

Połączenia authenticatorData zawiera kilka właściwości, które warto śledzić. Pierwszy to skrót SHA256 pochodzenia, którego używasz, znajdujący się w pierwszych 32 bajtach, co jest przydatne do sprawdzenia, czy żądanie pochodzi z tego samego serwera pochodzenia. Drugi to signCount, czyli bajt od 33 do 37. Jest on generowany przez wystawcę uwierzytelnienia i należy go porównać z jego poprzednią wartością, aby upewnić się, że z kluczem nie dzieje się nic podejrzanego. Wartość powinna zawsze wynosić 0, gdy jest to klucz dostępu dla wielu urządzeń, i powinna być losowo większa niż poprzednia wartość signCount, gdy jest to klucz dostępu dla jednego urządzenia.

Po potwierdzeniu loginu powinieneś być zalogowany — gratulacje! Klucze dostępu to całkiem niezły protokół, ale wiąże się z pewnymi zastrzeżeniami.

Niektóre wady

Klucze dostępu mają wiele zalet, jednak w chwili pisania tego tekstu są z nimi pewne problemy. Po pierwsze, klucze dostępu są wciąż dość wczesne pod względem obsługi, z poświadczeniami tylko jednego urządzenia dozwolonymi w systemie Windows i bardzo niewielką obsługą systemów Linux. Klucze dostępu.dev zapewnia ładny stół, który jest trochę jak Caniuse tego protokołu.

Ponadto platformy kluczy Google i Apple nie komunikują się ze sobą. Jeśli chcesz przenieść swoje dane uwierzytelniające z telefonu z Androidem na iPhone'a… cóż, na razie nie masz szczęścia. To nie znaczy, że nie ma interoperacyjności! Możesz zalogować się do komputera, używając telefonu jako uwierzytelnienia. Ale byłoby znacznie czystsze, gdyby zostało wbudowane w system operacyjny i zsynchronizowane bez blokowania go na poziomie dostawcy.

Dokąd zmierzają sprawy?

Jak wygląda protokół kluczy przyszłości? Wygląda całkiem nieźle! Gdy uzyska wsparcie ze strony większej liczby systemów operacyjnych, powinno nastąpić jego wykorzystanie, a zaczniesz widzieć, jak jest coraz częściej używany na wolności. Niektóre menedżerowie haseł będą nawet wspierać ich z pierwszej ręki.

Klucze dostępu nie są w żaden sposób obsługiwane tylko w Internecie. Android i iOS będą obsługiwać natywne klucze dostępu jako obywatele pierwszej klasy. Wciąż jesteśmy na początku tego wszystkiego, ale spodziewamy się, że będzie się o tym wspominać coraz częściej.

W końcu eliminujemy potrzebę stosowania haseł, a czyniąc to, czynimy świat bezpieczniejszym!

Zasoby

Oto kilka dodatkowych zasobów, jeśli chcesz dowiedzieć się więcej o kluczach dostępu. Istnieje również repozytorium i wersja demonstracyjna, które przygotowałem na potrzeby tego artykułu.

Znak czasu:

Więcej z Sztuczki CSS