Module: Tapyrus::JWS
- Defined in:
- lib/tapyrus/jws.rb
Defined Under Namespace
Classes: DecodeError
Constant Summary collapse
- ALGO =
"ES256K"
- CURVE_NAME =
"secp256k1"
Class Method Summary collapse
-
.decode(jws) ⇒ Array[JSON]
Decode JWS to JSON object.
-
.encode(payload, private_key_hex) ⇒ String
Encode data as JWS format.
-
.point_for(r_hex) ⇒ ECDSA::Point
Return point object that represents rG.
- .validate_header!(jwks) ⇒ Object
Class Method Details
.decode(jws) ⇒ Array[JSON]
Decode JWS to JSON object
50 51 52 53 54 55 56 57 |
# File 'lib/tapyrus/jws.rb', line 50 def decode(jws) jwt_claims, header = JWT.decode(jws, nil, false, { algorithm: ALGO }) jwks_hash = header.dig("jwk", "keys") raise Tapyrus::JWS::DecodeError, "No jwk key found in header" unless jwks_hash validate_header!(jwks_hash) jwks = JWT::JWK::Set.new(jwks_hash) JWT.decode(jws, nil, true, { algorithm: ALGO, jwks: jwks, allow_nil_kid: true }) end |
.encode(payload, private_key_hex) ⇒ String
Encode data as JWS format.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/tapyrus/jws.rb', line 16 def encode(payload, private_key_hex) parameters = { use: "sig", alg: ALGO } # see https://github.com/nov/json-jwt/blob/413848c/lib/json/jwk.rb#L162-L172 # see https://www.rfc-editor.org/rfc/rfc5915.html#page-6 sequence = OpenSSL::ASN1.Sequence( [ OpenSSL::ASN1.Integer(1), OpenSSL::ASN1.OctetString(OpenSSL::BN.new(private_key_hex, 16).to_s(2)), OpenSSL::ASN1.ObjectId(CURVE_NAME, 0, :EXPLICIT), OpenSSL::ASN1.BitString( ECDSA::Format::PointOctetString.encode(point_for(private_key_hex), compression: false), 1, :EXPLICIT ) ] ) ec_key = OpenSSL::PKey::EC.new(sequence.to_der) jwk = JWT::JWK.new(ec_key, parameters) jwks_hash = JWT::JWK::Set.new(jwk).export(include_private: false) JWT.encode(payload, jwk.signing_key, jwk[:alg], { typ: "JWT", algo: ALGO, jwk: jwks_hash }) end |
.point_for(r_hex) ⇒ ECDSA::Point
Return point object that represents rG
72 73 74 |
# File 'lib/tapyrus/jws.rb', line 72 def point_for(r_hex) Tapyrus::Key.new(priv_key: r_hex).to_point end |
.validate_header!(jwks) ⇒ Object
59 60 61 62 63 64 65 66 |
# File 'lib/tapyrus/jws.rb', line 59 def validate_header!(jwks) jwk = jwks.first raise Tapyrus::JWS::DecodeError, "No jwk key found in header" unless jwk raise Tapyrus::JWS::DecodeError, 'kty must be "EC"' if jwk["kty"] && jwk["kty"] != "EC" raise Tapyrus::JWS::DecodeError, 'crv must be "P-256K"' if jwk["crv"] && jwk["crv"] != "P-256K" raise Tapyrus::JWS::DecodeError, 'use must be "sig"' if jwk["use"] && jwk["use"] != "sig" raise Tapyrus::JWS::DecodeError, 'alg must be "ES256K"' if jwk["alg"] && jwk["alg"] != "ES256K" end |