Module: Faria::Launchpad::Packet
- Defined in:
- lib/faria/launchpad/packet.rb
Defined Under Namespace
Classes: ExpiredSignature, MismatchedRequestURL, MissingRemoteKey
Constant Summary collapse
- VERSION =
"v0.2"
Class Method Summary collapse
- .add_api_url(packet, url) ⇒ Object
- .add_expires(packet, expires_in) ⇒ Object
- .add_issued_at(packet) ⇒ Object
- .add_issuer(packet, issuer) ⇒ Object
- .add_source(packet, source) ⇒ Object
-
.decrypt(raw_data, options = {}, local_key:, remote_key:) ⇒ Object
for cases where you known in advance the remote key to use (such as LaunchPad clients which will only be receiving messages from LaunchPad and therefore will only use it’s public key for verifying signatures.
-
.decrypt_variable_key(raw_data, options = {}, local_key:, remote_key_func:) ⇒ Object
for cases where the signature key is not known in advance and must be determined by source information embedded in the JWT header.
-
.encrypt(data, options = {}, local_key:, remote_key:) ⇒ Object
encrypting is done with LaunchPad public key signing is done with local private key.
- .validate_expiration!(payload) ⇒ Object
- .validate_url!(payload, actual_url) ⇒ Object
Class Method Details
.add_api_url(packet, url) ⇒ Object
85 86 87 88 |
# File 'lib/faria/launchpad/packet.rb', line 85 def self.add_api_url(packet, url) packet["api_url"] = Addressable::URI.parse(url).normalize.to_s packet end |
.add_expires(packet, expires_in) ⇒ Object
95 96 97 98 |
# File 'lib/faria/launchpad/packet.rb', line 95 def self.add_expires(packet, expires_in) packet[:exp] = Time.now.utc.to_i + expires_in packet end |
.add_issued_at(packet) ⇒ Object
90 91 92 93 |
# File 'lib/faria/launchpad/packet.rb', line 90 def self.add_issued_at(packet) packet[:iat] = Time.now.utc.to_i packet end |
.add_issuer(packet, issuer) ⇒ Object
80 81 82 83 |
# File 'lib/faria/launchpad/packet.rb', line 80 def self.add_issuer(packet, issuer) packet[:iss] = issuer packet end |
.add_source(packet, source) ⇒ Object
75 76 77 78 |
# File 'lib/faria/launchpad/packet.rb', line 75 def self.add_source(packet, source) packet[:faria_source] = source packet end |
.decrypt(raw_data, options = {}, local_key:, remote_key:) ⇒ Object
for cases where you known in advance the remote key to use (such as LaunchPad clients which will only be receiving messages from LaunchPad and therefore will only use it’s public key for verifying signatures
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/faria/launchpad/packet.rb', line 45 def self.decrypt(raw_data, = {}, local_key:, remote_key: ) _version, jwe = raw_data.split(";", 2) jwt = JWE.decrypt(jwe, local_key) arr = JWT.decode(jwt, remote_key, true, { :algorithm => 'RS512' }) payload, _header = arr # validate_expiration will be handled by JWT decode validate_url!(payload, [:actual_url]) payload["data"] end |
.decrypt_variable_key(raw_data, options = {}, local_key:, remote_key_func:) ⇒ Object
for cases where the signature key is not known in advance and must be determined by source information embedded in the JWT header
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/faria/launchpad/packet.rb', line 59 def self.decrypt_variable_key(raw_data, = {}, local_key:, remote_key_func: ) _version, jwe = raw_data.split(";", 2) jwt = JWE.decrypt(jwe, local_key) header, payload = JWT::Decode.new(jwt, nil, false, {}).decode_segments[0..1] remote_key = remote_key_func.call(header, payload) fail(MissingRemoteKey) if remote_key.nil? arr = JWT.decode(jwt, remote_key, true, { :algorithm => 'RS512' }) payload, _header = arr # validate_expiration will be handled by JWT decode validate_url!(payload, [:actual_url]) payload["data"] end |
.encrypt(data, options = {}, local_key:, remote_key:) ⇒ Object
encrypting is done with LaunchPad public key signing is done with local private key
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/faria/launchpad/packet.rb', line 29 def self.encrypt(data, = {}, local_key:, remote_key: ) packet = { "data" => data} packet = add_issued_at(packet) packet = add_expires(packet, [:expires_in]) if [:expires_in] packet = add_api_url(packet, [:api_url]) if [:api_url] # packet = add_issuer(packet, options[:issuer]) packet = add_source(packet, [:source]) if [:source] payload = JWT.encode(packet, local_key, 'RS512') "#{VERSION};" + JWE.encrypt(payload, remote_key) # public end |
.validate_expiration!(payload) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/faria/launchpad/packet.rb', line 109 def self.validate_expiration!(payload) return unless payload.include?('exp') leeway = 0 valid_until = (Time.now.utc.to_i - leeway) if payload['exp'].to_i < valid_until diff = valid_until - payload['exp'].to_i error = ExpiredSignature.new("Signature expired", diff) fail(error) end end |
.validate_url!(payload, actual_url) ⇒ Object
100 101 102 103 104 105 106 107 |
# File 'lib/faria/launchpad/packet.rb', line 100 def self.validate_url!(payload, actual_url) return unless payload.include?('api_url') normalized_url = Addressable::URI.parse(actual_url).normalize.to_s if payload['api_url'] != normalized_url fail(MismatchedRequestURL) end end |