論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
FIDO認証によるパスワードレスログイン実装入門
1. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved.
FIDO認証による
パスワードレスログイン実装入門
HTML5 Conference 2018
ヤフー株式会社
2018/11/25
合路 健人
@kg0r0
2. アジェンダ
Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 2
1. 自己紹介
2. パスワード認証の課題
3. FIDOとは
4. FIDOの技術仕様
5. デモ
6. Web Authenticationフロー
7. まとめ
3. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved.
社内における認証をよりセキュアで使いやすくする取り組み
興味のある方は是非一緒にどうですか??
新卒入社2年目
システム統括本部
プラットフォーム開発本部
アイデンティティー&アクセスマネジメント部
自己紹介
合路 健人
4. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 4
パスワード認証の課題
5. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 5
パスワード認証の課題(利便性)
こんなことはありませんか
認証機会の増加
サービスごとに異なるパスワードを登録
複雑なパスワードの入力操作が不便
6. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 6
パスワード認証の課題(安全性)
Client Server
username + password
DB
DB LeakPhishing
Password List Attack
Dictionary Attack
7. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 7
FIDOとは
8. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 8
FIDO(Fast IDentity Online)
パスワードへの依存度を減らし、利便性と安全性を向上する
Poor Easy
WeakStrong
USABILITY
SECURITY
USABILITYSECURITY
https://www.slideshare.net/FIDOAlliance/fido-83445442https://www.slideshare.net/FIDOAlliance/introduction-to-fido-alliance-66730790
9. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 9
FIDO認証モデル
AuthenticatorUser verification FIDO Authentication
challenge
gesture signature
privatekey
publickey
公開鍵暗号方式による認証
オンラインサービスへの登録時に鍵ペアを生成して登録
client
RP
10. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 10
用語説明
RP(Relying Party)
• ユーザーの登録、認証を⾏うウェブサイト、または、事業者
認証器(Authenticator)
• キーペアの管理を行う
• 外部認証器と内部認証器がある
11. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 11
利便性
認証行為が容易
複数のパスワードを覚える負担を軽減
12. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 12
認証行為が容易
生体認証の導入
• 指紋・虹彩・顔・声紋など
認証器を指定・選択できるポリシー
• 認証器の多様性
• 認証器の選択
13. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 13
複数のパスワードを覚える負担を軽減
パスワード(記憶)
• 本人のみが記憶している情報
認証器(所持)
• 本人のみが所持している物
• 認証器が利用者本人を検証する機能を持つ
14. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 14
安全性
クレデンシャル情報の通信経路
クレデンシャル情報の安全性
認証器の信頼性
15. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 15
クレデンシャル情報の通信経路
パスワード認証
リモート認証
(ユーザー名, パスワード)
ローカル認証
(指紋など)
リモート認証
(署名)
FIDO認証モデル
User Client
User Authenticator client
Relying party
Relying party
16. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 16
クレデンシャル情報の安全性
FIDO Authentication
Kpub1
Kpub2
RPごとに鍵ペアを生成して登録
rpid1(origin)
rpid2(origin)
Relying party1
Relying party2
Client
リスト型攻撃に対する耐性
フィッシングに対する耐性
Authenticator
Kpriv1 Kpriv2
User Presence
17. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 17
クレデンシャル情報の安全性(リスト型攻撃対策)
Authenticator
FIDO Authentication Kpub1
Kpriv1
RPごとに異なる公開鍵を登録
Kpriv2
rpid1(origin)
rpid2(origin)
Relying party1
Relying party2
Client
Kpub2
User Presence
18. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 18
クレデンシャル情報の安全性(フィッシング対策)
FIDO Authentication
Kpriv1
RPごとに異なる秘密鍵を保管
Kpriv2
Client
User Presence
Kpub1Relying party1
Relying party2 Kpub2
Authenticator
Relying party3
19. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 19
認証器の信頼性
Attestation & Metadata
Authenticator
Registration
Attestation privKey Metadata
Authentication Keys
Signed Attestation Object
Relying party
Attestation pubKey
Attestation Certificate
20. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 20
FIDOの技術仕様
21. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 21
FIDOの3つの技術仕様
FIDO UAF(Universal Authentication Framework)
FIDO U2F(Universal 2nd Factor)
FIDO2
22. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 22
FIDO UAF
パスワードレス型(所持+生体など)
主にスマートフォン端末での利用を想定
生体認証などの認証手段によりパスワードレスを実現
https://www.slideshare.net/FIDOAlliance/fido-83445442
23. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 23
FIDO U2F
パスワード補完型(記憶+所持)
主にPC上でWebブラウザの利用を想定した二要素認証
着脱方式と無線方式に対応
https://www.slideshare.net/FIDOAlliance/fido-83445442
24. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 24
UAFとU2F
ユースケースが異なる
• UAF(FIDOクライアント=アプリ)
• U2F(ブラウザから利用できるが二要素認証)
ブラウザからパスワードレス認証を!!
https://www.slideshare.net/FIDOAlliance/fido-83445442
25. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 25
FIDO2
FIDO認証対応プラットフォームの拡大
Web Authentication API
ブラウザからクレデンシャルにアクセスするAPI
CTAP
クライアントと外部認証器間の通信をサポートするプロトコル
https://www.slideshare.net/FIDOAlliance/fido-psd2-solving-the-strong-customer-authentication-challenge-in-europe
26. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 26
Web Authentication API
ブラウザからクレデンシャルにアクセスするAPI
ブラウザの標準インターフェース
Credential Management API の拡張
登録 : navigator.credentials.create()
認証 : navigator.credentials.get()
27. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 27
CTAP
クライアントと外部認証器間の通信をサポートするプロトコル
物理的に異なるクライアントと外部認証器が連携
USB・BLE・NFC などをサポート
USB, BLE, NFC,
Authenticator client
28. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 28
様々な認証器に対応
https://www.slideshare.net/FIDOAlliance/fido-83445442
37. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved.
Web Authentication API
37
登録フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジなど
Attestation response 検証
公開鍵の保存
鍵ペアの生成
Attestation response
チャレンジ・RPの情報・ユーザーの情報
(署名・証明書・公開鍵など)
(署名・証明書・公開鍵など)
38. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 38
navigator.credentials.create()
navigator.credentials.create({
publicKey: {
rp: {
id: "example.com”,
name: "Acme"
},
user: {
id: new Uint8Array(16),
name: "john.p.smith@example.com",
displayName: "John P. Smith "
},
pubKeyCredParams: [{
type: "public-key",
alg: -7
}],
attestation: "direct",
timeout: 60000,
// must be a cryptographically random number sent from a server
challenge: new Uint8Array([
0x8C, 0x0A, 0x26, 0xFF, 0x22, 0x91, 0xC1, 0xE9, ... ]).buffer
}
})
サンプル
39. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 39
Parameter
rp [Object] (必須)
• Relying partyに関する情報
user [Object](必須)
• Credentialが紐づくユーザー情報
challenge[ArrayBuffer] (必須)
• サーバーで生成した乱数
pubKeyCredParams[Object] (必須)
• Credentialのタイプとアルゴリズムの指定(typeはpublic-key固定)
timeout [Int]
• ユーザーの入力待機時間
attestation [String]
• Authenticatorの出どころを検証するかどうか
authenticatorSelection [Object]
• 認証器への要求事項
40. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 40
navigator.credentials.create()
41. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 41
登録フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジなど
Attestation response 検証
公開鍵の保存
鍵ペアの生成
Attestation response
チャレンジ・RPの情報・ユーザーの情報
(署名・証明書・公開鍵など)
(署名・証明書・公開鍵など)
42. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 42
AuthenticatorAttestationResponse
{
// credential identifier on the device
"rawId": "imCIoe8U_N9M1rTGeCqJ96TAu5uqSPa7YUzd ... ",
"id": ” imCIoe8U_N9M1rTGeCqJ96TAu5uqSPa7YUzdh7qq ... ",
// attestation data
"response": {
"clientDataJSON": ”eyJjaGFsbGVuZ2UiOiJJSFdtWjFPa1MydDZLaH ... ”,
"attestationObject": ”o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2 ... "
},
// extensions results struct
"getClientExtensionResults": {},
// type of credential
"type": "public-key”
}
サンプル
43. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 43
clientDataJSON
{
// random number
"challenge": "IHWmZ1OkS2t6KhvX-koNxutkYuMVEunCjYNSXXgAxvU",
// origin of the website
"origin": "http://localhost:3000",
// type of the call.
"type": "webauthn.create”
}
サンプル
44. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 44
attestationObject
CBOR(Concise Binary Object Representation)
• JSONフォーマットをバイナリで表現
• JSONよりもサイズが小さい
const cbor = require('cbor');
. . .
let attestationBuffer =
base64url.toBuffer(webAuthnResponse.response.attestationObject);
let ctapMakeCredResp = cbor.decodeAllSync(attestationBuffer)[0];
公開鍵などを含むCBORでエンコードされたデータ
サンプル
45. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 45
attestationObject
{
// attestation format
"fmt": ”packed",
// raw buffer struct containing user info
"authData": "9569088f1ecee3232954035dbd10d7cae3 ... ",
// attestation statement data
"attStmt": {
// signature
"sig": "3046022100db3162cfa7b5dbd78c46864e5f9 ... ",
// X.509 Certificate Chain
"x5c": [
"3082013c3081e4a003020102020a395187893878526 ... ”
]
}
}
サンプル
公開鍵などを含むCBORでエンコードされたデータ
46. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 46
authData
https://medium.com/@herrjemand/verifying-fido2-responses-4691288c8770
ユーザーの情報を含むバイナリデータ
47. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 47
authDataのパース
let parseMakeCredAuthData = (buffer) => {
let rpIdHash = buffer.slice(0, 32); buffer = buffer.slice(32);
let flagsBuf = buffer.slice(0, 1); buffer = buffer.slice(1);
let flags = flagsBuf[0];
let counterBuf = buffer.slice(0, 4); buffer = buffer.slice(4);
let counter = counterBuf.readUInt32BE(0);
let aaguid = buffer.slice(0, 16); buffer = buffer.slice(16);
let credIDLenBuf = buffer.slice(0, 2); buffer = buffer.slice(2);
let credIDLen = credIDLenBuf.readUInt16BE(0);
let credID = buffer.slice(0, credIDLen); buffer = buffer.slice(credIDLen);
let COSEPublicKey = buffer;
return {rpIdHash, flagsBuf, flags, counter, counterBuf, aaguid, credID, credIDLen, credIDLenBuf,
COSEPublicKey}
}
サンプル
48. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 48
authDataのパース結果
{
// hash of the rpId
rpIdHash: <Buffer 49 96 0d e5 88 0e 8c 68 74 34 17 0f 64 76 60 5b 8f ... >,
// state of the authenticator during the authentication
flags: 65,
flagsBuf: <Buffer 41>,
// 4byte counter
counter: 53,
counterBuf: <Buffer 00 00 00 35>,
// authenticator attestation identifier
aaguid: <Buffer f8 a0 11 f3 8c 0a 4d 15 80 06 17 11 1f 9e dc 7d>,
// credential Identifier
credID: <Buffer de 13 93 92 33 87 5a 0e 89 1b de 60 dc 43 1f 89 8c ... >,
credIDLenBuf: <Buffer 00 40>,
credIDLen: 64,
// COSE encoded public key
COSEPublicKey: <Buffer a5 01 02 03 26 20 01 21 58 20 36 25 71 4a ... >
} サンプル
49. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 49
登録フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジなど
Attestation response 検証
公開鍵の保存
鍵ペアの生成
Attestation response
チャレンジ・RPの情報・ユーザーの情報
(署名・証明書・公開鍵など)
(署名・証明書・公開鍵など)
50. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 50
Verify Attestation
challenge、origin、typeの検証
flagsの検証
signatureの検証
51. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 51
challengeの検証
router.post('/response', (request, response) => {
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
if(clientData.challenge !== request.session.challenge) {
response.json({
'status': 'failed',
'message': 'Challenges don¥'t match!’
})
}
. . .
})
サンプル
clientDataJSON内のchallengeを検証
52. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 52
originの検証
router.post('/response', (request, response) => {
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
. . .
if(clientData.origin !== config.origin) {
response.json({
'status': 'failed',
'message': 'Origins don¥'t match!’
})
}
})
サンプル
clientDataJSON内のoriginを検証
53. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 53
typeの検証
. . .
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
if(clientData.type !== 'webauthn.create') {
. . .
}
})
サンプル
clientDataJSON内のtypeがwebauthn.createであるか確認
54. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 54
Verify Attestation
challenge、origin、typeの検証
flagsの検証
signatureの検証
55. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 55
flagsの検証
AuthenticatorでのUP、UVの結果
UP : User Presence
• ユーザーの存在確認(必須)
UV : User Verification
• ユーザーの認証(任意)
https://slides.com/fidoalliance/jan-2018-fido-seminar-webauthn-tutorial#/
56. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 56
flagsの検証
let authrDataStruct = parseMakeCredAuthData(ctapMakeCredResp.authData);
if(!(authrDataStruct.flags & 0x01))
throw new Error('User was NOT presented durring authentication!');
サンプル
AuthenticatorでのUP、UVの結果
UP : User Presence
• ユーザーの存在確認(必須)
UV : User Verification
• ユーザーの認証(任意)
57. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 57
Verify Attestation
challenge、origin、typeの検証
flagsの検証
signatureの検証
58. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 58
signatureの検証
Attestation Certificateの取得
authDataのパラメーターとclientDataJSONのハッシュ値を連結
attStmtからsignatureを取得
signatureを検証
59. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 59
Attestation Certificateの取得
authData内にあるattSmtのx5c(X.509 Certificate Chain)
PEM形式に変換する
• Base64エンコード
• 64文字ごとに改行コードをいれる
• ヘッダとフッタを入れる
let ASN1toPEM = (pkBuffer) => {
let type;
. . .
type = 'CERTIFICATE';
}
let b64cert = pkBuffer.toString('base64');
let PEMKey = '';
for(let i = 0; i < Math.ceil(b64cert.length / 64); i++) {
let start = 64 * i;
PEMKey += b64cert.substr(start, 64) + '¥n';
}
PEMKey = `-----BEGIN ${type}-----¥n` + PEMKey + `-----END ${type}-----¥n`;
return PEMKey
}
サンプル
60. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 60
signatureの検証
. . .
let attestationBuffer = base64url.toBuffer(attestationObject);
let ctapMakeCredResp = cbor.decodeAllSync(attestationBuffer)[0];
let authrDataStruct = parseMakeCredAuthData(ctapMakeCredResp.authData);
let clientDataHash = hash(base64url.toBuffer(clientDataJSON))
// Attestation Certificateの取得
let PEMCertificate = ASN1toPEM(ctapMakeCredResp.attStmt.x5c[0]);
// authDataのパラメーターとclientDataJSONのハッシュ値を連結
let signatureBase = Buffer.concat([
authrDataStruct.rpIdHash,
authrDataStruct.flagsBuf,
authrDataStruct.counterBuf,
authrDataStruct.aaguid,
authrDataStruct.credIDLenBuf,
authrDataStruct.credID,
authrDataStruct.COSEPublicKey,
clientDataHash
]);
// attStmtからsignatureの取得
let signature = ctapMakeCredResp.attStmt.sig;
// 検証
response.verified = crypto
.createVerify('SHA256')
.update(signatureBase)
.verify(PEMCertificate, signature);
}
サンプル
61. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 61
Verify Attestation
challenge、origin、typeの検証
flagsの検証
signatureの検証
62. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 62
登録成功!!
63. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 63
登録フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジなど
Attestation response 検証
公開鍵の保存
鍵ペアの生成
Attestation response
チャレンジ・RPの情報・ユーザーの情報
(署名・証明書・公開鍵など)
(署名・証明書・公開鍵など)
64. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 64
publicKeyの保存
let verifyAuthenticatorAttestationResponse = (webAuthnResponse) => {
. . .
let authrDataStruct = parseMakeCredAuthData(ctapMakeCredResp.authData);
// COSE PublicKeyをPKCS形式に変換
let publicKey = COSEECDHAtoPKCS(authrDataStruct.COSEPublicKey)
let verified = verifySignature(signature, signatureBase, PEMCertificate)
if(verified) {
// publicKeyなどを保存
response.authrInfo = {
fmt: ’packed',
publicKey: base64url.encode(publicKey),
counter: authrDataStruct.counter,
credID: base64url.encode(authrDataStruct.credID)
}
}
}
return response
}
サンプル
COSE(CBOR Object Signing and Encryption)
• 暗号鍵を表現するためのJSONをCBORエンコードしたフォーマット
• COSEから取得したxとyを連結し、先頭に0x04を加えるとPublicKeyになる
65. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 65
publicKeyの保存
COSE(CBOR Object Signing and Encryption)
• 暗号鍵を表現するためのJSONをCBORエンコードしたフォーマット
• COSEから取得したxとyを連結し、先頭に0x04を加えるとPublicKeyになる
// result of COSE parse
{
1: kty=2,
3: alg=-7,
-1: crv=1,
-2: x,
-3: y,
} サンプル
66. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 66
publicKeyの保存
COSE(CBOR Object Signing and Encryption)
• 暗号鍵を表現するためのJSONをCBORエンコードしたフォーマット
• COSEから取得したxとyを連結し、先頭に0x04を加えるとPublicKeyになる
const cbor = require('cbor');
. . .
let COSEECDHAtoPKCS = (COSEPublicKey) => {
let coseStruct = cbor.decodeAllSync(COSEPublicKey)[0];
let tag = Buffer.from([0x04]);
let x = coseStruct.get(-2);
let y = coseStruct.get(-3);
return Buffer.concat([tag, x, y])
}
サンプル
67. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 67
Web Authentication(認証)
68. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 68
認証フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
69. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 69
実装範囲
Authenticator Client Relying party
Web Authentication API 実装が必要な箇所
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
70. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 70
認証フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
71. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 71
ユーザー名の入力
72. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 72
ユーザー名の送信
fetch('/webauthn/login', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.username.value
})
})
サンプル
73. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 73
challengeの送信
let generateServerGetAssertion = (authenticators) => {
let allowCredentials = [];
for(let authr of authenticators) {
allowCredentials.push({
type: 'public-key',
id: authr.credID,
transports: ['usb', 'nfc', 'ble']
})
}
return {
// random number
challenge: randomBase64URLBuffer(32),
allowCredentials: allowCredentials
}
}
サンプル
74. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved.
Web Authentication API
74
実装範囲
Authenticator Client Relying party
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
77. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 77
navigator.credentials.get()
78. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 78
実装範囲
Authenticator Client Relying party
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
79. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 79
AuthenticatorAssertionResponse
{
// credential identifier on the device
"rawId": "imCIoe8U_N9M1rTGeCqJ96TAu5uqSPa7YUzd ... " ,
"id": "imCIoe8U_N9M1rTGeCqJ96TAu5uqSPa7YUzdh7qq ... ",
// assertion data
"response": {
"authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAALQ",
"signature": "MEUCIQCFOqnsAFZLQmcPt2qSjnCb403SisGEASSjT3fOPuD5JgIgF ...",
"userHandle": "",
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiJDUXF5aUlrQ00yWEtvaHVSdlNqTEFoN ...”
},
// extensions results struct
"getClientExtensionResults": {},
// type of credential
"type": "public-key”
}
サンプル
80. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 80
authenticatorData
https://slides.com/fidoalliance/jan-2018-fido-seminar-webauthn-tutorial#/
ユーザーの情報を含むバイナリデータ
81. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 81
authenticatorDataのパース
let parseGetAssertAuthData = (buffer) => {
let rpIdHash = buffer.slice(0, 32); buffer = buffer.slice(32);
let flagsBuf = buffer.slice(0, 1); buffer = buffer.slice(1);
let flags = flagsBuf[0];
let counterBuf = buffer.slice(0, 4); buffer = buffer.slice(4);
let counter = counterBuf.readUInt32BE(0);
return {rpIdHash, flagsBuf, flags, counter, counterBuf}
}
サンプル
82. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 82
authenticatorDataのパース結果
{
// hash of the rpId
rpIdHash: <Buffer 49 96 0d e5 88 0e 8c 68 74 34 17 0f 64 76 60 5b 8f e4 ae b9
a2 86 32 c7 99 5c f3 ba 83 1d 97 63>,
// state of the authenticator during the authentication
flags: 1,
flagsBuf: <Buffer 01>,
// 4byte counter
counter: 68,
counterBuf: <Buffer 00 00 00 44>
}
サンプル
83. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 83
認証フロー(概略)
Authenticator Client Relying party
ユーザー名
チャレンジやユーザーの情報など
Assertion response
検証
署名の生成
Assertion response
チャレンジ・RPの情報・ユーザーの情報
(署名など)
(署名など)
84. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 84
Verify Assertion
challenge、origin、typeの検証
flagsの検証
signatureの検証
counterの検証と更新
85. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 85
challengeの検証
router.post('/response', (request, response) => {
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
if(clientData.challenge !== request.session.challenge) {
response.json({
'status': 'failed',
'message': 'Challenges don¥'t match!’
})
}
. . .
})
サンプル
clientDataJSONとセッションなどに保存していたchallengeを比較
86. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 86
originの検証
router.post('/response', (request, response) => {
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
. . .
if(clientData.origin !== config.origin) {
response.json({
'status': 'failed',
'message': 'Origins don¥'t match!’
})
}
})
サンプル
clientDataJSONとサーバーのコンフィグなどから取得したoriginを比較
87. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 87
typeの検証
. . .
let webauthnResp = request.body
let clientData =
JSON.parse(base64url.decode(webauthnResp.response.clientDataJSON));
if(clientData.type !== 'webauthn.get') {
. . .
}
})
サンプル
clientDataJSONのtypeがwebauthn.getであるか確認
88. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 88
Verify Assertion
challenge、origin、typeの検証
flagsの検証
signatureの検証
counterの検証と更新
89. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 89
flagsの検証
let authrDataStruct = parseMakeCredAuthData(ctapMakeCredResp.authData);
if(!(authrDataStruct.flags & 0x01))
throw new Error('User was NOT presented durring authentication!');
サンプル
AuthenticatorでのUP、UVの結果を検証
90. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 90
Verify Assertion
challenge、origin、typeの検証
flagsの検証
signatureの検証
counterの検証と更新
91. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 91
signatureの検証
Authenticatorの検索
PublicKeyの取得
authenticatorDataのパラメータとclientDataJSONのハッシュ値を連結
AuthenticatorAssertionResponseからsignatureを取得
signatureを検証
92. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 92
Authenticatorの検索
let findAuthr = (credID, authenticators) => {
for(let authr of authenticators) {
if(authr.credID === credID)
return authr
}
throw new Error(`Unknown authenticator with credID ${credID}!`)
}
サンプル
CredentialIdを元にAuthenticatorを検索する
93. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 93
publicKeyの取得
登録時に保存したpublicKeyを取りだす
PEM形式に変換する
• 26バイトのメタデータ(固定)を付与する
• Base64エンコード
• 64文字ごとに改行コードをいれる
• ヘッダとフッタを入れる
94. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 94
publicKeyの取得
let ASN1toPEM = (pkBuffer) => {
. . .
// 26byteのメタデータを追加
pkBuffer = Buffer.concat([
new Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"),
pkBuffer
]);
type = 'PUBLIC KEY';
. . .
// Base64エンコード
let b64cert = pkBuffer.toString('base64');
let PEMKey = '';
for(let i = 0; i < Math.ceil(b64cert.length / 64); i++) {
let start = 64 * i;
// 改行コードの追加
PEMKey += b64cert.substr(start, 64) + '¥n';
}
// ヘッダとフッタの追加
PEMKey = `-----BEGIN ${type}-----¥n` + PEMKey + `-----END ${type}-----¥n`;
return PEMKey
}
サンプル
95. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 95
signatureの検証
let verifyAuthenticatorAssertionResponse = (webAuthnResponse, authenticators) => {
. . .
let authenticatorData = base64url.toBuffer(webAuthnResponse.response.authenticatorData);
let authrDataStruct = parseGetAssertAuthData(authenticatorData);
let clientDataHash = hash(base64url.toBuffer(webAuthnResponse.response.clientDataJSON))
// authenticatorDataとclientDataJSONのハッシュ値を連結
let signatureBase = Buffer.concat([
authrDataStruct.rpIdHash,
authrDataStruct.flagsBuf,
authrDataStruct.counterBuf,
clientDataHash
]);
// 登録時に保存した公開鍵を取得
let publicKey = ASN1toPEM(base64url.toBuffer(authr.publicKey));
// navigator.credentials.get()の戻り値のsignatureを取得
let signature = base64url.toBuffer(webAuthnResponse.response.signature);
// 検証
response.verified = crypto
.createVerify('SHA256')
.update(signatureBase)
.verify(publicKey, signature);
. . .
}
サンプル
96. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 96
Verify Assertion
challenge、origin、typeの検証
flagsの検証
signatureの検証
counterの検証と更新
97. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 97
counterの検証と更新
let verifyAuthenticatorAssertionResponse = (webAuthnResponse, authenticators) =>
{
. . .
if(response.verified) {
if(response.counter <= authr.counter)
throw new Error('Authr counter did not increase!');
authr.counter = authrDataStruct.counter
}
}
. . .
} サンプル
authenticatorDataのcounterを検証
98. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 98
Verify Assertion
challenge、origin、typeの検証
flagsの検証
signatureの検証
counterの検証と更新
99. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 99
認証成功!!
100. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 100
まとめ
101. まとめ
Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 101
パスワード認証は利便性と安全性に問題
FIDO認証は公開鍵暗号を応用しパスワード認証の課題を解消
FIDO2プロジェクトにより認証対応プラットフォームの拡大
102. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 102
RPのサンプル実装
様々な言語で実装されている
Node.js : https://github.com/fido-alliance/webauthn-demo
Python : https://github.com/duo-labs/py_webauthn
Ruby : https://github.com/cedarcode/webauthn-ruby
Go : https://github.com/duo-labs/webauthn
Java : https://github.com/Yubico/java-webauthn-server
この他にもいっぱい!!
https://github.com/apowers313/fido2-server-demo/
103. Copyright (C) 2018 Yahoo Japan Corporation. All Rights Reserved. 103
参考
• FIDO認証の概要説明
https://www.slideshare.net/FIDOAlliance/fido-83445442?ref=https://fidoalliance.org/presentations/
• Webauthn-isig
http://slides.com/herrjemand/webauthn-isig
• INTRODUCTION TO FIDO ALLIANCE
https://www.slideshare.net/FIDOAlliance/introduction-to-fido-alliance-66730790
• MDN web docs WebAuthentication API
https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API
• Welcome to WebAuthn workshop
https://slides.com/fidoalliance/jan-2018-fido-seminar-webauthn-tutorial#/
• Verifying WebAuthn/FIDO2 responses
https://medium.com/@herrjemand/verifying-fido2-responses-4691288c8770
• Verifying FIDO-U2F Attestation
https://medium.com/@herrjemand/verifying-fido-u2f-attestations-in-fido2-f83fab80c355
• WebAuthn from the relying-party view
https://speakerdeck.com/ynojima/webauthn-from-the-relying-party-view