Class: SshTresor::Vault

Inherits:
Object
  • Object
show all
Defined in:
lib/ssh_tresor/vault.rb

Overview

Public high-level API for encrypting and decrypting tresors from another Ruby application or gem.

‘Vault` is intentionally a small facade over the lower-level SSH agent, crypto, and wire-format objects. It connects to `SSH_AUTH_SOCK` by default, but accepts an injected agent object for tests or alternate transports.

Examples:

Encrypt and decrypt using the current SSH agent

vault = SshTresor::Vault.new
encrypted = vault.encrypt("secret", armor: true)
plaintext = vault.decrypt(encrypted)

Inject a custom agent implementation

vault = SshTresor::Vault.new(agent: my_agent)

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(agent: Agent.connect) ⇒ SshTresor::Vault

Creates a vault bound to an SSH agent.

The default agent is opened from ‘ENV`. The injected agent must implement the subset of Agent used by the high-level operations: `first_key`, `find_key`, `list_keys`, and `sign`.

Parameters:

  • agent (#first_key, #find_key, #list_keys, #sign) (defaults to: Agent.connect)

    SSH agent-like object.

Raises:



34
35
36
# File 'lib/ssh_tresor/vault.rb', line 34

def initialize(agent: Agent.connect)
  @agent = agent
end

Instance Method Details

#add_all_keys(encrypted, armor: nil) ⇒ Array(String, Integer)

Adds slots for all available SSH agent keys not already present.

Keys that are already present or cannot sign are skipped.

Parameters:

  • encrypted (String)

    Binary or armored tresor content.

  • armor (Boolean, nil) (defaults to: nil)

    Output armor mode. ‘nil` preserves input format.

Returns:

  • (Array(String, Integer))

    Updated tresor content and number of slots added.

Raises:



95
96
97
98
99
100
# File 'lib/ssh_tresor/vault.rb', line 95

def add_all_keys(encrypted, armor: nil)
  input_was_armored = armored?(encrypted)
  blob = TresorBlob.from_bytes(encrypted)
  updated, added = Tresor.add_all_keys_with_agent(@agent, blob)
  [serialize(updated, armor.nil? ? input_was_armored : armor), added]
end

#add_key(encrypted, fingerprint:, armor: nil) ⇒ String

Adds one SSH key slot to an existing tresor.

The current agent must be able to decrypt an existing slot before adding a new one, because the master key must be recovered and re-wrapped for the new key.

Parameters:

  • encrypted (String)

    Binary or armored tresor content.

  • fingerprint (String)

    Fingerprint or unambiguous prefix of the key to add.

  • armor (Boolean, nil) (defaults to: nil)

    Output armor mode. ‘nil` preserves input format.

Returns:

  • (String)

    Updated encrypted tresor content.

Raises:



80
81
82
83
84
85
# File 'lib/ssh_tresor/vault.rb', line 80

def add_key(encrypted, fingerprint:, armor: nil)
  input_was_armored = armored?(encrypted)
  blob = TresorBlob.from_bytes(encrypted)
  updated = Tresor.add_key_with_agent(@agent, blob, fingerprint)
  serialize(updated, armor.nil? ? input_was_armored : armor)
end

#decrypt(encrypted) ⇒ String

Decrypts an encrypted tresor using any matching key in the SSH agent.

The input may be binary ‘SSHTRESR` v3 data or armored text. The agent is asked to sign the stored slot challenge for matching key fingerprints.

Parameters:

  • encrypted (String)

    Binary or armored tresor content.

Returns:

  • (String)

    Decrypted plaintext bytes.

Raises:



64
65
66
# File 'lib/ssh_tresor/vault.rb', line 64

def decrypt(encrypted)
  Tresor.decrypt_with_agent(@agent, TresorBlob.from_bytes(encrypted))
end

#encrypt(plaintext, fingerprints: [], armor: false) ⇒ String

Encrypts plaintext for one or more keys available in the SSH agent.

When no fingerprints are given, the first key returned by the agent is used. Fingerprints may be full ‘SHA256:…` values or unambiguous prefixes.

Parameters:

  • plaintext (String)

    Plaintext bytes to encrypt.

  • fingerprints (Array<String>) (defaults to: [])

    SSH key fingerprints to encrypt for.

  • armor (Boolean) (defaults to: false)

    Whether to return base64 armor instead of binary format.

Returns:

  • (String)

    Encrypted tresor bytes or armored text.

Raises:



49
50
51
52
# File 'lib/ssh_tresor/vault.rb', line 49

def encrypt(plaintext, fingerprints: [], armor: false)
  blob = Tresor.encrypt_with_agent(@agent, plaintext, fingerprints: fingerprints)
  armor ? blob.to_armored : blob.to_bytes
end

#list_keysArray<SshTresor::AgentKey>

Lists keys currently available through the configured SSH agent.

Returns:

Raises:



124
125
126
# File 'lib/ssh_tresor/vault.rb', line 124

def list_keys
  @agent.list_keys
end

#list_slots(encrypted) ⇒ Array<String>

Lists key slot fingerprints present in encrypted tresor content.

This does not require access to an SSH agent because slot fingerprints are stored in the tresor header.

Parameters:

  • encrypted (String)

    Binary or armored tresor content.

Returns:

  • (Array<String>)

    Raw 32-byte SHA-256 fingerprint bytes for each slot.

Raises:



136
137
138
# File 'lib/ssh_tresor/vault.rb', line 136

def list_slots(encrypted)
  TresorBlob.from_bytes(encrypted).slot_fingerprints
end

#remove_key(encrypted, fingerprint:, armor: nil) ⇒ String

Removes one key slot from an existing tresor.

This operation only edits metadata and does not require the SSH agent to hold the removed key. Removing the final slot is rejected.

Parameters:

  • encrypted (String)

    Binary or armored tresor content.

  • fingerprint (String)

    Fingerprint or unambiguous prefix of the slot to remove.

  • armor (Boolean, nil) (defaults to: nil)

    Output armor mode. ‘nil` preserves input format.

Returns:

  • (String)

    Updated encrypted tresor content.

Raises:



113
114
115
116
117
118
# File 'lib/ssh_tresor/vault.rb', line 113

def remove_key(encrypted, fingerprint:, armor: nil)
  input_was_armored = armored?(encrypted)
  blob = TresorBlob.from_bytes(encrypted)
  updated = Tresor.remove_key(blob, fingerprint)
  serialize(updated, armor.nil? ? input_was_armored : armor)
end