Module: AceMQ::AMQP::Keys
- Defined in:
- lib/acemq/amqp/crypto.rb
Overview
Getting an AES key from the shapes one usually arrives in.
Keys are plain binary strings here rather than a wrapper class, because that is what OpenSSL wants and what a secret store hands back. The wrapper worth having is EncryptionKey, which pairs a key with the name messages will refer to it by.
Constant Summary collapse
- SIZES =
The three lengths AES takes. Anything else is refused rather than padded or hashed into shape, because both would make a weak key look like a strong one.
[16, 24, 32].freeze
Class Method Summary collapse
-
.from_base64(text) ⇒ String
The usual way a key arrives from a secret store or the environment.
-
.from_bytes(bytes) ⇒ String
The same bytes, checked.
-
.generate(bits: 256) ⇒ String
A new key from the platform's secure random.
-
.to_base64(key) ⇒ String
For writing a generated key into a secret store.
Class Method Details
.from_base64(text) ⇒ String
The usual way a key arrives from a secret store or the environment.
66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/acemq/amqp/crypto.rb', line 66 def self.from_base64(text) decoded = begin text.to_s.strip.unpack1("m0") rescue ArgumentError => e # Deliberately without the value. Whatever that string was, it was # meant to be a key, and a key does not belong in a message that # will be logged. raise ArgumentError, "could not read a key from Base64: #{e.}" end from_bytes(decoded) end |
.from_bytes(bytes) ⇒ String
Returns the same bytes, checked.
52 53 54 55 56 57 58 59 60 |
# File 'lib/acemq/amqp/crypto.rb', line 52 def self.from_bytes(bytes) material = bytes.to_s.dup.force_encoding(Encoding::BINARY) return material if SIZES.include?(material.bytesize) raise ArgumentError, "an AES key is 16, 24 or 32 bytes and this is #{material.bytesize}. If it came " \ "from a passphrase it needs a key derivation function such as PBKDF2 or Argon2 " \ "rather than being used as it stands." end |
.generate(bits: 256) ⇒ String
A new key from the platform's secure random.
41 42 43 44 45 46 47 48 |
# File 'lib/acemq/amqp/crypto.rb', line 41 def self.generate(bits: 256) bytes = bits / 8 unless SIZES.include?(bytes) raise ArgumentError, "an AES key is 128, 192 or 256 bits and this asked for #{bits}" end OpenSSL::Random.random_bytes(bytes) end |
.to_base64(key) ⇒ String
For writing a generated key into a secret store.
83 |
# File 'lib/acemq/amqp/crypto.rb', line 83 def self.to_base64(key) = [key.to_s].pack("m0") |