### Install Ruby JWE Gem Source: https://github.com/jwt/ruby-jwe/blob/master/README.md Install the JWE gem using the standard RubyGems command. ```bash gem install jwe ``` -------------------------------- ### Quick Configuration Examples for JWE Encryption Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/SUMMARY.md Examples demonstrating how to configure JWE encryption for different security levels and performance considerations. Choose 'alg' and 'enc' based on your requirements. ```ruby # High security JWE.encrypt(data, key, alg: 'RSA-OAEP-256', enc: 'A256GCM') ``` ```ruby # Performance JWE.encrypt(data, key, alg: 'RSA-OAEP', enc: 'A256GCM') ``` ```ruby # Backward compatibility JWE.encrypt(data, key, alg: 'RSA-OAEP', enc: 'A128GCM') ``` -------------------------------- ### Install Ruby JWE Gem Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/README.md Install the JWE gem using Bundler or directly with gem install. Ensure you run `bundle install` after adding it to your Gemfile. ```ruby gem 'jwe' ``` ```bash gem install jwe ``` -------------------------------- ### Get Compression Algorithm Instance Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Instantiate a compression algorithm by its name. Currently, only 'DEF' (DEFLATE) is supported. The returned instance provides compress and decompress methods. ```ruby def self.for(zip) ``` ```ruby zip = JWE::Zip.for('DEF') compressed = zip.compress(plaintext) decompressed = zip.decompress(compressed) ``` -------------------------------- ### Environment-Based JWE Configuration Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md Configure JWE encryption and decryption parameters by reading environment variables. This example shows a Rails initializer setup. ```ruby # config/initializers/jwe.rb (Rails example) module JWEConfig ALG = ENV['JWE_ALG'] || 'RSA-OAEP' ENC = ENV['JWE_ENC'] || 'A256GCM' ZIP = ENV['JWE_ZIP'] # nil if not set def self.encrypt(payload, key, **extra_headers) JWE.encrypt(payload, key, alg: ALG, enc: ENC, zip: ZIP, **extra_headers) end def self.decrypt(token, key) JWE.decrypt(token, key) end end # Usage encrypted = JWEConfig.encrypt(secret_data, rsa_key) plaintext = JWEConfig.decrypt(encrypted, rsa_key) ``` -------------------------------- ### JWE Usage Example with AES-256 Key Wrap Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Demonstrates how to use AES-256 Key Wrap for symmetric key distribution within JWE. Encrypts a payload using a generated Key Encryption Key (KEK). ```ruby require 'jwe' # AES-256 Key Wrap for symmetric key distribution kek = SecureRandom.random_bytes(32) # Key Encryption Key encrypted = JWE.encrypt(payload, kek, alg: 'A256KW', enc: 'A256GCM') plaintext = JWE.decrypt(encrypted, kek) ``` -------------------------------- ### Check OpenSSL Version Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md This snippet helps you identify the currently installed OpenSSL version on your system, which is crucial for understanding algorithm compatibility as detailed in the documentation. ```ruby require 'openssl' puts OpenSSL::VERSION # => "OpenSSL 1.1.1..." or "OpenSSL 3.0...." ``` -------------------------------- ### JWE Encryption Examples Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md Demonstrates various JWE encryption configurations using different key encryption algorithms (alg) and content encryption algorithms (enc). Includes RSA-OAEP, RSA-OAEP-256, AES Key Wrap, and direct encryption. ```ruby require 'jwe' # RSA-OAEP (default) rsa_key = OpenSSL::PKey::RSA.generate(2048) encrypted = JWE.encrypt(payload, rsa_key) ``` ```ruby # RSA-OAEP-256 (requires OpenSSL >= 3.0) encrypted = JWE.encrypt(payload, rsa_key, alg: 'RSA-OAEP-256') ``` ```ruby # AES Key Wrap with symmetric key distribution kek = SecureRandom.random_bytes(32) # Key Encryption Key encrypted = JWE.encrypt(payload, kek, alg: 'A256KW', enc: 'A256GCM') ``` ```ruby # Direct encryption (no key wrapping) direct_key = SecureRandom.random_bytes(32) # For A256GCM encrypted = JWE.encrypt(payload, direct_key, alg: 'dir', enc: 'A256GCM') ``` -------------------------------- ### JWE Usage Example with Direct Encryption Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Shows how to perform direct encryption with A256GCM, requiring a 32-byte key. It encrypts a payload and then decrypts it using the same direct key. ```ruby require 'jwe' # Direct encryption with A256GCM (32-byte key required) direct_key = SecureRandom.random_bytes(32) encrypted = JWE.encrypt(payload, direct_key, alg: 'dir', enc: 'A256GCM') plaintext = JWE.decrypt(encrypted, direct_key) ``` -------------------------------- ### Get Content Encryption Algorithm Instance Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Instantiate a content encryption algorithm by its name. CEK, IV, and tag can be provided for decryption; otherwise, they are auto-generated for encryption. ```ruby def self.for(enc, cek = nil, iv = nil, tag = nil) ``` ```ruby # For encryption (auto-generate CEK/IV) cipher = JWE::Enc.for('A128GCM') # For decryption (with stored CEK, IV, tag) cek = stored_bytes iv = stored_bytes tag = stored_bytes cipher = JWE::Enc.for('A128GCM', cek, iv, tag) ``` -------------------------------- ### AES GCM Usage Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Example demonstrating how to encrypt and decrypt a payload using AES GCM with a generated RSA key. This shows the basic API for JWE encryption and decryption. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) encrypted = JWE.encrypt(payload, rsa_key, enc: 'A256GCM') # 256-bit (32-byte) key plaintext = JWE.decrypt(encrypted, rsa_key) ``` -------------------------------- ### AES CBC-HS Usage Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Example demonstrating how to encrypt and decrypt a payload using AES CBC-HS with a generated RSA key. This showcases the API for JWE encryption and decryption with CBC-HS modes. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) encrypted = JWE.encrypt(payload, rsa_key, enc: 'A256CBC-HS512') plaintext = JWE.decrypt(encrypted, rsa_key) ``` -------------------------------- ### Direct Encryption with Specific Key Sizes Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md When using the 'dir' algorithm, you must provide a key of the exact required length for the chosen encryption algorithm. Examples show key generation for A128GCM, A256GCM, and A256CBC-HS512. ```ruby require 'jwe' # For A128GCM: 16-byte key key_16 = SecureRandom.random_bytes(16) encrypted = JWE.encrypt(payload, key_16, alg: 'dir', enc: 'A128GCM') # For A256GCM: 32-byte key key_32 = SecureRandom.random_bytes(32) encrypted = JWE.encrypt(payload, key_32, alg: 'dir', enc: 'A256GCM') # For A256CBC-HS512: 64-byte key (32 for HMAC, 32 for cipher) key_64 = SecureRandom.random_bytes(64) encrypted = JWE.encrypt(payload, key_64, alg: 'dir', enc: 'A256CBC-HS512') ``` -------------------------------- ### JWE Base64 Encoding Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Encodes binary or text data to Base64URL format without padding. Use this for preparing data for JWE transmission. ```ruby require 'jwe' encoded = JWE::Base64.jwe_encode("hello") puts encoded # => "aGVsbG8" ``` -------------------------------- ### JWE Header Structure Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Illustrates the structure of a JWE header, which is represented as a Ruby hash. Both symbol and string keys are accepted for standard fields like 'alg', 'enc', and 'zip'. ```ruby { alg: String, # Required. Key encryption algorithm. enc: String, # Required. Content encryption algorithm. zip: String | nil, # Optional. Compression algorithm. # ... additional custom headers } ``` -------------------------------- ### RSpec Test Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/README.md An example RSpec test demonstrating a 'roundtrip' scenario where data is encrypted and then decrypted using an RSA key, asserting that the decrypted data matches the original. ```ruby describe JWE do let(:key) { OpenSSL::PKey::RSA.generate(2048) } it 'roundtrips' do encrypted = JWE.encrypt('secret', key) plaintext = JWE.decrypt(encrypted, key) expect(plaintext).to eq 'secret' end end ``` -------------------------------- ### Test JWE Encryption and Decryption with RSpec (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md These RSpec examples demonstrate how to test JWE encryption, decryption, handling of tampered data, inclusion of custom headers, and support for compression. ```ruby # spec/services/jwe_service_spec.rb require 'rails_helper' RSpec.describe JweService do let(:key) { OpenSSL::PKey::RSA.generate(2048) } let(:plaintext) { 'secret data' } it 'encrypts and decrypts data' do encrypted = JWE.encrypt(plaintext, key) decrypted = JWE.decrypt(encrypted, key) expect(decrypted).to eq plaintext end it 'raises on tampered ciphertext' do encrypted = JWE.encrypt(plaintext, key) parts = encrypted.split('.') parts[3] = 'tampered' tampered = parts.join('.') expect { JWE.decrypt(tampered, key) }.to raise_error(JWE::InvalidData) end it 'includes custom headers' do encrypted = JWE.encrypt(plaintext, key, user_id: 'user-123') header_part = encrypted.split('.').first headers = JSON.parse(JWE::Base64.jwe_decode(header_part)) expect(headers['user_id']).to eq 'user-123' end it 'supports compression' do large_data = 'x' * 10_000 uncompressed = JWE.encrypt(large_data, key) compressed = JWE.encrypt(large_data, key, zip: 'DEF') expect(compressed.length).to be < uncompressed.length expect(JWE.decrypt(compressed, key)).to eq large_data end end ``` -------------------------------- ### JWE Header with Custom Fields Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Provides a concrete example of a JWE header hash, including standard fields and custom fields like 'kid' and 'custom_field'. Custom fields are not encrypted and are visible in the JWE token. ```ruby header = { alg: 'RSA-OAEP', enc: 'A128GCM', zip: 'DEF', kid: 'key-id-1', custom_field: 'plaintext value' } ``` -------------------------------- ### JWE Base64 Decoding Example Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Decodes Base64URL-encoded data, with or without padding. This is used to retrieve the original data from a JWE token. ```ruby require 'jwe' decoded = JWE::Base64.jwe_decode("aGVsbG8") puts decoded # => "hello" ``` -------------------------------- ### JWE::Enc.for Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Returns an algorithm instance for the given encryption algorithm, optionally initialized with CEK, IV, and tag. This method is used for both encryption and decryption setup. ```APIDOC ## JWE::Enc.for ### Description Returns an algorithm instance for the given encryption algorithm, optionally initialized with CEK, IV, and tag. ### Method Signature ```ruby def self.for(enc, cek = nil, iv = nil, tag = nil) ``` ### Parameters #### Path Parameters - **enc** (String) - Required - Content encryption algorithm name (e.g., 'A128GCM'). - **cek** (String) - Optional - Content Encryption Key (raw bytes). If nil, auto-generated. - **iv** (String) - Optional - Initialization Vector (raw bytes). If nil, auto-generated. - **tag** (String) - Optional - Authentication tag (raw bytes). Set only during decryption. ### Return Type Object — Algorithm instance (e.g., `JWE::Enc::A128gcm`) with attributes set. ### Throws - **JWE::NotImplementedError**: Algorithm not supported. ### Example ```ruby # For encryption (auto-generate CEK/IV) cipher = JWE::Enc.for('A128GCM') # For decryption (with stored CEK, IV, tag) cek = stored_bytes iv = stored_bytes tag = stored_bytes cipher = JWE::Enc.for('A128GCM', cek, iv, tag) ``` ``` -------------------------------- ### AES GCM Encryption and Decryption Implementation Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Simplified implementation of AES GCM for encrypting and decrypting data. It handles setup, encryption/decryption, and authentication tag generation/verification. Ensure the CEK meets the required key length. ```ruby # lib/jwe/enc/aes_gcm.rb module AesGcm def encrypt(cleartext, authenticated_data) raise JWE::BadCEK unless cek.length >= key_length setup_cipher(:encrypt, authenticated_data) ciphertext = cipher.update(cleartext) + cipher.final self.tag = cipher.auth_tag ciphertext end def decrypt(ciphertext, authenticated_data) raise JWE::BadCEK unless cek.length >= key_length setup_cipher(:decrypt, authenticated_data) cipher.update(ciphertext) + cipher.final rescue OpenSSL::Cipher::CipherError raise JWE::InvalidData, 'Invalid ciphertext or authentication tag' end end ``` -------------------------------- ### Get Algorithm Class for JWE Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Use `JWE::Alg.for` to get the algorithm class for a given algorithm name. This method returns the class itself, not an instance. ```ruby alg_class = JWE::Alg.for('RSA-OAEP') # => JWE::Alg::RsaOaep ``` -------------------------------- ### Configure JWE Compression Algorithm Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md Use the 'zip' option to specify the compression algorithm. 'DEF' enables DEFLATE compression. Omitting or setting to nil or an empty string disables compression. ```ruby require 'jwe' # With DEFLATE compression encrypted = JWE.encrypt(payload, key, zip: 'DEF') # Without compression (default) encrypted = JWE.encrypt(payload, key) # zip defaults to nil # Explicitly disable (equivalent to above) encrypted = JWE.encrypt(payload, key, zip: nil) encrypted = JWE.encrypt(payload, key, zip: '') ``` -------------------------------- ### Initialize AES Key Wrap Algorithm Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Initializes the AES Key Wrap algorithm with an optional key and a default or custom Initialization Vector (IV). The IV defaults to the RFC 3394 standard value. ```ruby def initialize(key = nil, iv = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6") self.iv = iv.b self.key = key.b end ``` -------------------------------- ### Configure JWE Encryption with Environment Variables (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md This class reads JWE encryption and compression settings from environment variables, falling back to defaults. It also handles key loading from a specified path or a default location. ```ruby # config/jwe_config.rb class JweConfig def self.encryption_alg ENV['JWE_ALG'] || 'RSA-OAEP' end def self.encryption_enc ENV['JWE_ENC'] || 'A256GCM' end def self.compression_enabled? ENV['JWE_COMPRESSION']&.downcase == 'true' end def self.key @key ||= begin key_path = ENV['JWE_KEY_PATH'] || Rails.root.join('config', 'jwe', 'key.pem') OpenSSL::PKey::RSA.new(File.read(key_path)) end end def self.encrypt(payload, **extra_headers) zip = compression_enabled? ? 'DEF' : nil JWE.encrypt( payload, key, alg: encryption_alg, enc: encryption_enc, zip: zip, **extra_headers ) end def self.decrypt(token) JWE.decrypt(token, key) end end # Usage encrypted = JweConfig.encrypt(data) plaintext = JweConfig.decrypt(encrypted) ``` -------------------------------- ### Encrypt with Performance-Optimized Algorithms (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md Select algorithms like RSA-OAEP and A256GCM for better performance compared to older or more complex options. This is suitable when maximum security is not the absolute priority over speed. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) # RSA-OAEP is faster than RSA1_5 # A256GCM is faster than A256CBC-HS512 encrypted = JWE.encrypt( payload, rsa_key, alg: 'RSA-OAEP', enc: 'A256GCM' ) plaintext = JWE.decrypt(encrypted, rsa_key) ``` -------------------------------- ### Handle JWE::NotImplementedError Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/errors.md Shows how to catch JWE::NotImplementedError when an unsupported encryption or compression algorithm is requested. ```ruby require 'jwe' begin JWE.encrypt(payload, key, alg: 'ECDH-ES') # Not implemented rescue JWE::NotImplementedError => e puts "Algorithm not available: #{e.message}" end ``` ```ruby begin encrypted = JWE.encrypt(payload, key, alg: custom_alg) rescue JWE::NotImplementedError => e puts "Requested algorithm is not available in this version" # Fall back to a supported algorithm end ``` -------------------------------- ### Encrypt with A256GCM Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md Use A256GCM for optimal performance. This is the recommended algorithm for general use. ```ruby encrypted = JWE.encrypt(payload, key, enc: 'A256GCM') ``` -------------------------------- ### Load RSA Key Pair from PEM File for JWE Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md Demonstrates loading an RSA private key from a PEM file for encryption and decryption. The public key can be extracted for encryption-only scenarios. ```ruby require 'jwe' # Load private key from file (includes public key) private_key = OpenSSL::PKey::RSA.new(File.read('private.pem')) encrypted = JWE.encrypt(payload, private_key) # For encryption only, extract public key public_key = private_key.public_key encrypted = JWE.encrypt(payload, public_key) # Decrypt with private key plaintext = JWE.decrypt(encrypted, private_key) ``` -------------------------------- ### Generate Raw Byte Keys for JWE Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Demonstrates generating raw byte keys for direct encryption ('dir') or AES key wrapping algorithms. The required key length depends on the specific algorithm (e.g., 16 bytes for A128KW/A128GCM, 32 bytes for A256KW/A256GCM). ```ruby key = SecureRandom.random_bytes(16) # For A128KW or A128GCM with dir key = SecureRandom.random_bytes(24) # For A192KW or A192GCM with dir key = SecureRandom.random_bytes(32) # For A256KW or A256GCM with dir ``` -------------------------------- ### JWE Encryption with DEFLATE Compression Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Demonstrates how to encrypt a large payload using DEFLATE compression with the JWE library. Also shows encryption without compression for comparison. ```ruby require 'jwe' # With compression large_payload = "x" * 100_000 encrypted = JWE.encrypt(large_payload, key, zip: 'DEF') # Without compression (default) encrypted = JWE.encrypt(large_payload, key) ``` -------------------------------- ### Encrypt for Legacy System Compatibility (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md Use algorithms like RSA-OAEP and A128GCM for compatibility with older systems. A smaller encryption key (A128GCM) can be used if the legacy system has limitations. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) # Use RSA-OAEP instead of RSA1_5 (but RSA1_5 for compatibility if needed) encrypted = JWE.encrypt( payload, rsa_key, alg: 'RSA-OAEP', enc: 'A128GCM' # Smaller key for compatibility ) ``` -------------------------------- ### Basic JWE Encryption and Decryption in Ruby Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/00-START-HERE.txt Demonstrates the fundamental usage of the JWE library for encrypting a secret message and then decrypting it using an RSA key. Ensure the 'jwe' gem is required and an OpenSSL::PKey::RSA key is generated. ```ruby require 'jwe' key = OpenSSL::PKey::RSA.generate(2048) encrypted = JWE.encrypt("secret", key) plaintext = JWE.decrypt(encrypted, key) ``` -------------------------------- ### Supported Key Encryption Algorithms (alg) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/INDEX.md Lists the supported algorithms for key encryption in JWE tokens. ```APIDOC ## Supported Key Encryption (alg) - RSA-OAEP (recommended) - RSA-OAEP-256 (OpenSSL 3.0+) - RSA1_5 (legacy) - A128KW, A192KW, A256KW (AES Key Wrap) - dir (direct encryption) ``` -------------------------------- ### Generate RSA Key for JWE Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Shows how to generate a new RSA key or load an existing one from a PEM string. A minimum of 2048 bits is recommended for security. The library automatically uses the public key for encryption and the private key for decryption. ```ruby key = OpenSSL::PKey::RSA.generate(2048) # or key = OpenSSL::PKey::RSA.new(pem_string) ``` -------------------------------- ### Valid JWE Compression Algorithms Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Lists all accepted compression algorithm names for JWE. Only 'DEF' is implemented. ```ruby ['DEF'] ``` -------------------------------- ### Run RSpec Tests Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/README.md Execute the comprehensive RSpec tests included with the gem to verify its functionality. ```bash bundle exec rspec ``` -------------------------------- ### Encrypt and Decrypt Files Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/README.md Encrypt the content of a file and write it to a new file with a '.jwe' extension. Decrypt the '.jwe' file back to its original content. ```ruby content = File.read(file_path) encrypted = JWE.encrypt(content, key) File.write(file_path + '.jwe', encrypted) # Decrypt encrypted = File.read(encrypted_path) content = JWE.decrypt(encrypted, key) ``` -------------------------------- ### JWE::Alg::Rsa15 Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Implements RSA key encryption with PKCS#1 v1.5 padding. This is a legacy method and not recommended for new implementations. ```APIDOC ## JWE::Alg::Rsa15 ### Description RSA key encryption with PKCS#1 v1.5 padding (legacy, not recommended). ### Attributes & Methods Same interface as RsaOaep. ### Example ```ruby rsa_key = OpenSSL::PKey::RSA.generate(2048) alg = JWE::Alg::Rsa15.new(rsa_key) encrypted_cek = alg.encrypt(cek) ``` ``` -------------------------------- ### Handle JWE::BadCEK Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/errors.md Illustrates catching JWE::BadCEK when the Content Encryption Key (CEK) is invalid, such as being the wrong size. ```ruby require 'jwe' cipher = JWE::Enc::A128gcm.new cipher.cek = SecureRandom.random_bytes(8) # Too short (need 16) begin cipher.encrypt("plaintext", "auth_data") rescue JWE::BadCEK => e puts "Invalid CEK: #{e.message}" end ``` ```ruby begin plaintext = JWE.decrypt(token, key) rescue JWE::BadCEK => e puts "Key decryption failed or key is invalid" # Verify the correct key is being used end ``` -------------------------------- ### RSA Key Encryption with OAEP Padding Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Use RsaOaep for RSA key encryption with PKCS#1 OAEP padding. Requires an OpenSSL::PKey::RSA object for initialization. ```ruby rsa_key = OpenSSL::PKey::RSA.generate(2048) alg = JWE::Alg::RsaOaep.new(rsa_key) encrypted_cek = alg.encrypt(cek) original_cek = alg.decrypt(encrypted_cek) ``` -------------------------------- ### DEFLATE Compression and Decompression Implementation Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Implements DEFLATE compression and decompression using Ruby's zlib library. It handles both RFC 1951 (raw DEFLATE) and RFC 1950 (zlib format) decompression. ```ruby class Def def compress(payload) zlib = Zlib::Deflate.new(Zlib::DEFAULT_COMPRESSION, -Zlib::MAX_WBITS) zlib.deflate(payload, Zlib::FINISH) end def decompress(payload) Zlib::Inflate.inflate(payload) rescue Zlib::DataError # Fallback for RFC 1950 format inflate = Zlib::Inflate.new(-Zlib::MAX_WBITS) inflate.inflate(payload) end end ``` -------------------------------- ### Encrypt and Decrypt with Default Algorithms Source: https://github.com/jwt/ruby-jwe/blob/master/README.md Encrypts a payload using default RSA-OAEP and A128GCM algorithms and then decrypts it. Requires an RSA key. ```ruby require 'jwe' key = OpenSSL::PKey::RSA.generate(2048) payload = "The quick brown fox jumps over the lazy dog." encrypted = JWE.encrypt(payload, key) puts encrypted plaintext = JWE.decrypt(encrypted, key) puts plaintext #"The quick brown fox jumps over the lazy dog." ``` -------------------------------- ### Main API Entry Points for JWE Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/00-START-HERE.txt These are the primary functions for encrypting and decrypting JWE tokens, and for checking parameters. Ensure you have the correct key and algorithm specified. ```ruby JWE.encrypt(payload, key, alg: 'RSA-OAEP', enc: 'A128GCM', **headers) JWE.decrypt(token, key) JWE.check_params(header, key) ``` -------------------------------- ### JWE::Zip.for Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Returns a compression algorithm instance for the given algorithm name. This method is used to obtain a compression object for subsequent compress/decompress operations. ```APIDOC ## JWE::Zip.for ### Description Returns a compression algorithm instance for the given algorithm name. ### Method Signature ```ruby def self.for(zip) ``` ### Parameters #### Path Parameters - **zip** (String) - Required - Compression algorithm name (currently only 'DEF' is supported). ### Return Type Object — Algorithm instance (e.g., `JWE::Zip::Def`). ### Throws - **JWE::NotImplementedError**: Algorithm not supported. ### Example ```ruby zip = JWE::Zip.for('DEF') compressed = zip.compress(plaintext) decompressed = zip.decompress(compressed) ``` ``` -------------------------------- ### AES-256 Key Wrap Algorithm Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Use A256kw for AES-256 Key Wrap. Requires a 32-byte key and shares the same interface as A128kw. ```ruby # kek = SecureRandom.random_bytes(32) # alg = JWE::Alg::A256kw.new(kek) # wrapped = alg.encrypt(cek) # unwrapped = alg.decrypt(wrapped) ``` -------------------------------- ### Handle JWE::DecodeError Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/errors.md Demonstrates how to catch and handle JWE::DecodeError when a JWE token is malformed or cannot be parsed. ```ruby require 'jwe' begin JWE.decrypt("invalid.token", key) rescue JWE::DecodeError => e puts "Decode failed: #{e.message}" end ``` ```ruby begin plaintext = JWE.decrypt(token, key) rescue JWE::DecodeError => e puts "Token format is invalid" # Handle token parsing failure end ``` -------------------------------- ### JWE.VERSION Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/00-START-HERE.txt Returns the current version of the JWE Ruby library. ```APIDOC ## JWE.VERSION ### Description Returns the current version of the JWE Ruby library. ### Method `JWE.VERSION` ### Parameters None ### Request Example ```ruby require 'jwe' puts "JWE Library Version: #{JWE.VERSION}" ``` ### Response #### Success Response (String) - The version string of the library. #### Response Example ``` "1.1.1" ``` ``` -------------------------------- ### Encrypt and Decrypt with 'dir' Algorithm Source: https://github.com/jwt/ruby-jwe/blob/master/README.md Encrypts a payload using the 'dir' algorithm method. Requires a direct encryption key of the correct size for the specified encryption method. ```ruby require 'jwe' key = SecureRandom.random_bytes(32) payload = "The quick brown fox jumps over the lazy dog." encrypted = JWE.encrypt(payload, key, alg: 'dir') puts encrypted plaintext = JWE.decrypt(encrypted, key) puts plaintext #"The quick brown fox jumps over the lazy dog." ``` -------------------------------- ### Check JWE Algorithm Availability Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/configuration.md Use this snippet to determine if a specific JWE algorithm class is loaded and available. It handles potential `NotImplementedError` for algorithms requiring specific OpenSSL versions. ```ruby require 'jwe' # Check if an algorithm class exists and is loaded begin alg_class = JWE::Alg.for('RSA-OAEP-256') puts "RSA-OAEP-256 is available" rescue JWE::NotImplementedError puts "RSA-OAEP-256 is not available (requires OpenSSL >= 3.0)" end # Check enc algorithm availability via class method available = JWE::Enc::A256gcm.available? # => true/false ``` -------------------------------- ### JWE Encryption for New Applications Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Encrypts a payload using recommended algorithms for new applications: RSA-OAEP-256 for key encryption, A256GCM for content encryption, and DEF for compression if the payload exceeds 1KB. ```ruby JWE.encrypt(payload, rsa_key, alg: 'RSA-OAEP-256', enc: 'A256GCM', zip: 'DEF') ``` -------------------------------- ### Encrypt with High-Security Algorithms (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md Use the strongest available algorithms for JWE encryption, with a fallback for older OpenSSL versions. Ensure your OpenSSL version supports RSA-OAEP-256 for enhanced security. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) payload = "sensitive data" # Use strongest algorithms available begin encrypted = JWE.encrypt( payload, rsa_key, alg: 'RSA-OAEP-256', # OpenSSL 3.0+ only enc: 'A256GCM' ) rescue JWE::NotImplementedError # Fallback for older OpenSSL encrypted = JWE.encrypt( payload, rsa_key, alg: 'RSA-OAEP', enc: 'A256GCM' ) end plaintext = JWE.decrypt(encrypted, rsa_key) ``` -------------------------------- ### RSA1_5 Encryption and Decryption Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Implements RSA key encryption using the legacy PKCS#1 v1.5 padding. This algorithm is vulnerable to padding oracle attacks and should only be used for backward compatibility with legacy systems. ```ruby # lib/jwe/alg/rsa15.rb class Rsa15 attr_accessor :key def initialize(key) self.key = key end def encrypt(cek) key.public_encrypt(cek) end def decrypt(encrypted_cek) key.private_decrypt(encrypted_cek) end end ``` -------------------------------- ### AES CBC-HS Encryption and Decryption Implementation Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Simplified implementation of AES CBC-HS for encrypting and decrypting data. It splits the CEK for encryption and MAC keys, generates a tag, and verifies it during decryption. The CEK must exactly match the required key length. ```ruby # lib/jwe/enc/aes_cbc_hs.rb module AesCbcHs def encrypt(cleartext, authenticated_data) raise JWE::BadCEK unless cek.length == key_length ciphertext = cipher_round(:encrypt, iv, cleartext) signature = generate_tag(authenticated_data, iv, ciphertext) self.tag = signature ciphertext end def decrypt(ciphertext, authenticated_data) raise JWE::BadCEK unless cek.length == key_length signature = generate_tag(authenticated_data, iv, ciphertext) raise JWE::InvalidData unless signature == tag cipher_round(:decrypt, iv, ciphertext) end def generate_tag(authenticated_data, iv, ciphertext) length = [authenticated_data.length * 8].pack('Q>') to_sign = authenticated_data + iv + ciphertext + length signature = OpenSSL::HMAC.digest(hash_name, mac_key, to_sign) signature[0...mac_key.length] # Truncate to MAC key size end end ``` -------------------------------- ### JWE.param_to_class_name Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Converts hyphenated or plus-separated algorithm names into CamelCase class names, useful for internal mapping. ```APIDOC ## JWE.param_to_class_name ### Description Converts hyphenated/plus-separated algorithm names to CamelCase class names. ### Method Signature ```ruby def self.param_to_class_name(param) ``` ### Parameters #### Path Parameters - **param** (String) - Required - Algorithm name (e.g., 'RSA-OAEP', 'A128KW'). ### Return Type String — CamelCase class name (e.g., 'RsaOaep', 'A128kw'). ### Example ```ruby JWE.param_to_class_name('RSA-OAEP') # => 'RsaOaep' JWE.param_to_class_name('RSA-OAEP-256') # => 'RsaOaep256' ``` ``` -------------------------------- ### AES-192 Key Wrap Algorithm Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Use A192kw for AES-192 Key Wrap. Requires a 24-byte key and shares the same interface as A128kw. ```ruby # kek = SecureRandom.random_bytes(24) # alg = JWE::Alg::A192kw.new(kek) # wrapped = alg.encrypt(cek) # unwrapped = alg.decrypt(wrapped) ``` -------------------------------- ### RSA Key Encryption with PKCS#1 v1.5 Padding Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Use Rsa15 for RSA key encryption with PKCS#1 v1.5 padding. This method is legacy and not recommended. It shares the same interface as RsaOaep. ```ruby rsa_key = OpenSSL::PKey::RSA.generate(2048) alg = JWE::Alg::Rsa15.new(rsa_key) encrypted_cek = alg.encrypt(cek) ``` -------------------------------- ### General JWE Error Handling in Ruby Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/errors.md This snippet demonstrates a comprehensive approach to handling various JWE-related exceptions during decryption. It covers invalid token formats, data tampering, unsupported algorithms, bad CEK, and argument errors, logging each issue appropriately. ```ruby require 'jwe' begin plaintext = JWE.decrypt(token, key) # Use plaintext rescue JWE::DecodeError => e # Token format is invalid Rails.logger.warn("Invalid JWE token format: #{e.message}") return nil rescue JWE::InvalidData => e # Token has been tampered or uses wrong key Rails.logger.warn("JWE authentication failed: #{e.message}") return nil rescue JWE::NotImplementedError => e # Algorithm not supported Rails.logger.error("Unsupported algorithm in JWE: #{e.message}") return nil rescue JWE::BadCEK => e # Key decryption produced invalid CEK Rails.logger.error("Bad CEK during JWE decryption: #{e.message}") return nil rescue ArgumentError => e # Invalid parameters Rails.logger.error("Invalid parameters for JWE: #{e.message}") return nil end ``` -------------------------------- ### Valid JWE Encryption Algorithms Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Lists all accepted algorithm names for JWE encryption. These are case-sensitive. ```ruby [ 'RSA1_5', 'RSA-OAEP', 'RSA-OAEP-256', 'A128KW', 'A192KW', 'A256KW', 'dir', 'ECDH-ES', 'ECDH-ES+A128KW', 'ECDH-ES+A192KW', 'ECDH-ES+A256KW', 'A128GCMKW', 'A192GCMKW', 'A256GCMKW', 'PBES2-HS256+A128KW', 'PBES2-HS384+A192KW', 'PBES2-HS512+A256KW' ] ``` -------------------------------- ### Convert Algorithm Param to Class Name Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/api-reference.md Converts hyphenated or plus-separated algorithm names into CamelCase class names. Useful for mapping algorithm strings to their corresponding class implementations. ```ruby def self.param_to_class_name(param) end ``` ```ruby JWE.param_to_class_name('RSA-OAEP') # => 'RsaOaep' JWE.param_to_class_name('RSA-OAEP-256') # => 'RsaOaep256' ``` -------------------------------- ### Direct Encryption Key Size Requirements Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/algorithms.md Illustrates the key size requirements for direct encryption with different JWE content encryption algorithms, such as A128GCM and A256CBC-HS512. ```ruby # A128GCM: 16 bytes key = SecureRandom.random_bytes(16) encrypted = JWE.encrypt(payload, key, alg: 'dir', enc: 'A128GCM') # A256CBC-HS512: 64 bytes (32 for MAC, 32 for cipher) key = SecureRandom.random_bytes(64) encrypted = JWE.encrypt(payload, key, alg: 'dir', enc: 'A256CBC-HS512') ``` -------------------------------- ### Generate and Validate API Tokens Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/README.md Create encrypted API tokens with specific data and permissions, and later decrypt and parse them for validation. The `kid` parameter can be used to specify the key identifier. ```ruby token_data = { user_id: 123, permissions: ['read', 'write'] } encrypted_token = JWE.encrypt(token_data.to_json, rsa_key, kid: 'key-v1') # Later: validate and extract token data plaintext = JWE.decrypt(encrypted_token, rsa_key) token_data = JSON.parse(plaintext) ``` -------------------------------- ### Valid JWE Encryption Algorithms Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/types.md Lists all accepted encryption algorithms for JWE. These are case-sensitive. ```ruby [ 'A128CBC-HS256', 'A192CBC-HS384', 'A256CBC-HS512', 'A128GCM', 'A192GCM', 'A256GCM' ] ``` -------------------------------- ### Supported Content Encryption Algorithms (enc) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/INDEX.md Lists the supported algorithms for content encryption in JWE tokens. ```APIDOC ## Supported Content Encryption (enc) - A128GCM, A192GCM, A256GCM (recommended) - A128CBC-HS256, A192CBC-HS384, A256CBC-HS512 ``` -------------------------------- ### Optional Compression Based on Payload Size (Ruby) Source: https://github.com/jwt/ruby-jwe/blob/master/_autodocs/usage-patterns.md Conditionally apply compression based on payload size to optimize token size. Compression is applied only if the payload exceeds a specified threshold. ```ruby require 'jwe' rsa_key = OpenSSL::PKey::RSA.generate(2048) def encrypt_with_optional_compression(payload, key, compression_threshold: 1024) zip = payload.bytesize > compression_threshold ? 'DEF' : nil JWE.encrypt(payload, key, zip: zip) end small_payload = "small data" encrypted_small = encrypt_with_optional_compression(small_payload, rsa_key) large_payload = "x" * 50_000 encrypted_large = encrypt_with_optional_compression(large_payload, rsa_key) ```