omuronの備忘録

個人的な備忘録

Auth0 の JWT 検証デバッグ sha256 署名編

JWT 検証デバッグ昨日 の続き。
署名が正しいか自力で検証する。

openssl 準備

macOSopenssl コマンドを確認する。

$ openssl version
LibreSSL 2.6.5

OpenSSL が欲しいので brew でいれる。

$ brew instal openssl

... 適当にパスを通して

$ openssl version
OpenSSL 1.1.1g  21 Apr 2020

検証する JWT

テスト用なので見られても困らないので、 token もここで公開します。
これを利用して検証を行う。

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJmNGJWZXlRZWFTMVNieDkxWXVLaSJ9.eyJpc3MiOiJodHRwczovL29tdXJvbi51cy5hdXRoMC5jb20vIiwic3ViIjoiaWV5ZGt1M0Q3QVRDbm5BN2ZHaFJ5anZobjQ0NVNmQ1NAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vb211cm9uLnVzLmF1dGgwLmNvbS9hcGkvdjIvIiwiaWF0IjoxNTkyNTYzMTU3LCJleHAiOjE1OTI2NDk1NTcsImF6cCI6ImlleWRrdTNEN0FUQ25uQTdmR2hSeWp2aG40NDVTZkNTIiwic2NvcGUiOiJyZWFkOmNsaWVudF9ncmFudHMgY3JlYXRlOmNsaWVudF9ncmFudHMgZGVsZXRlOmNsaWVudF9ncmFudHMgdXBkYXRlOmNsaWVudF9ncmFudHMgcmVhZDp1c2VycyB1cGRhdGU6dXNlcnMgZGVsZXRlOnVzZXJzIGNyZWF0ZTp1c2VycyByZWFkOnVzZXJzX2FwcF9tZXRhZGF0YSB1cGRhdGU6dXNlcnNfYXBwX21ldGFkYXRhIGRlbGV0ZTp1c2Vyc19hcHBfbWV0YWRhdGEgY3JlYXRlOnVzZXJzX2FwcF9tZXRhZGF0YSByZWFkOnVzZXJfY3VzdG9tX2Jsb2NrcyBjcmVhdGU6dXNlcl9jdXN0b21fYmxvY2tzIGRlbGV0ZTp1c2VyX2N1c3RvbV9ibG9ja3MgY3JlYXRlOnVzZXJfdGlja2V0cyByZWFkOmNsaWVudHMgdXBkYXRlOmNsaWVudHMgZGVsZXRlOmNsaWVudHMgY3JlYXRlOmNsaWVudHMgcmVhZDpjbGllbnRfa2V5cyB1cGRhdGU6Y2xpZW50X2tleXMgZGVsZXRlOmNsaWVudF9rZXlzIGNyZWF0ZTpjbGllbnRfa2V5cyByZWFkOmNvbm5lY3Rpb25zIHVwZGF0ZTpjb25uZWN0aW9ucyBkZWxldGU6Y29ubmVjdGlvbnMgY3JlYXRlOmNvbm5lY3Rpb25zIHJlYWQ6cmVzb3VyY2Vfc2VydmVycyB1cGRhdGU6cmVzb3VyY2Vfc2VydmVycyBkZWxldGU6cmVzb3VyY2Vfc2VydmVycyBjcmVhdGU6cmVzb3VyY2Vfc2VydmVycyByZWFkOmRldmljZV9jcmVkZW50aWFscyB1cGRhdGU6ZGV2aWNlX2NyZWRlbnRpYWxzIGRlbGV0ZTpkZXZpY2VfY3JlZGVudGlhbHMgY3JlYXRlOmRldmljZV9jcmVkZW50aWFscyByZWFkOnJ1bGVzIHVwZGF0ZTpydWxlcyBkZWxldGU6cnVsZXMgY3JlYXRlOnJ1bGVzIHJlYWQ6cnVsZXNfY29uZmlncyB1cGRhdGU6cnVsZXNfY29uZmlncyBkZWxldGU6cnVsZXNfY29uZmlncyByZWFkOmhvb2tzIHVwZGF0ZTpob29rcyBkZWxldGU6aG9va3MgY3JlYXRlOmhvb2tzIHJlYWQ6YWN0aW9ucyB1cGRhdGU6YWN0aW9ucyBkZWxldGU6YWN0aW9ucyBjcmVhdGU6YWN0aW9ucyByZWFkOmVtYWlsX3Byb3ZpZGVyIHVwZGF0ZTplbWFpbF9wcm92aWRlciBkZWxldGU6ZW1haWxfcHJvdmlkZXIgY3JlYXRlOmVtYWlsX3Byb3ZpZGVyIGJsYWNrbGlzdDp0b2tlbnMgcmVhZDpzdGF0cyByZWFkOnRlbmFudF9zZXR0aW5ncyB1cGRhdGU6dGVuYW50X3NldHRpbmdzIHJlYWQ6bG9ncyByZWFkOnNoaWVsZHMgY3JlYXRlOnNoaWVsZHMgdXBkYXRlOnNoaWVsZHMgZGVsZXRlOnNoaWVsZHMgcmVhZDphbm9tYWx5X2Jsb2NrcyBkZWxldGU6YW5vbWFseV9ibG9ja3MgdXBkYXRlOnRyaWdnZXJzIHJlYWQ6dHJpZ2dlcnMgcmVhZDpncmFudHMgZGVsZXRlOmdyYW50cyByZWFkOmd1YXJkaWFuX2ZhY3RvcnMgdXBkYXRlOmd1YXJkaWFuX2ZhY3RvcnMgcmVhZDpndWFyZGlhbl9lbnJvbGxtZW50cyBkZWxldGU6Z3VhcmRpYW5fZW5yb2xsbWVudHMgY3JlYXRlOmd1YXJkaWFuX2Vucm9sbG1lbnRfdGlja2V0cyByZWFkOnVzZXJfaWRwX3Rva2VucyBjcmVhdGU6cGFzc3dvcmRzX2NoZWNraW5nX2pvYiBkZWxldGU6cGFzc3dvcmRzX2NoZWNraW5nX2pvYiByZWFkOmN1c3RvbV9kb21haW5zIGRlbGV0ZTpjdXN0b21fZG9tYWlucyBjcmVhdGU6Y3VzdG9tX2RvbWFpbnMgdXBkYXRlOmN1c3RvbV9kb21haW5zIHJlYWQ6ZW1haWxfdGVtcGxhdGVzIGNyZWF0ZTplbWFpbF90ZW1wbGF0ZXMgdXBkYXRlOmVtYWlsX3RlbXBsYXRlcyByZWFkOm1mYV9wb2xpY2llcyB1cGRhdGU6bWZhX3BvbGljaWVzIHJlYWQ6cm9sZXMgY3JlYXRlOnJvbGVzIGRlbGV0ZTpyb2xlcyB1cGRhdGU6cm9sZXMgcmVhZDpwcm9tcHRzIHVwZGF0ZTpwcm9tcHRzIHJlYWQ6YnJhbmRpbmcgdXBkYXRlOmJyYW5kaW5nIGRlbGV0ZTpicmFuZGluZyByZWFkOmxvZ19zdHJlYW1zIGNyZWF0ZTpsb2dfc3RyZWFtcyBkZWxldGU6bG9nX3N0cmVhbXMgdXBkYXRlOmxvZ19zdHJlYW1zIGNyZWF0ZTpzaWduaW5nX2tleXMgcmVhZDpzaWduaW5nX2tleXMgdXBkYXRlOnNpZ25pbmdfa2V5cyByZWFkOmxpbWl0cyB1cGRhdGU6bGltaXRzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0.TJyTQQpBq0j6X-Smq8qcNkChbBxAFJT_xFNn8Bc2Uv-UP2KZsGRq801bLKdTgNUz2Wp8FT15i4LHCDwv1qhxpgMN9LdlL3uqNmzFgFcWXHnsToARf9mV3Hyi_QYZSzugrzql4jEZyITOhaxelThcko4FVZ4rL6-Tc4ZoZlkgY_6PgPlRrC5DXZR74-iVoruydPlo3lCnJmQkx4jcNCtqYXXpQsKCjCxoDD_Jzb_x16RMUczxrBqNuo6VSVjsiyPmkisdpsCzgwH8xZIK8dGJ_lDtV26GSOui6Gg9dN5smVGHBuDuaP_WYvAEh8qCkxFE5Z6WOrvvnyvGgNzRquuajA

