- Security token डिवाइस के बाहर private key को निकाले बिना डिवाइस के भीतर signing करता है, और यूज़र की भौतिक कार्रवाई मांगता है, इसलिए remote attacker के लिए मनमाना signature बनाना मुश्किल हो जाता है
- इसे SSH authentication, U2F, passwordless local login,
sudo, और git commit signing में इस्तेमाल किया जा सकता है, और आधुनिक laptop व smartphone के built-in security hardware YubiKey की जगह ले सकते हैं
ssh-keygen -t ed25519-sk से बनी “private key” फ़ाइल असली private key नहीं बल्कि token के अंदर मौजूद key की ओर इशारा करने वाला handle होती है, और उसी token से दूसरे कंप्यूटर पर भी वही SSH key file बनाई जा सकती है
- MacBook में secure element को SSH key की तरह सेट करके Touch ID आधारित SSH login संभव हुआ, और git commit signing के लिए file path की जगह
ssh-agent और key:: फ़ॉर्मेट वाले user.signingKey configuration की ज़रूरत पड़ी
- Security token खो जाने पर private key को recover नहीं किया जा सकता, और बार-बार touch करने की आदत usability risk पैदा करती है; Windows laptop में Windows Hello face recognition, fingerprint, या PIN से SSH key उपयोग की पुष्टि कर सकता था
Security token के फ़ायदे और सीमाएँ
-
Remote attack रोकने वाली मूल संरचना
- Security token ऐसा डिवाइस है जो private key/public key pair को अपने भीतर रखता है; public key को आसानी से बाहर निकाला जा सकता है, लेकिन private key को डिवाइस के बाहर न जाने देने के लिए बनाया जाता है
- Sign करने के लिए data packet डिवाइस को भेजा जाता है, फिर उसी private key से डिवाइस के भीतर signature बनता है, और आम तौर पर blinking touch button दबाने जैसी यूज़र की भौतिक कार्रवाई भी ज़रूरी होती है
- इसलिए remote attacker कंप्यूटर तक पहुँच भी जाए, तब भी जब तक यूज़र वास्तविक दुनिया में कोई कार्रवाई न करे, security token मनमाना signature नहीं करेगा; इस वजह से
~/.ssh directory में पूरी SSH private/public key pair को file के रूप में रखने के तरीके से यह बेहतर लगता है
- SoloKeys और Nitrokeys जैसे FOSS firmware चाहने वालों के लिए विकल्प भी मौजूद हैं
- ज़्यादा advanced security token built-in fingerprint reader जैसी biometric authentication सुविधाएँ भी जोड़ते हैं, लेकिन मूल बात यही है कि private key डिवाइस के बाहर नहीं जाती
-
Usability से पैदा होने वाले जोखिम
- अगर यूज़र security token के blink करते ही हर बार उसे दबाने का आदी हो जाए, तो वह malicious request पर भी अनजाने में प्रतिक्रिया दे सकता है
- लगातार signing वाले काम के दौरान token को बार-बार दबाना पड़े, तो एक अतिरिक्त blink request को वास्तव में पहचानना मुश्किल हो सकता है
- Apple और Microsoft smartphone authentication app में हर access request के साथ random number code दिखाकर यूज़र से उसे दर्ज करवाने का तरीका अपनाते हैं, लेकिन यह झंझट भरा है और TOTP इस्तेमाल करने वाले Authy या Google Authenticator की तुलना में security token का usability advantage घटा देता है
-
खो जाने और backup की समस्या
- Security token खो जाने पर उससे जुड़ी private key हमेशा के लिए गायब हो जाती है और उसका backup लेने का कोई तरीका नहीं होता
- कई accounts से lock out होने के जोखिम से बचने के लिए security token खरीदते समय कम से कम 2 token लेकर उन्हें एक ही service में register करना चाहिए
- एक विकल्प BIP 39 जैसा backup/restore तरीका है, जिसमें private key को इंसान द्वारा पढ़े जा सकने वाले शब्दों की सूची में बदलकर लिख लिया जाता है
- अगर private key secure enclave के बाहर जा सकती हो, तो phishing attack के ज़रिए यूज़र को यह शब्द सूची गलत जगह लिखने के लिए फुसलाया भी जा सकता है
- अगर सभी security token खो जाने की संभावना बहुत चिंता पैदा करती है, तो BIP 39 शब्द सूची सिस्टम access वापस पाने के लिए आख़िरी उपाय बन सकती है
SSH और git में security token का उपयोग
-
SSH private key को security token में रखना
- आम तौर पर
ssh-keygen चलाने पर पूरी private key वाली file pair बनती है
- Private key को security token में रखने के लिए Yubico की FIDO/U2F guide के अनुसार libfido2 install करें, फिर security token लगाकर
ssh-keygen -t ed25519-sk चलाएँ
- इस स्थिति में भी file pair बनती है, लेकिन “private key” file असली private key नहीं, बल्कि security token के अंदर मौजूद private key की ओर इशारा करने वाला handle होती है
- उसी security token के साथ
ssh-keygen -t ed25519-sk दोबारा चलाने पर किसी भी कंप्यूटर पर वही private/public key files बनाई जा सकती हैं, इसलिए SSH access किसी खास कंप्यूटर की किसी खास file से नहीं, बल्कि security token के साथ चलता है
-
git authentication और commit signing
- Security token को दबाने वाली लगभग 90% स्थितियाँ git इस्तेमाल करते समय आती हैं
- git forge push और pull के लिए SSH authentication लागू करते हैं, और ऊपर बनी
id_ed25519_sk.pub file upload करके security token key pair को अनुमति दी जा सकती है
- git commit signing के लिए भी SSH key support करता है; GitHub docs की SSH key को signing key की तरह सेट करना गाइड के बाद
git config --global commit.gpgsign true चलाने से सभी commit अपने-आप sign होने लगते हैं
- git forge को commit को आपकी signature के रूप में पहचानने के लिए public key को फिर से upload करना पड़ता है, और यह field आम तौर पर SSH authentication field से अलग होती है
-
Commit signing की असुविधा
- लंबी commit list पर rebase करते समय हर commit को फिर से sign करना पड़ता है
- Fingerprint reader वाले YubiKey में दर्जनों commits को लगातार sign करने पर fingerprint पहचान विफलता दर इतनी अधिक थी कि उसका उपयोग छोड़ना पड़ा
- git के “rebase/amend केंद्रित” wrapper jujutsu में push के समय ही commit sign करने का तरीका मौजूद है
-
Linux local login और sudo
MacBook के secure element को SSH key की तरह इस्तेमाल करना
- USB-C port में security token लगातार लगा रहे, तो वह थोड़ा बाहर निकला हुआ लीवर जैसा बन जाता है, जिससे गलती से गिरने या टकराने पर port और token दोनों को नुकसान हो सकता है
- 2020 M1 MacBook Air पर Arian van Putten की guide के अनुसार built-in security element को SSH key की तरह सेट किया गया
sc_auth create-ctk-identity -l ssh -k p-256-ne -t bio
ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""
- इन commands से
id_ecdsa_sk_rk private/public key file pair बनी, और इन files को ~/.ssh directory में ले जाया गया
- यहाँ भी private key file असली private key नहीं बल्कि डिवाइस के अंदर मौजूद key का handle है, इसलिए इसे सार्वजनिक रूप से paste किया जा सकता है
- Homelab server में public key को authorized key के रूप में जोड़ने के लिए यह command चलाएँ
ssh-copy-id -i ~/.ssh/id_ecdsa_sk_rk.pub <server nickname>
- इसके बाद
~/.ssh/config में यह configuration जोड़ी गई
Host *
IdentityFile ~/.ssh/id_ecdsa_sk_rk
SecurityKeyProvider=/usr/lib/ssh-keychain.dylib
ssh <server nickname> चलाने पर login से पहले macOS अपने-आप fingerprint prompt दिखाता है, और उसके बाद SSH login सामान्य रूप से हो जाता है
MacBook secure element से git commit sign करना
git config --global user.signingKey /Users/ahelwer/.ssh/id_ecdsa_sk_rk सेट करने और .ssh/allowed_signers file अपडेट करने के बाद भी git commit signing तुरंत काम नहीं करती
- git commit signing में fail होता है और
device not found? जैसी error देता है
error: Signing file /var/folders/l5/5wqvq2l10p96wtdtfr6lvrvw0000gn/T//.git_signing_buffer_tmpc4uQgO
Confirm user presence for key ECDSA-SK SHA256:oQDA2SNYb2MoSQcxJVSmWyAeAWPqMp7rxliBRfi87as
Couldn't sign message: device not found?
Signing /var/folders/l5/5wqvq2l10p96wtdtfr6lvrvw0000gn/T//.git_signing_buffer_tmpc4uQgO failed: device not found?
fatal: failed to write commit object
- इसका समाधान
~/.ssh directory की files को सीधे point करने के बजाय ssh-agent का उपयोग करना है
- ऊपर दिए गए tutorial के अनुसार यह command चलाकर key pair को ssh-agent में register किया गया
ssh-add -K -S /usr/lib/ssh-keychain.dylib
- इसके बाद
user.signingKey में file path नहीं, बल्कि ~/.ssh/id_ecdsa_sk_rk.pub की सामग्री के आगे key:: जोड़कर उसी key को ~/.gitconfig में रखना होता है
[user]
name = Andrew Helwer
signingKey = "key::sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGxFEdnIg6ppz+pQCdd1eisjOV4gxrjMv1Y4SbtdLoSm6CJCgPZ6q7lnNyuQQsdnS4/Tllsc656AQL7BO3OS47cAAAAEc3NoOg== ssh:"
- इस setting के बाद MacBook के secure element में मौजूद key से file sign करके GitLab Pages site पर push किया जा सका
Windows और Linux पर आज़माने के नतीजे
- कंपनी द्वारा दिए गए Windows laptop पर भी एक तेज़ प्रयोग किया गया
winget install Microsoft.OpenSSH.preview
ssh-keygen -t ecdsa-sk
- इस command ने भी private/public key file pair बनाई, और SSH connection के समय Windows Hello के standard login flow के ज़रिए face recognition, fingerprint, या PIN में से किसी एक को स्वीकार किया गया
- Linux पर इसी तरह के वास्तविक user presence check के बाद secure element से जुड़े laptop तक पहुँच नहीं होने के कारण demo नहीं किया जा सका
1 टिप्पणियां
Lobste.rs की राय
शानदार लेख है, और सिर्फ यह दिखा देना भी कि यह संभव है, अपने आप में बहुत उपयोगी है
निजी तौर पर मैं इसे चलाने के लिए सही library version नहीं ढूंढ पाया, लेकिन मुझे पता चला कि 1Password 8 SSH keys को सुरक्षित रूप से स्टोर कर सकता है और इसका agent biometric authentication से key unlock को support करता है
इसलिए अब मैं सिर्फ उंगली लगाकर git काम भी कर सकता हूँ और SSH hosts में login भी कर सकता हूँ
गाइड: https://developer.1password.com/docs/ssh/get-started/
यह सिर्फ Mac के लिए लगता है
ऐसे security element वाले Linux system को मैं आज़मा नहीं पाया, और मेरे Linux workstation में V1 TPM है, लेकिन signing operation को सिर्फ असली user presence verification के बाद ही चलने की गारंटी कैसे दी जाए, यह मुझे ठीक से नहीं पता
शायद Framework जैसे Linux laptop वाला कोई इसे आज़मा सके। हो सकता है Asahi पर भी यह सच में काम करे
तो दिए गए private key file के अंदर आखिर होता क्या है?
ssh:वाला हिस्सा, यानी application, passkey के origin के बराबर है और host या domain-specific resident key बनाने में उपयोगी हैउदाहरण के लिए, मैं एक ही physical Yubikey के अंदर भी अलग-अलग purpose के लिए keys को अलग रखने में इसका उपयोग करता हूँ
flagsयह तय करता है कि hardware key को कैसे handle करे [1]. Agent अपनी तरफ से अतिरिक्त constraints भी जोड़ सकता हैतकनीकी रूप से, FIDO key में दूसरे blobs या extensions भी स्टोर किए जा सकते हैं, और पिछली नौकरी में मैंने इसका उपयोग authentication के साथ X.509 public key जैसे auxiliary credentials भेजने के लिए किया था। काफ़ी बढ़िया तरीका है
[1]
outer wrapper में magic value
openssh-key-v1\0,cipher=none,kdf=noneहोता है, इसलिए यह ciphertext नहीं है74-byte public key blob में key type
sk-ssh-ed25519@openssh.com, 32-byte Ed25519 pointfdcce889…03e7852b, और applicationssh:होता है, और यही value SSH और WebAuthn के FIDO credentials को namespace के आधार पर अलग करती हैprivate section 248 bytes का है और
cipher=noneहोने से plaintext है। इसमेंcheckint1 == checkint2 == 0x46744267random value, दोहराया गया key type और public key, applicationssh:, औरflags: 0x01शामिल हैंयह flag
USER_PRESENCE_REQUIREDहै, यानी touch ज़रूरी है लेकिन PIN/user verification नहीं, और यह non-resident key हैkey_handle128-byte opaque credential ID है जिसेauthenticatorGetAssertionमें भेजा जाता है, और device इसे अंदरूनी तौर पर resolve करके Ed25519 seed को restore करता हैइसके अलावा खाली
reserved, commentahelwer@ah-mbair.local, और padding01 02 03हैयह लेख सिर्फ SSH की बात करता लगता है, लेकिन क्या मेरे कंप्यूटर के Secure Enclave या TPM को FIDO2 या U2F key की तरह इस्तेमाल करने का कोई तरीका है?
Passkey भी इसी तरह का एक रूप है, जहाँ हर website के लिए अलग private key इस्तेमाल होती है
यह देखते हुए अजीब लगता है कि hardware से bind की जा सकने वाली asymmetric या HMAC API keys का support ज़्यादा आम क्यों नहीं है
WebAuthn, DBSC(Device-Bound Session Credentials), और OAuth2 DPOP जैसी specs का इस दिशा में और आगे बढ़ना अच्छा लगता है