生物辨識主要的目標是取代像是 OTP,可以做一個可信任的身份認證。
服務的流程大致上是:
- APP 先產生 private/public key
- APP 將 public key 傳到 BE
當要使用身份認證時
- APP 打 API 取得一個 BE 產生的 nonce-1
- APP 產生一個 nonce-2
- APP 用 nonce-1 + nonce-2 + 講好的規則 用 private key 做 signature
- APP 將 nonce-2 以及 signature 傳到 BE,BE 認證沒問題後,回傳一個一次性的 Token
在這個前期 POC 中,我先要試的是,如何產生 private/public 做 signature
Secure Envlave
雖然一直知道 Apple 有用另一個 SoC 做安全保護,但其實一直都沒去看他過XD。感覺官方文件已經寫的淺顯易懂了。
由文件可以知道,會產生一個 SoC 內的 UID,且不會外丟,來確保安全性。
在跟公司同事討論的過程裡,還蠻好奇產生的 private / public key 會存放在哪裡?
看了很多文章,以及實作。感覺應該還是在 KeyChain 內。
確定 Public Key 是可以拿得到。
至於 Private Key 的內容是否拿得到?但目前並沒有這樣的需求,所以可能就等之後有機會再研究看看了。
Apple CryptoKit
iOS 13 之後,Apple 提供了新的 Framework - CryptoKit
看了幾篇文章
https://www.raywenderlich.com/10846296-introducing-cryptokit#toc-anchor-016
https://developer.apple.com/documentation/cryptokit/storing_cryptokit_keys_in_the_keychain
https://medium.com/@alx.gridnev/ios-keychain-using-secure-enclave-stored-keys-8f7c81227f4
使用上系統已經做好了包裝
產生 Private key
1 | // Check that the device has a Secure Enclave |
拿出 Public Key 丟給 BE
1 | // Create public key data |
在測試的過程中我需要將它輸出成 PEM,iOS 14 以後有一個 function pemRepresentation
可以將回傳值直接儲存到檔案。
但 iOS 13 的要如何解決呢?我是用
1 | let pemRepresentation = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE" + privateKey.publicKey.rawRepresentation.base64EncodedString() |
我在寫這篇的時候沒注意到還有 compactRepresentation
不確定印出來的是什麼,之後可能可以試試。
APP 端做 signature
1 | // Produce a signature |
權限控管
以及 可以結合 accessControl & Local Authentication (目前這部分還沒試過,下次再說)
異端驗證
我試圖模擬 API 回傳資料的狀況,需要有下面的資料:
- public 的 PEM
- 明文的 nonce-2
- 算出來的 signature
從手機 APP 複製出來,在 console mode 下用 openSSL 來驗證
reference:
https://www.scottbrady91.com/OpenSSL/Creating-Elliptical-Curve-Keys-using-OpenSSL
https://ithelp.ithome.com.tw/m/articles/10252000
https://link.medium.com/UU7H2Inz7jb
準備資料:
1 | echo -n "i am nonce" > data |
Verify:
1 | openssl dgst -sha256 -verify public.pem -signature sig data |
最後成功就會看到
1 | Verified OK |
ECDSA / ECDH
主要的疑問是來自這兩個參數
https://developer.apple.com/documentation/cryptokit/p256
enum P256.KeyAgreement
A mechanism used to create a shared secret between two users by performing NIST P-256 elliptic curve Diffie Hellman (ECDH) key exchange.
enum P256.Signing
A mechanism used to create or verify a cryptographic signature using the NIST P-256 elliptic curve digital signature algorithm (ECDSA).
看了一輪不太清楚實務上這兩個的差異與用途
後來讀了一些網路文章
https://easonwang.gitbook.io/crypto/ecdsa
https://zhuanlan.zhihu.com/p/66794410
https://github.com/Kitura/BlueECC
以及問了丟神 m(_ _)m,才大概知道
- ECDH 其實是 symmetric key 做金鑰交換
- ECDSA 是要拿來做 signature
所以依據目前的用途,應該選擇 signing 就 OK 了
另外也看到這篇文章這樣提到:
1 | (1)相同密鑰長度下,安全性能更高,如160位ECC已經與1024位RSA、DSA有相同的安全強度。 |
RSA
在這次的研究中,我就沒有實作他了,主要原因是因為 CryptoKit 並沒有 Support RSA,如果真的要實作,則可能需要用舊的 API 來處理。
加上考量上述的好處,或許可以建議後端也用 ECDSA 來處理。
other reference:
https://www.andyibanez.com/posts/cryptokit-not-enough/
https://ithelp.ithome.com.tw/m/articles/10251744