公開鍵保存

昨日取得した公開鍵を pem ファイルに保存しておく。
pub のほうが名前としては正しいかもだけど)

$ echo "-----BEGIN CERTIFICATE-----
MIIDATCCAemgAwIBAgIJbOX8RffC+u+LMA0GCSqGSIb3DQEBCwUAMB4xHDAaBgNVBAMTE29tdXJvbi51cy5hdXRoMC5jb20wHhcNMjAwNjE5MDgxMjAwWhcNMzQwMjI2MDgxMjAwWjAeMRwwGgYDVQQDExNvbXVyb24udXMuYXV0aDAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5HgBZMeT0iwu24jS9KsDQX85GLwU9kdbLYnuq/IT8LFENrUH7WxUhRaIaS3FvA4T/OCVNdVcJ+nPH++Gq2AlW4rkv+BBp963IICj9dwYbwZFFKeSlUMp2/QYdg2HeBZLJpqM8z6MhC8tejvWfAZ7Pblu3hICP5wyByDzjF9BiDDfrxdugfUGP0RtRe9EK1+51ZhByO8Hss4mIgoyrDOaw6R0vxJYxJCivOpvhhaKuSvEr+rA4tvOEkd3yeC5JqMyzLb/wouF9Md+0foxpzOrgoYnlIR02zcgnzlMHyRbV5Soaj1nokeXhMmIxU5d8BGNgSn+KX3lIexEHj5XchUUUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSSScOdNOvjZ/oiJTaKoRk21MXjVzAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAIKHXiXfdzB7IS2N2oeI2519aoFukgx5gzfeG7lecjFDGo4CVxt8ez1/oF9ZZeIopZ150zEtkWOuU4C0IvkKNqT5MyKBfW38ED23SPXuuuPdqXcmlsL7AaKpNYuFTAE7escc1yJ2ddVGWRh+F+jeyAii+cP+5LxDyz39p3wBTeB9Am0RiXnNG+nXkPtT/y/MJ7H7jqjoK5zUHcveLRvxfp2K2RDpZtzDV2u0L+SzsPPgi27VCaCKchZpih2I9SDvhXVMKXLWm5mir8triXBjfYIYcSOz/UqzgpxJp6H9wzyaIfrxBMnMWsMF82movhwINV9bSXl475FpLVvEcUvMwp0=
-----END CERTIFICATE-----" > pem

