class CZTop::Certificate

Represents a CZMQ::FFI::Zcert.

Constants

KEY_ALL_ZERO

Public Class Methods

check_curve_availability() click to toggle source

Warns if CURVE security isn’t available. @return [Boolean] whether it’s available

# File lib/cztop/certificate.rb, line 13
def self.check_curve_availability
  if Zsys.has_curve
    true
  else
    warn "CZTop: CURVE isn't available. Consider installing libsodium."
    false
  end
end
load(filename) click to toggle source

Loads a certificate from a file. @param filename [String, Pathname, to_s] path to certificate file @return [Certificate] the loaded certificate

# File lib/cztop/certificate.rb, line 26
def self.load(filename)
  ptr = Zcert.load(filename.to_s)
  from_ffi_delegate(ptr)
end
new(...) click to toggle source
# File lib/cztop/certificate.rb, line 57
def self.new(...)
  fail NotImplementedError
end
new() click to toggle source

Initialize a new in-memory certificate with random keys.

# File lib/cztop/certificate.rb, line 70
def initialize
  attach_ffi_delegate(Zcert.new)
end
new_from(public_key, secret_key = nil) click to toggle source

Creates a new certificate from the given keys (either binary or in Z85 format). @param public_key [String] binary public key (32 or 40 bytes) @param secret_key [String, nil] binary secret key (32 or 40 bytes), or

nil to initialize a public key only certificate

@return [Certificate] the fresh certificate @raise [ArgumentError] if keys passed are invalid @raise [SystemCallError] if this fails

# File lib/cztop/certificate.rb, line 40
def self.new_from(public_key, secret_key = nil)
  raise ArgumentError, 'no public key given' unless public_key

  secret_key ||= "\x00" * 32 # no secret key given, provide 32 null bytes

  # convert Z85 => binary
  public_key = Z85.decode(public_key) if public_key.bytesize == 40
  secret_key = Z85.decode(secret_key) if secret_key.bytesize == 40

  raise ArgumentError, 'invalid public key size' if public_key.bytesize != 32
  raise ArgumentError, 'invalid secret key size' if secret_key.bytesize != 32

  ptr = Zcert.new_from(public_key, secret_key)
  from_ffi_delegate(ptr)
end

Public Instance Methods

==(other) click to toggle source

Compares this certificate to another. @param other [Cert] other certificate @return [Boolean] whether they have the same keys

# File lib/cztop/certificate.rb, line 229
def ==(other)
  ffi_delegate.eq(other.ffi_delegate)
end
[](key) click to toggle source

Get metadata. @param key [String] metadata key @return [String] value for meta key @return [nil] if metadata key is not set

# File lib/cztop/certificate.rb, line 126
def [](key)
  ffi_delegate.meta(key)
end
[]=(key, value) click to toggle source

Set metadata. @param key [String] metadata key @param value [String] metadata value @return [value]

# File lib/cztop/certificate.rb, line 135
def []=(key, value)
  if value
    ffi_delegate.set_meta(key, '%s', :string, value)
  else
    ffi_delegate.unset_meta(key)
  end
end
apply(zocket) click to toggle source

Applies this certificate on a {Socket} or {Actor}. @param zocket [Socket, Actor] path/filename to secret file @return [void] @raise [SystemCallError] if secret key is undefined

# File lib/cztop/certificate.rb, line 207
def apply(zocket)
  raise ArgumentError, format('invalid zocket argument %p', zocket) unless zocket
  return ffi_delegate.apply(zocket) unless secret_key.nil?

  raise_zmq_err('secret key is undefined')
end
dup() click to toggle source

Duplicates the certificate. @return [Certificate] @raise [SystemCallError] if this fails

# File lib/cztop/certificate.rb, line 218
def dup
  ptr = ffi_delegate.dup
  return from_ffi_delegate(ptr) unless ptr.null?

  raise_zmq_err('unable to duplicate certificate')
end
meta_keys() click to toggle source

Returns meta keys set. @return [Array<String>]

# File lib/cztop/certificate.rb, line 146
def meta_keys
  zlist     = ffi_delegate.meta_keys
  first_key = zlist.first
  return [] if first_key.null?

  keys = [first_key.read_string]
  while (key = zlist.next)
    break if key.null?

    keys << key.read_string
  end
  keys
end
public_key(format: :z85) click to toggle source

Returns the public key either as Z85-encoded ASCII string (default) or binary string. @param format [Symbol] :z85 for Z85, :binary for binary @return [String] public key

# File lib/cztop/certificate.rb, line 89
def public_key(format: :z85)
  case format
  when :z85
    ffi_delegate.public_txt.force_encoding(Encoding::ASCII)
  when :binary
    ffi_delegate.public_key.read_string(32)
  else
    raise ArgumentError, format('invalid format: %p', format)
  end
end
save(filename) click to toggle source

Save full certificate (public + secret) to files. @param filename [String, to_s] path/filename to public file @return [void] @raise [ArgumentError] if path is invalid @raise [SystemCallError] if this fails @note This will create two files: one of the public key and one for the

secret key. The secret filename is filename + "_secret".
# File lib/cztop/certificate.rb, line 168
def save(filename)
  # see https://github.com/zeromq/czmq/issues/1244
  raise ArgumentError, "filename can't be empty" if filename.to_s.empty?

  rc = ffi_delegate.save(filename.to_s)
  return if rc.zero?

  raise_zmq_err(format('error while saving to file %p', filename))
end
save_public(filename) click to toggle source

Saves the public key to file in ZPL ({Config}) format. @param filename [String, to_s] path/filename to public file @return [void] @raise [SystemCallError] if this fails

# File lib/cztop/certificate.rb, line 183
def save_public(filename)
  rc = ffi_delegate.save_public(filename.to_s)
  return if rc.zero?

  raise_zmq_err(format('error while saving to the file %p', filename))
end
save_secret(filename) click to toggle source

Saves the secret key to file in ZPL ({Config}) format. @param filename [String, to_s] path/filename to secret file @return [void] @raise [SystemCallError] if this fails

# File lib/cztop/certificate.rb, line 195
def save_secret(filename)
  rc = ffi_delegate.save_secret(filename.to_s)
  return if rc.zero?

  raise_zmq_err(format('error while saving to the file %p', filename))
end
secret_key(format: :z85) click to toggle source

Returns the secret key either as Z85-encoded ASCII string (default) or binary string. @param format [Symbol] :z85 for Z85, :binary for binary @return [String] secret key @return [nil] if secret key is undefined (like after loading from a file

created using {#save_public})
# File lib/cztop/certificate.rb, line 107
def secret_key(format: :z85)
  case format
  when :z85
    key = ffi_delegate.secret_txt.force_encoding(Encoding::ASCII)
    return nil if key.count('0') == 40
  when :binary
    key = ffi_delegate.secret_key.read_string(32)
    return nil if key.count("\0") == 32
  else
    raise ArgumentError, format('invalid format: %p', format)
  end
  key
end
zero?() click to toggle source

@return [Boolean] whether one of the keys is all zeros (happens when CURVE is not available, i.e. libzmq was

compiled without libsodium)

@see .check_curve_availability

# File lib/cztop/certificate.rb, line 80
def zero?
  public_key(format: :z85) == KEY_ALL_ZERO || secret_key(format: :z85) == KEY_ALL_ZERO
end