Class: AceMQ::AMQP::EncryptionKey

Inherits:
Object
  • Object
show all
Defined in:
lib/acemq/amqp/crypto.rb

Overview

A key and the name messages will refer to it by.

The identifier is the part that makes rotation possible. It travels in every message, so a message written last month can still be read by a service whose current key is a different one, without anybody having to know when the change happened.

Identifiers are public. They sit in the clear in front of the ciphertext where anyone holding the message can read them, which is the point — the reader has to know what to ask the key store for before it can decrypt anything. Name them for the key, not for what they protect: orders-2026-09 rather than customer-card-numbers.

Constant Summary collapse

MAX_ID_BYTES =

The identifier goes in the framing behind a single length byte, so this is what fits. Long enough for a name and a date; short enough that it is not a place to put a comment.

255
CIPHERS =

What OpenSSL calls AES-GCM at each key length.

{ 16 => "aes-128-gcm", 24 => "aes-192-gcm", 32 => "aes-256-gcm" }.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, secret) ⇒ EncryptionKey

Returns a new instance of EncryptionKey.

Parameters:

  • id (String) —

    what messages written with this key will name

  • secret (String) —

    16, 24 or 32 bytes; 32 unless there is a reason

Raises:

  • (ArgumentError) —

    when the identifier or the key will not do



112
113
114
115
116
117
# File 'lib/acemq/amqp/crypto.rb', line 112

def initialize(id, secret)
  @id = id.to_s
  check_id!
  @secret = Keys.from_bytes(secret)
  freeze
end

Instance Attribute Details

#id ⇒ Object (readonly)

Returns the value of attribute id.



107
108
109
# File 'lib/acemq/amqp/crypto.rb', line 107

def id
  @id
end

#secret ⇒ Object (readonly)

Returns the value of attribute secret.



107
108
109
# File 'lib/acemq/amqp/crypto.rb', line 107

def secret
  @secret
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



130
# File 'lib/acemq/amqp/crypto.rb', line 130

def ==(other) = other.is_a?(EncryptionKey) && other.id == @id && other.secret == @secret

#cipher_name ⇒ String

What OpenSSL should be asked for to use this key.

Returns:

  • (String)


122
# File 'lib/acemq/amqp/crypto.rb', line 122

def cipher_name = CIPHERS.fetch(@secret.bytesize)

#hash ⇒ Object



132
# File 'lib/acemq/amqp/crypto.rb', line 132

def hash = [@id, @secret].hash

#id_bytes ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The identifier as it goes on the wire.

Returns:

  • (String) —

    UTF-8 bytes



128
# File 'lib/acemq/amqp/crypto.rb', line 128

def id_bytes = @id.dup.force_encoding(Encoding::BINARY)

#inspect ⇒ Object



136
# File 'lib/acemq/amqp/crypto.rb', line 136

def inspect = "#<AceMQ::AMQP::EncryptionKey id=#{@id.inspect}>"

#to_s ⇒ Object

The identifier and nothing else. The key must never appear in a log.



135
# File 'lib/acemq/amqp/crypto.rb', line 135

def to_s = "EncryptionKey{id=#{@id}}"