It’s hard to make authenticated encryption fit in an address bar. If you want to be compatible with IE, you’re stuck with 2048 bytes or less.

Pre-encryption data length: 166
IV length: 16
Data length: 166
Signature length: 139
Cert length: 397
Encoded length: 836

Some acronyms: AES-256-CFB, ECDSA, NIST P-521 / secp521r1, JSON, Base64.

encoded = [iv, encrypted_data, signature, service.public_key.to_der, service.signature].
  map{|d| Base64.urlsafe_encode64 d}.
  join(',')

I could get it smaller at the expense of harder key management if I simply pre-shared the service’s public key and didn’t have to pack a bunch of certificate things at the end.