module WebhookSystem::Payload

Public Class Methods

decode(response_body, secret:, format:) click to toggle source
# File lib/webhook_system/encoder.rb, line 73
def decode(response_body, secret:, format:)
  payload = JSON.parse(response_body)

  case format
  when 'base64+aes256'
    decode_aes(payload, secret)
  when 'json'
    payload
  else
    raise ArgumentError, "don't know how to handle: #{payload['format']} payload"
  end
end
encode(payload, secret:, format:) click to toggle source
# File lib/webhook_system/encoder.rb, line 62
def encode(payload, secret:, format:)
  case format
  when 'base64+aes256'
    encode_aes(payload, secret)
  when 'json'
    payload
  else
    raise ArgumentError, "don't know how to handle: #{payload['format']} payload"
  end
end

Private Class Methods

decode_aes(payload, secret) click to toggle source
# File lib/webhook_system/encoder.rb, line 102
def decode_aes(payload, secret)
  encoded = Base64.decode64(payload['payload'])
  iv = Base64.decode64(payload['iv'])

  cipher = OpenSSL::Cipher.new('aes-256-cbc')
  cipher.decrypt
  cipher.iv = iv
  cipher.key = key_from_secret(iv, secret)
  decoded = cipher.update(encoded) + cipher.final

  JSON.parse(decoded)
rescue OpenSSL::Cipher::CipherError
  raise DecodingError, 'Decoding Failed, probably mismatched secret'
end
encode_aes(payload, secret) click to toggle source
# File lib/webhook_system/encoder.rb, line 88
def encode_aes(payload, secret)
  cipher = OpenSSL::Cipher.new('aes-256-cbc')
  cipher.encrypt
  iv = cipher.random_iv
  cipher.key = key_from_secret(iv, secret)
  encoded = cipher.update(payload.to_json) + cipher.final

  {
    format: 'base64+aes256',
    payload: Base64.encode64(encoded),
    iv: Base64.encode64(iv),
  }
end
key_from_secret(iv, secret_string) click to toggle source
# File lib/webhook_system/encoder.rb, line 117
def key_from_secret(iv, secret_string)
  OpenSSL::PKCS5.pbkdf2_hmac(secret_string, iv, 100_000, 256 / 8, 'SHA256')
end