Class: BreachMitigation::MaskingSecrets
- Inherits:
-
Object
- Object
- BreachMitigation::MaskingSecrets
- Defined in:
- lib/breach_mitigation/masking_secrets.rb
Constant Summary collapse
- AUTHENTICITY_TOKEN_LENGTH =
32
Class Method Summary collapse
-
.masked_authenticity_token(session) ⇒ Object
Sets the token value for the current session and returns it in a masked form that’s safe to send to the client.
-
.valid_authenticity_token?(session, encoded_masked_token) ⇒ Boolean
Checks the client’s masked token to see if it matches the session token.
Class Method Details
.masked_authenticity_token(session) ⇒ Object
Sets the token value for the current session and returns it in a masked form that’s safe to send to the client. See section 3.4 of “BREACH: Reviving the CRIME attack”.
12 13 14 15 16 17 |
# File 'lib/breach_mitigation/masking_secrets.rb', line 12 def masked_authenticity_token(session) one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH) encrypted_csrf_token = xor_byte_strings(one_time_pad, real_csrf_token(session)) masked_token = one_time_pad + encrypted_csrf_token Base64.strict_encode64(masked_token) end |
.valid_authenticity_token?(session, encoded_masked_token) ⇒ Boolean
Checks the client’s masked token to see if it matches the session token. Essentially the inverse of masked_authenticity_token
.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/breach_mitigation/masking_secrets.rb', line 22 def valid_authenticity_token?(session, encoded_masked_token) return false if encoded_masked_token.nil? || encoded_masked_token.empty? begin masked_token = Base64.strict_decode64(encoded_masked_token) rescue ArgumentError # encoded_masked_token is invalid Base64 return false end # See if it's actually a masked token or not. In order to # deploy this code, we should be able to handle any unmasked # tokens that we've issued without error. if masked_token.length == AUTHENTICITY_TOKEN_LENGTH # This is actually an unmasked token. This is expected if # you have just upgraded to masked tokens, but should stop # happening shortly after installing this gem compare_with_real_token masked_token, session elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2 # Split the token into the one-time pad and the encrypted # value and decrypt it one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH] encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1] csrf_token = xor_byte_strings(one_time_pad, encrypted_csrf_token) compare_with_real_token csrf_token, session else false # Token is malformed end end |