spangled shalalala blog

諦めたらそこで試合終了だよ。

rubyでjwtのエンコードを実装してみるサンプル

JWTを調べたついでにエンコードしてトークンを作成する実装をしてみようと思い、rubyで実装したみた。
素直にgemを使えよ、という話ですが...😅

JWTについて調べたメモは以下の記事をご参考に。 spangled-shalalala.hatenablog.com

JWTのサンプルコード

require 'json'
require 'base64'
require 'openssl'

SECRET_KEY = "secretkey".freeze

def urlsafe_encode64(string)
  Base64.urlsafe_encode64(string).tr('+/', '-_').gsub(/[\n=]/, '')
end

header = { alg: "HS256", typ: "JWT" }.to_json
header_enc = urlsafe_encode64(header)

payload = {
 "loggedInAs": "admin",
 "iat": 1422779638
}.to_json
payload_enc = urlsafe_encode64(payload)

message = [header_enc, payload_enc].join(".")
sign = OpenSSL::HMAC::digest("sha256", SECRET_KEY, message)

token = [header_enc, payload_enc, urlsafe_encode64(sign)].join(".")

urlsafe_encode64のメソッドは ruby-jwt から引用。

微妙にはまった点は署名部分を OpenSSL::HMAC::hexdigestエンコードしていて結果が合わなくて悩んでしまった。
hexdigestは計算結果を16進文字列で返すのでNG。バイナリ文字列で結果を返すdigestで署名するのが正しいというわけですね。当たり前といえば当たり前ですが見落としていたせいで悩んでしまった。

自分で考えた結果よりjwtの署名の理解ができたような気がします!

トークンの結果はこちらのサイトで一致を確認して(あと、jsonwikipediaに記載のものを使用したのでそちらの記載とも一致を確認)結果を確かめました。

jwt.io

普段、日常業務でここらへんの暗号化とか実装する機会はあまり無いので楽しかった。これを機会に暗号化の本も読んでみたい。
暗号技術はこの本が有名みたいなので仕事帰りに買ってくるかな。