1 पॉइंट द्वारा GN⁺ 5 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 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

    • Linux system में Pluggable Authentication Module(PAM) के ज़रिए security token को passwordless local login और sudo privilege escalation के लिए इस्तेमाल किया जा सकता है

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 टिप्पणियां

 
GN⁺ 5 시간 전
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 के लिए लगता है

    • मैं काम पर नया Windows laptop इस्तेमाल कर सकता हूँ, इसलिए मैंने OpenSSH को Windows Hello के साथ इस तरह integrate किया
      winget install Microsoft.OpenSSH.preview  
      ssh-keygen -t ecdsa-sk  
      
      इसके बाद यह पहले की तरह काम करता था, और key के साथ कहीं भी SSH connect करते समय standard Windows Hello flow आता था, जहाँ fingerprint reader, face recognition, या PIN में से एक इस्तेमाल कर सकता था
      ऐसे security element वाले Linux system को मैं आज़मा नहीं पाया, और मेरे Linux workstation में V1 TPM है, लेकिन signing operation को सिर्फ असली user presence verification के बाद ही चलने की गारंटी कैसे दी जाए, यह मुझे ठीक से नहीं पता
      शायद Framework जैसे Linux laptop वाला कोई इसे आज़मा सके। हो सकता है Asahi पर भी यह सच में काम करे
    • लगभग ऐसा ही है। Linux या Windows पर TPM2 FIDO emulation layer है या नहीं, यह मुझे नहीं पता
  • तो दिए गए private key file के अंदर आखिर होता क्या है?

    • @wrs ने पहले ही जवाब दे दिया, लेकिन 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]
      #define SSH_SK_USER_PRESENCE_REQD  0x01  
      #define SSH_SK_USER_VERIFICATION_REQD  0x04  
      #define SSH_SK_FORCE_OPERATION    0x10  
      #define SSH_SK_RESIDENT_KEY    0x20  
      
    • Claude के अनुसार, और openssh_key_parser से verify करने पर, संरचना इस तरह है
      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 point fdcce889…03e7852b, और application ssh: होता है, और यही value SSH और WebAuthn के FIDO credentials को namespace के आधार पर अलग करती है
      private section 248 bytes का है और cipher=none होने से plaintext है। इसमें checkint1 == checkint2 == 0x46744267 random value, दोहराया गया key type और public key, application ssh:, और flags: 0x01 शामिल हैं
      यह flag USER_PRESENCE_REQUIRED है, यानी touch ज़रूरी है लेकिन PIN/user verification नहीं, और यह non-resident key है
      key_handle 128-byte opaque credential ID है जिसे authenticatorGetAssertion में भेजा जाता है, और device इसे अंदरूनी तौर पर resolve करके Ed25519 seed को restore करता है
      इसके अलावा खाली reserved, comment ahelwer@ah-mbair.local, और padding 01 02 03 है
    • base64 decoder में डालने पर यह निकलता है

      openssh-key-v1����none���none����������J���sk-ssh-ed25519@openssh.com��� 盘˪<F$KW+���ssh:���FtBgFtBg���sk-ssh-ed25519@openssh.com��� 盘˪<F$KW+���ssh:���fІpF$D8"&0[X 'L=Ev ')BjM]$}rTv6Z+p9O8ݹ%V* f.|қ.%I{9 .W !D"8N ai*W�y53 �������ahelwer@ah-mbair.local
      इसमें key standard version v1, key type sk-ssh-ed25519@openssh.com है, जो किसी कारण दोहराया गया है, और human-readable key name ahelwer@ah-mbair.local भी है
      बाकी शायद OpenSSH flags हैं, जैसे PIN या user presence confirmation की ज़रूरत है या नहीं, और वह handle GUID जिसे OpenSSH challenge के साथ FIDO/U2F API को भेज सकता है
      OpenSSH key type, खासकर sk, देखकर यह निष्कर्ष निकाल सकता है कि यह असली private key नहीं है बल्कि security element को call करना है
      उसके बाद यह SecurityKeyProvider setting या SSH_SK_PROVIDER environment variable को देखकर तय करता है कि security element से बात कराने वाली dynamic library कहाँ से load करनी है

  • यह लेख सिर्फ SSH की बात करता लगता है, लेकिन क्या मेरे कंप्यूटर के Secure Enclave या TPM को FIDO2 या U2F key की तरह इस्तेमाल करने का कोई तरीका है?

    • बिल्कुल, और यह लगभग default configuration में ही काम करना चाहिए
      Passkey भी इसी तरह का एक रूप है, जहाँ हर website के लिए अलग private key इस्तेमाल होती है
  • यह देखते हुए अजीब लगता है कि hardware से bind की जा सकने वाली asymmetric या HMAC API keys का support ज़्यादा आम क्यों नहीं है
    WebAuthn, DBSC(Device-Bound Session Credentials), और OAuth2 DPOP जैसी specs का इस दिशा में और आगे बढ़ना अच्छा लगता है