Module: PQCrypto::JWT::JWK
- Defined in:
- lib/pq_crypto/jwt/jwk.rb
Constant Summary collapse
- KTY =
"AKP".freeze
Class Method Summary collapse
- .alg_for_algorithm!(algorithm) ⇒ Object
- .algorithm_from_jwk!(jwk) ⇒ Object
- .base64url(bytes) ⇒ Object
- .base64url_decode(value) ⇒ Object
- .from_public_key(public_key, kid: nil) ⇒ Object
- .from_secret_key ⇒ Object
- .normalize_hash!(hash) ⇒ Object
- .public_key_from_jwk(hash) ⇒ Object
- .secret_key_from_jwk ⇒ Object
- .thumbprint(jwk_hash) ⇒ Object
Class Method Details
.alg_for_algorithm!(algorithm) ⇒ Object
90 91 92 93 94 95 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 90 def alg_for_algorithm!(algorithm) match = PQCrypto::JWT.signing_algorithms.find { |candidate| candidate.pq_crypto_algorithm == algorithm } raise PQCrypto::JWT::UnsupportedAlgorithm, "Unsupported pq_crypto signature algorithm: #{algorithm.inspect}" unless match match.alg end |
.algorithm_from_jwk!(jwk) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 77 def algorithm_from_jwk!(jwk) unless jwk.fetch("kty", nil) == KTY raise PQCrypto::JWT::Error, "Unsupported JWK kty: #{jwk.fetch('kty', nil).inspect}" end alg = jwk.fetch("alg", nil) algorithm = PQCrypto::JWT.algorithm_for(alg) raise PQCrypto::JWT::UnsupportedAlgorithm, "Unsupported JWK alg: #{alg.inspect}" unless algorithm raise PQCrypto::JWT::UnsupportedAlgorithm, "Unsupported JWK alg: #{alg.inspect}" unless algorithm.key_kind == :signature algorithm.pq_crypto_algorithm end |
.base64url(bytes) ⇒ Object
49 50 51 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 49 def base64url(bytes) Base64.urlsafe_encode64(String(bytes).b, padding: false) end |
.base64url_decode(value) ⇒ Object
53 54 55 56 57 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 53 def base64url_decode(value) Base64.urlsafe_decode64(String(value)) rescue ArgumentError => e raise PQCrypto::JWT::Error, "Invalid base64url value: #{e.}" end |
.from_public_key(public_key, kid: nil) ⇒ Object
14 15 16 17 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 14 def from_public_key(public_key, kid: nil) validate_public_key!(public_key) base_public_jwk(public_key.algorithm, public_key.to_bytes, kid: kid).freeze end |
.from_secret_key ⇒ Object
19 20 21 22 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 19 def from_secret_key(*, **) raise PQCrypto::JWT::UnsupportedAlgorithm, "Private AKP JWK export is not supported in the first release; use PEM/PKCS#8 for signing keys" end |
.normalize_hash!(hash) ⇒ Object
59 60 61 62 63 64 65 66 67 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 59 def normalize_hash!(hash) unless hash.respond_to?(:to_hash) raise PQCrypto::JWT::Error, "JWK must be a Hash-like object" end hash.to_hash.each_with_object({}) do |(key, value), normalized| normalized[String(key)] = value end end |
.public_key_from_jwk(hash) ⇒ Object
24 25 26 27 28 29 30 31 32 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 24 def public_key_from_jwk(hash) jwk = normalize_hash!(hash) reject_private_material!(jwk) algorithm = algorithm_from_jwk!(jwk) public_bytes = decode_required_key_bytes!(jwk, "pub", algorithm, :public_key_bytes) PQCrypto::Signature.public_key_from_bytes(algorithm, public_bytes) rescue ArgumentError => e raise PQCrypto::JWT::Error, e. end |
.secret_key_from_jwk ⇒ Object
34 35 36 37 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 34 def secret_key_from_jwk(*) raise PQCrypto::JWT::UnsupportedAlgorithm, "Private AKP JWK import is not supported in the first release; use PEM/PKCS#8 for signing keys" end |
.thumbprint(jwk_hash) ⇒ Object
39 40 41 42 43 44 45 46 47 |
# File 'lib/pq_crypto/jwt/jwk.rb', line 39 def thumbprint(jwk_hash) jwk = normalize_hash!(jwk_hash) reject_private_material!(jwk) algorithm_from_jwk!(jwk) raise PQCrypto::JWT::Error, "JWK pub is required" unless jwk.key?("pub") canonical = JSON.generate({ "alg" => jwk.fetch("alg"), "kty" => KTY, "pub" => jwk.fetch("pub") }) base64url(Digest::SHA256.digest(canonical.b)) end |