Module: PQCrypto::JWT::JWA::MLDSAStreaming
- Included in:
- MLDSA65
- Defined in:
- lib/pq_crypto/jwt/jwa/ml_dsa_streaming.rb
Constant Summary collapse
- DEFAULT_CHUNK_SIZE =
1 << 20
- EMPTY_CONTEXT =
"".b.freeze
Instance Method Summary collapse
- #sign_io(signing_key:, payload_io: nil, io: nil, header_fields: {}, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
- #streaming_supported? ⇒ Boolean
- #verify_io(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
- #verify_io!(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
Instance Method Details
#sign_io(signing_key:, payload_io: nil, io: nil, header_fields: {}, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/pq_crypto/jwt/jwa/ml_dsa_streaming.rb', line 18 def sign_io(signing_key:, payload_io: nil, io: nil, header_fields: {}, chunk_size: DEFAULT_CHUNK_SIZE) raise PQCrypto::JWT::UnsupportedAlgorithm, "#{alg} does not support streaming JWS" unless streaming_supported? ensure_secret_key!(signing_key) source = payload_io || io raise ArgumentError, "payload_io must respond to #read" unless source.respond_to?(:read) header = stringify_keys(header_fields || {}).merge("alg" => alg) encoded_header = base64url(JSON.generate(header)) signing_input = DetachedSigningInputIO.new(encoded_header, source, chunk_size: chunk_size) signature = signing_key.sign_io(signing_input, chunk_size: chunk_size, context: EMPTY_CONTEXT) "#{encoded_header}..#{base64url(signature)}" rescue PQCrypto::JWT::Error, ArgumentError raise rescue StandardError => e raise ::JWT::EncodeError, e. end |
#streaming_supported? ⇒ Boolean
13 14 15 16 |
# File 'lib/pq_crypto/jwt/jwa/ml_dsa_streaming.rb', line 13 def streaming_supported? pq_crypto_algorithm == :ml_dsa_65 && PQCrypto::Signature.supported.include?(:ml_dsa_65) end |
#verify_io(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/pq_crypto/jwt/jwa/ml_dsa_streaming.rb', line 36 def verify_io(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) raise PQCrypto::JWT::UnsupportedAlgorithm, "#{alg} does not support streaming JWS" unless streaming_supported? ensure_public_key!(verification_key) raise ArgumentError, "token must be a String" unless token.is_a?(String) raise ArgumentError, "payload_io must respond to #read" unless payload_io.respond_to?(:read) encoded_header, encoded_payload, encoded_signature = token.split(".", -1) return false unless encoded_header && encoded_payload == "" && encoded_signature header = JSON.parse(Base64.urlsafe_decode64(encoded_header)) return false unless header["alg"] == alg signature = Base64.urlsafe_decode64(encoded_signature) signing_input = DetachedSigningInputIO.new(encoded_header, payload_io, chunk_size: chunk_size) verified = verification_key.verify_io(signing_input, signature, chunk_size: chunk_size, context: EMPTY_CONTEXT) return false unless verified [payload_position(payload_io), header] rescue JSON::ParserError, ArgumentError, PQCrypto::InvalidKeyError false end |
#verify_io!(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) ⇒ Object
58 59 60 61 62 63 |
# File 'lib/pq_crypto/jwt/jwa/ml_dsa_streaming.rb', line 58 def verify_io!(verification_key:, token:, payload_io:, chunk_size: DEFAULT_CHUNK_SIZE) result = verify_io(verification_key: verification_key, token: token, payload_io: payload_io, chunk_size: chunk_size) raise ::JWT::VerificationError, "Streaming JWS verification failed" unless result true end |