class Capsium::Package::Cipher
Encrypts and decrypts whole Capsium packages (05x-packaging “Encryption”, 05x-security “Encrypted information”).
An encrypted .cap is a zip containing exactly:
metadata.json (cleartext, per the standard: name/version stay
readable without the key)
signature.json (the encryption envelope)
package.enc (AES-256-GCM ciphertext of the inner, plaintext
.cap zip holding content/, the configuration
files and data/)
The envelope:
{"encryption": {"algorithm": "AES-256-GCM",
"keyManagement": "RSA-OAEP-SHA256",
"encryptedDek": <base64>, "iv": <base64>,
"authTag": <base64>}}
A random 256-bit data encryption key (DEK) encrypts the inner zip; the DEK is wrapped with the recipient’s RSA public key using OAEP with SHA-256 (MGF1-SHA-256). OpenPGP key management (an armored OpenPGP message carrying the DEK) is provided by the parallel OpenPgpCipher subclass; the OCB alternative mentioned by the standard remains out of scope.
Constants
- ALGORITHM
- ENCRYPTED_FILE
- ENVELOPE_FILE
- KEY_MANAGEMENT
- RSA_OPTIONS
Public Class Methods
(String | Pathname source_path, String private_key_path) → String
Source
# File lib/capsium/package/cipher.rb, line 123 def self.decrypt_to_directory(source_path, private_key_path) Dir.mktmpdir.tap do |tmp| inner_cap = File.join(tmp, "inner.cap") for_encrypted(source_path).decrypt(source_path, private_key_path, inner_cap) package_path = File.join(tmp, File.basename(source_path.to_s, ".cap")) FileUtils.mkdir_p(package_path) Packager.new.unpack(inner_cap, package_path) FileUtils.rm_f(inner_cap) return package_path end end
Decrypts an encrypted package into a fresh temporary directory and returns the directory path. The cipher is selected from the envelope’s keyManagement (for_encrypted), so Package.new(decryption_key:) accepts either key format transparently.
(String | Pathname path) → bool
Source
# File lib/capsium/package/cipher.rb, line 57 def self.encrypted?(path) return File.file?(File.join(path, ENCRYPTED_FILE)) if File.directory?(path) return false unless File.file?(path) Zip::File.open(path) { |zip| !zip.find_entry(ENCRYPTED_FILE).nil? } rescue Zip::Error false end
Whether the path (.cap file or uncompressed directory) is an encrypted package, i.e. contains package.enc.
(String | Pathname path) → Cipher
Source
# File lib/capsium/package/cipher.rb, line 78 def self.for_encrypted(path) key_management(path) == OpenPgpCipher::KEY_MANAGEMENT ? OpenPgpCipher.new : new end
The cipher instance matching the envelope’s keyManagement: OpenPgpCipher for OpenPGP envelopes, the RSA cipher otherwise.
(String | Pathname path) → String?
Source
# File lib/capsium/package/cipher.rb, line 69 def self.key_management(path) source = envelope_source(path) source && EncryptionConfig.from_json(source).encryption&.key_management rescue Lutaml::Model::Error, JSON::ParserError nil end
The keyManagement declared by the encryption envelope of the path (.cap file or uncompressed directory), or nil when the envelope is absent or unreadable.
Public Instance Methods
(String | Pathname encrypted_path, String private_key_path, String output_path) → String
Source
# File lib/capsium/package/cipher.rb, line 110 def decrypt(encrypted_path, private_key_path, output_path) private_key = load_private_key(private_key_path) envelope = load_envelope(encrypted_path) ciphertext = read_source(encrypted_path, ENCRYPTED_FILE) File.binwrite(output_path, decrypt_bytes(ciphertext, envelope, private_key)) output_path end
Decrypts the encrypted package at encrypted_path (.cap file or uncompressed directory) with the recipient’s RSA private key and writes the plaintext .cap to output_path.
(String source_path, String public_key_path, String output_path) → String
Source
# File lib/capsium/package/cipher.rb, line 97 def encrypt(source_path, public_key_path, output_path) public_key = load_public_key(public_key_path) with_cap_file(source_path) do |cap_path| envelope, ciphertext = encrypt_bytes(File.binread(cap_path), public_key) write_encrypted_cap(output_path, read_source(cap_path, Package::METADATA_FILE), envelope, ciphertext) end output_path end
Encrypts the package at source_path (a .cap file, or a package directory which is packed first) for the recipient’s RSA public key (or X.509 certificate) and writes the encrypted .cap to output_path.