JWT の署名を取り出す

JWT の3つめのセクションが、署名になる。
base64 デコードが必要なので、4byte パディングの調整を = で行い、情報を確認。

$ echo "TJyTQQpBq0j6X-Smq8qcNkChbBxAFJT_xFNn8Bc2Uv-UP2KZsGRq801bLKdTgNUz2Wp8FT15i4LHCDwv1qhxpgMN9LdlL3uqNmzFgFcWXHnsToARf9mV3Hyi_QYZSzugrzql4jEZyITOhaxelThcko4FVZ4rL6-Tc4ZoZlkgY_6PgPlRrC5DXZR74-iVoruydPlo3lCnJmQkx4jcNCtqYXXpQsKCjCxoDD_Jzb_x16RMUczxrBqNuo6VSVjsiyPmkisdpsCzgwH8xZIK8dGJ_lDtV26GSOui6Gg9dN5smVGHBuDuaP_WYvAEh8qCkxFE5Z6WOrvvnyvGgNzRquuajA==" | base64 -D | hexdump -C
00000000  4c 9c 93 41 0a 41 ab 48  fa 5f e4 a6 ab ca 9c 36  |L..A.A.H._.....6|
00000010  40 a1 6c 1c 40 14 94 ff  c4 53 67 f0 17 36 52 ff  |@.l.@....Sg..6R.|
00000020  94 3f 62 99 b0 64 6a f3  4d 5b 2c a7 53 80 d5 33  |.?b..dj.M[,.S..3|
00000030  d9 6a 7c 15 3d 79 8b 82  c7 08 3c 2f d6 a8 71 a6  |.j|.=y....</..q.|
00000040  03 0d f4 b7 65 2f 7b aa  36 6c c5 80 57 16 5c 79  |....e/{.6l..W.\y|
00000050  ec 4e 80 11 7f d9 95 dc  7c a2 fd 06 19 4b 3b a0  |.N......|....K;.|
00000060  af 3a a5 e2 31 19 c8 84  ce 85 ac 5e 95 38 5c 92  |.:..1......^.8\.|
00000070  8e 05 55 9e 2b 2f af 93  73 86 68 66 59 20 63 fe  |..U.+/..s.hfY c.|
00000080  8f 80 f9 51 ac 2e 43 5d  94 7b e3 e8 95 a2 bb b2  |...Q..C].{......|
00000090  74 f9 68 de 50 a7 26 64  24 c7 88 dc 34 2b 6a 61  |t.h.P.&d$...4+ja|
000000a0  75 e9 42 c2 82 8c 2c 68  0c 3f c9 cd bf f1 d7 a4  |u.B...,h.?......|
000000b0  4c 51 cc f1 ac 1a 8d ba  8e 95 49 58 ec 8b 23 e6  |LQ........IX..#.|
000000c0  92 2b 1d a6 c0 b3 83 01  fc c5 92 0a f1 d1 89 fe  |.+..............|
000000d0  50 ed 57 6e 86 48 eb a2  e8 68 3d 74 de 6c 99 51  |P.Wn.H...h=t.l.Q|
000000e0  87 06 e0 ee 68 ff d6 62  f0 04 87 ca 82 93 11 44  |....h..b.......D|
000000f0  e5 9e 96 3a bb ef 9f 2b  c6 80 dc d1 aa eb 9a 8c  |...:...+........|
00000100

この内容を jwt.sign に保存する。

$ echo "TJyTQQpBq0j6X-Smq8qcNkChbBxAFJT_xFNn8Bc2Uv-UP2KZsGRq801bLKdTgNUz2Wp8FT15i4LHCDwv1qhxpgMN9LdlL3uqNmzFgFcWXHnsToARf9mV3Hyi_QYZSzugrzql4jEZyITOhaxelThcko4FVZ4rL6-Tc4ZoZlkgY_6PgPlRrC5DXZR74-iVoruydPlo3lCnJmQkx4jcNCtqYXXpQsKCjCxoDD_Jzb_x16RMUczxrBqNuo6VSVjsiyPmkisdpsCzgwH8xZIK8dGJ_lDtV26GSOui6Gg9dN5smVGHBuDuaP_WYvAEh8qCkxFE5Z6WOrvvnyvGgNzRquuajA==" | base64 -D > jwt.sign

OpenSSL でハッシュ値確認

$ openssl rsautl -verify -asn1parse -in jwt.sign -certin -inkey pem
    0:d=0  hl=2 l=  49 cons: SEQUENCE          
    2:d=1  hl=2 l=  13 cons:  SEQUENCE          
    4:d=2  hl=2 l=   9 prim:   OBJECT            :sha256
   15:d=2  hl=2 l=   0 prim:   NULL              
   17:d=1  hl=2 l=  32 prim:  OCTET STRING      
      0000 - 30 55 55 70 f7 d2 4e c4-35 91 de 57 70 b7 4a c5   0UUp..N.5..Wp.J.
      0010 - ab 26 62 d5 58 23 d1 59-3c 3f 31 95 be 1b 35 9e   .&b.X#.Y<?1...5.

最後の2行のハッシュ値が、SHA256の出力結果であることが確認できる。

SHA256 ハッシュの検証

JWT の 「ヘッダー + . + ペイロード」と同じ値か、 shasum -a 256 コマンドを利用して検証を行う。

echo -n "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImJmNGJWZXlRZWFTMVNieDkxWXVLaSJ9.eyJpc3MiOiJodHRwczovL29tdXJvbi51cy5hdXRoMC5jb20vIiwic3ViIjoiaWV5ZGt1M0Q3QVRDbm5BN2ZHaFJ5anZobjQ0NVNmQ1NAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vb211cm9uLnVzLmF1dGgwLmNvbS9hcGkvdjIvIiwiaWF0IjoxNTkyNTYzMTU3LCJleHAiOjE1OTI2NDk1NTcsImF6cCI6ImlleWRrdTNEN0FUQ25uQTdmR2hSeWp2aG40NDVTZkNTIiwic2NvcGUiOiJyZWFkOmNsaWVudF9ncmFudHMgY3JlYXRlOmNsaWVudF9ncmFudHMgZGVsZXRlOmNsaWVudF9ncmFudHMgdXBkYXRlOmNsaWVudF9ncmFudHMgcmVhZDp1c2VycyB1cGRhdGU6dXNlcnMgZGVsZXRlOnVzZXJzIGNyZWF0ZTp1c2VycyByZWFkOnVzZXJzX2FwcF9tZXRhZGF0YSB1cGRhdGU6dXNlcnNfYXBwX21ldGFkYXRhIGRlbGV0ZTp1c2Vyc19hcHBfbWV0YWRhdGEgY3JlYXRlOnVzZXJzX2FwcF9tZXRhZGF0YSByZWFkOnVzZXJfY3VzdG9tX2Jsb2NrcyBjcmVhdGU6dXNlcl9jdXN0b21fYmxvY2tzIGRlbGV0ZTp1c2VyX2N1c3RvbV9ibG9ja3MgY3JlYXRlOnVzZXJfdGlja2V0cyByZWFkOmNsaWVudHMgdXBkYXRlOmNsaWVudHMgZGVsZXRlOmNsaWVudHMgY3JlYXRlOmNsaWVudHMgcmVhZDpjbGllbnRfa2V5cyB1cGRhdGU6Y2xpZW50X2tleXMgZGVsZXRlOmNsaWVudF9rZXlzIGNyZWF0ZTpjbGllbnRfa2V5cyByZWFkOmNvbm5lY3Rpb25zIHVwZGF0ZTpjb25uZWN0aW9ucyBkZWxldGU6Y29ubmVjdGlvbnMgY3JlYXRlOmNvbm5lY3Rpb25zIHJlYWQ6cmVzb3VyY2Vfc2VydmVycyB1cGRhdGU6cmVzb3VyY2Vfc2VydmVycyBkZWxldGU6cmVzb3VyY2Vfc2VydmVycyBjcmVhdGU6cmVzb3VyY2Vfc2VydmVycyByZWFkOmRldmljZV9jcmVkZW50aWFscyB1cGRhdGU6ZGV2aWNlX2NyZWRlbnRpYWxzIGRlbGV0ZTpkZXZpY2VfY3JlZGVudGlhbHMgY3JlYXRlOmRldmljZV9jcmVkZW50aWFscyByZWFkOnJ1bGVzIHVwZGF0ZTpydWxlcyBkZWxldGU6cnVsZXMgY3JlYXRlOnJ1bGVzIHJlYWQ6cnVsZXNfY29uZmlncyB1cGRhdGU6cnVsZXNfY29uZmlncyBkZWxldGU6cnVsZXNfY29uZmlncyByZWFkOmhvb2tzIHVwZGF0ZTpob29rcyBkZWxldGU6aG9va3MgY3JlYXRlOmhvb2tzIHJlYWQ6YWN0aW9ucyB1cGRhdGU6YWN0aW9ucyBkZWxldGU6YWN0aW9ucyBjcmVhdGU6YWN0aW9ucyByZWFkOmVtYWlsX3Byb3ZpZGVyIHVwZGF0ZTplbWFpbF9wcm92aWRlciBkZWxldGU6ZW1haWxfcHJvdmlkZXIgY3JlYXRlOmVtYWlsX3Byb3ZpZGVyIGJsYWNrbGlzdDp0b2tlbnMgcmVhZDpzdGF0cyByZWFkOnRlbmFudF9zZXR0aW5ncyB1cGRhdGU6dGVuYW50X3NldHRpbmdzIHJlYWQ6bG9ncyByZWFkOnNoaWVsZHMgY3JlYXRlOnNoaWVsZHMgdXBkYXRlOnNoaWVsZHMgZGVsZXRlOnNoaWVsZHMgcmVhZDphbm9tYWx5X2Jsb2NrcyBkZWxldGU6YW5vbWFseV9ibG9ja3MgdXBkYXRlOnRyaWdnZXJzIHJlYWQ6dHJpZ2dlcnMgcmVhZDpncmFudHMgZGVsZXRlOmdyYW50cyByZWFkOmd1YXJkaWFuX2ZhY3RvcnMgdXBkYXRlOmd1YXJkaWFuX2ZhY3RvcnMgcmVhZDpndWFyZGlhbl9lbnJvbGxtZW50cyBkZWxldGU6Z3VhcmRpYW5fZW5yb2xsbWVudHMgY3JlYXRlOmd1YXJkaWFuX2Vucm9sbG1lbnRfdGlja2V0cyByZWFkOnVzZXJfaWRwX3Rva2VucyBjcmVhdGU6cGFzc3dvcmRzX2NoZWNraW5nX2pvYiBkZWxldGU6cGFzc3dvcmRzX2NoZWNraW5nX2pvYiByZWFkOmN1c3RvbV9kb21haW5zIGRlbGV0ZTpjdXN0b21fZG9tYWlucyBjcmVhdGU6Y3VzdG9tX2RvbWFpbnMgdXBkYXRlOmN1c3RvbV9kb21haW5zIHJlYWQ6ZW1haWxfdGVtcGxhdGVzIGNyZWF0ZTplbWFpbF90ZW1wbGF0ZXMgdXBkYXRlOmVtYWlsX3RlbXBsYXRlcyByZWFkOm1mYV9wb2xpY2llcyB1cGRhdGU6bWZhX3BvbGljaWVzIHJlYWQ6cm9sZXMgY3JlYXRlOnJvbGVzIGRlbGV0ZTpyb2xlcyB1cGRhdGU6cm9sZXMgcmVhZDpwcm9tcHRzIHVwZGF0ZTpwcm9tcHRzIHJlYWQ6YnJhbmRpbmcgdXBkYXRlOmJyYW5kaW5nIGRlbGV0ZTpicmFuZGluZyByZWFkOmxvZ19zdHJlYW1zIGNyZWF0ZTpsb2dfc3RyZWFtcyBkZWxldGU6bG9nX3N0cmVhbXMgdXBkYXRlOmxvZ19zdHJlYW1zIGNyZWF0ZTpzaWduaW5nX2tleXMgcmVhZDpzaWduaW5nX2tleXMgdXBkYXRlOnNpZ25pbmdfa2V5cyByZWFkOmxpbWl0cyB1cGRhdGU6bGltaXRzIiwiZ3R5IjoiY2xpZW50LWNyZWRlbnRpYWxzIn0" | shasum -a 256
30555570f7d24ec43591de5770b74ac5ab2662d55823d1593c3f3195be1b359e  -

30555570f7d24ec43591de5770b74ac5ab2662d55823d1593c3f3195be1b359e の値が、 openssl rsautl と同じ値であることが確認できる。
これを用いて、JWT が改ざんされていないか検証している。

以上

やっと、やっっと自力で JWT の署名が検証できた!