Skip to content

Instantly share code, notes, and snippets.

@mikem
Last active August 8, 2017 14:36
Show Gist options
  • Save mikem/cad669b7a9409cb6c6070949ad805ed0 to your computer and use it in GitHub Desktop.
Save mikem/cad669b7a9409cb6c6070949ad805ed0 to your computer and use it in GitHub Desktop.
A short program to decrypt a JWE Compact Serialization encrypted with a symmetric key
#!/usr/bin/env ruby
require 'optparse'
require 'jwe'
require 'jwt'
require 'pp'
options = {}
OptionParser.new do |opts|
opts.banner = <<-TXT
Decrypt JWT encrypted with AES symmetric key
Usage: #{__FILE__} [options] jwe_compact_serialization
TXT
opts.on("-sKEYPATH", "--signing-public-key=KEYPATH", "Path to public key for signature verification") do |key_path|
options[:signing_public_key] = key_path
end
opts.on("-eKEY", "--encryption-key=KEY", "Encryption key (64 hex characters)") do |key|
options[:encryption_key] = key
end
opts.on("-h", "--help", "Prints this help") do
puts opts
exit
end
end.parse!
jwe_compact_serialization = ARGV[0]
key = begin
key_hex = options[:encryption_key]
if !key_hex.nil?
key_hex = key_hex[2..-1] if key_hex.start_with? '0x'
key_hex.unpack('a2' * 32).map(&:hex).pack('c' * 32)
end
end
public_key = begin
key_path = options[:signing_public_key]
OpenSSL::PKey.read(File.read(key_path)) if key_path && File.exists?(key_path)
end
encoded_token = if key.nil?
jwe_compact_serialization
else
JWE.decrypt jwe_compact_serialization, key
end
payload, header = begin
verify_jwt = !public_key.nil?
decoded = JWT.decode encoded_token, public_key, verify_jwt, { algorithm: 'ES256', verify_expiration: false, verify_not_before: false }
puts "\nSignature verified!" if verify_jwt
decoded
rescue JWT::DecodeError
puts "\nWARNING: signature verification failed!"
JWT.decode encoded_token, public_key, false, { algorithm: 'ES256', verify_expiration: false, verify_not_before: false }
end
puts "\nJWT header"
pp header
puts "\nJWT payload"
pp payload
#!/usr/bin/env ruby
require 'openssl'
require 'base64'
# Verify RSA-SHA256 signature
#
# Usage:
# ./verify_rsa-sha256.rb [path to public key file]
#
# [path to public key file]: the path of the public key to use for verification
#
# Replace the two input strings below with your own signature and string to sign.
#
# Also see https://gist.github.com/gevans/6004752
public_key_path = ARGV[0]
digest = OpenSSL::Digest::SHA256.new
# This is a random signature, replace with your own
base64_encoded_signature = <<TXT.chomp
ERcQyTRsmfWaZKPP7cqoQxCIsKMno8vUY0YuXo72vVgA8CVHz/9/GVR88l/sMWbhbTeUuAuCaoPIavtk3SDQGa8eL2iL8PmKwr9RIiz68zrh5A6J/u10TkCXWhFnkmDbEm6p1lwn3+7GT4itF7XSBM7/V3x/y11ZkiKcbariqCk6aeQ7q5vTJ8Z+B93k64qsCOnSeOKNE6+H5V3Gp+fztVYYybUQ696RG2YSwc3jxOSuMDeN6ccNdVfmnqVRJQBbi3iciqrtZWCVbfSES5cKEJbV3GvcUiTa94SLPm/Cn80lTcohteCszSJZT0Zv4EYdLi3stpjyLhJwS3F92dKebg==
TXT
# Copied from https://web-payments.org/specs/source/http-signatures/#rfc.section.2.3
# Replace with your own
signature_string = <<TXT.chomp
(request-target): get /foo
host: example.org
date: Tue, 07 Jun 2014 20:51:35 GMT
cache-control: max-age=60, must-revalidate
x-example: Example header with some whitespace.
TXT
public_key = OpenSSL::PKey.read(File.read(public_key_path))
if public_key.verify(digest, Base64.strict_decode64(base64_encoded_signature), signature_string)
puts "Signature is valid"
else
puts "Signature is NOT valid"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment