とあるバッチ処理で繰り返し大量の署名付き JWT を生成する事になり、今まで(深く)気にしてこなかったアルゴリズム別の性能差を確認してみた時のメモ。
※ HMAC の鍵長や ECDSA の使い方(曲線の選び方?)についてよく分かっていないので、条件がおかしいかもしれない。
require 'benchmark'
require 'jwt'
require 'digest/md5'
keys = {
HMAC: {
HS256: Digest::MD5.hexdigest('HS256'),
HS384: Digest::MD5.hexdigest('HS384'),
HS512: Digest::MD5.hexdigest('HS512'),
},
RSA: {
RS256: OpenSSL::PKey::RSA.generate(2048),
RS384: OpenSSL::PKey::RSA.generate(2048),
RS512: OpenSSL::PKey::RSA.generate(2048),
},
ECDSA: {
ES256: OpenSSL::PKey::EC.new('prime256v1').tap(&:generate_key),
ES384: OpenSSL::PKey::EC.new('secp384r1').tap(&:generate_key),
ES512: OpenSSL::PKey::EC.new('secp521r1').tap(&:generate_key),
},
}
n = 10_000
Benchmark.bm(15) do |bm|
keys.each do |group, algs|
algs.each do |alg, key|
bm.report("#{group} / #{alg}") do
n.times { JWT.encode({}, key, alg.to_s) }
end
end
end
end
__END__
user system total real
HMAC / HS256 0.280000 0.000000 0.280000 ( 0.289864)
HMAC / HS384 0.250000 0.000000 0.250000 ( 0.254620)
HMAC / HS512 0.260000 0.000000 0.260000 ( 0.255493)
RSA / RS256 6.140000 0.000000 6.140000 ( 6.146817)
RSA / RS384 6.140000 0.010000 6.150000 ( 6.155130)
RSA / RS512 6.140000 0.000000 6.140000 ( 6.151847)
ECDSA / ES256 0.810000 0.000000 0.810000 ( 0.815459)
ECDSA / ES384 7.140000 0.010000 7.150000 ( 7.149290)
ECDSA / ES512 3.610000 0.010000 3.620000 ( 3.627512)
備考: 実行環境など
- Ruby 2.4.2p111
- jwt/ruby-jwt v2.1.0
追記: RbNaCl
cryptosphere/rbnacl がロード可能であれば HMAC 系アルゴリズムで RbNaCl を使うという事が書かれていたので試してみたところ、若干遅くなる模様。
user system total real
HMAC / HS256 0.350000 0.000000 0.350000 ( 0.358537)
HMAC / HS384 0.260000 0.000000 0.260000 ( 0.264705)
HMAC / HS512 0.330000 0.000000 0.330000 ( 0.329434)
HMAC / HS512256 0.330000 0.000000 0.330000 ( 0.331153)
NaCl (Networking and Cryptography library) についてはよく分かっていません(jedisct1/libsodium も)。NaCl (ネットワーク応用通信研究所; Network Applied Communication Laboratory Ltd.)との関係もよく分かりません。