Barracuda Application Server C/C++ Reference
Native APIs, integration guides, and platform interfaces
Signed and Encrypted ZIP files

The Barracuda App Server (BAS) can protect deployed Lua ZIP applications in two different ways:

  • Signing proves that the ZIP file was produced by you and has not been modified.
  • Encryption hides sensitive files inside the ZIP archive.

Signing is most useful when Lua applications are deployed as external ZIP files instead of being embedded directly in firmware.

Quick Start

If you are new to this topic, start with this rule of thumb:

Goal Use signing? Use encryption?
Deploy a normal application with no secrets in the ZIP Yes Usually no
Prevent unauthorized or modified Lua applications from running Yes Usually no
Protect passwords, private keys, or other secrets stored inside the ZIP Yes Yes, for the sensitive files
Build the strongest practical deployment Yes Yes, but encrypt only the files that need confidentiality

For most embedded products, signing is the most important feature. If you use ZIP encryption, you should also require ZIP signing. Otherwise, an attacker may be able to replace encrypted entries with spoofed plaintext files.

What Signing and Encryption Protect

Signing Protects Authenticity and Integrity

When BaLua_param.zipPubKey is configured, the Lua ba.mkio ZIP creation paths verify the archive before exposing the resulting I/O object. This does not automatically verify a ZipIo that application C code constructs itself, nor the vmio supplied before the Lua VM is created. Verify those archives explicitly with baCheckZipSignature when verification is required.

Signing gives you two important guarantees:

  • Authenticity: the ZIP file was signed by someone who holds your private signing key.
  • Integrity: the ZIP file has not been modified since it was signed.

In practice, signing is what prevents unauthorized Lua applications, modified scripts, or injected files from being mounted and executed.

Encryption Protects Confidentiality

ZIP encryption protects the content of selected files inside the archive. This is useful for files such as:

  • configuration files with passwords or API credentials
  • private keys
  • product secrets
  • other deployment data that should not be readable from the ZIP file alone

You do not need to encrypt every file in the archive. In fact, that is usually a bad idea because it increases runtime decryption work, especially for frequently accessed Lua files and Lua Server Pages. ZIP encryption is applied per file, so it is usually best to encrypt only the files that actually contain secrets.

Signing and Encryption Serve Different Purposes

These two mechanisms are independent and solve different problems:

  • Embedded public key: tells BAS to verify signatures on mounted ZIP files.
  • Embedded ZIP password: lets BAS automatically decrypt encrypted files inside ZIP archives.

A signed ZIP file is not automatically encrypted. An encrypted ZIP file is not automatically trusted. In practice, encrypted ZIP files must be signed. Without signing, an attacker may be able to replace encrypted files in the archive with plaintext files containing spoofed data.

If you prefer not to embed a global ZIP password in C code, or if different ZIP files use different passwords, Lua code can set passwords individually by using io:setpasswd().

Recommended Production Workflow

For most deployments, the easiest way to think about the process is:

  1. Build your ZIP application.
  2. Encrypt only the files inside the ZIP that contain secrets.
  3. Sign the final ZIP file.
  4. Embed the public key in your BAS startup code.
  5. If you use ZIP encryption, also embed the generated ZIP password in your BAS startup code, or provide it from Lua via io:setpasswd().
  6. Deploy the ZIP file with both protections enabled.

Important: If you modify the ZIP file after signing it, you must sign it again. A signature always covers the final ZIP file bytes.

How ZIP Signing Works in BAS

BAS verifies signed ZIP files by using a standard public/private key model:

  • Private key: used by you during the build or release process to sign the ZIP file.
  • Public key: embedded in your BAS-based application and used to verify the signature.

Only someone with the private key can produce a valid signature. BAS only needs the public key to verify the signature when the ZIP file is mounted.

How the ZIP Signature Is Stored

ZIP files permit extra data to be appended to the end of the file. BAS takes advantage of this by storing the digital signature after the ZIP data. The BAS verifier expects its signature immediately after the archive end record. Use a ZIP without an archive comment, then sign it as shown below. The current verifier requires a signed file of at least 512 bytes and searches its final 512 bytes for the end record. See baCheckZipSignature for results.

Steps to Sign a ZIP File

  1. Calculate a SHA-256 hash of the ZIP file.
  2. Sign that hash with your ECC private key.
  3. Append the resulting signature to the end of the ZIP file.

When the configured Lua ZIP creation path opens the archive, it checks the signature before returning the I/O object.

Generate an ECC Key Pair with OpenSSL

If you do not already have an ECC key pair, you can create one with OpenSSL:

# Generate a private ECC key
openssl ecparam -genkey -name prime256v1 -noout -out private_key.pem
# Generate the corresponding public key
openssl ec -in private_key.pem -pubout -out public_key.pem

Files:

  • private_key.pem: keep this secure; it is used to sign ZIP files.
  • public_key.pem: embed this key in BAS so signed ZIP files can be verified.

Example: Sign a ZIP File

The following Bash script shows the basic signing process:

#!/bin/bash
set -e
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <zipfile> <privatekey>"
exit 1
fi
ZIP_FILE="$1"
PRIVATE_KEY="$2"
# Keep temporary output separate from the input archive.
SIGNATURE_FILE=$(mktemp)
trap 'rm -f "$SIGNATURE_FILE"' EXIT
echo "Creating SHA-256 signature for the ZIP file..."
openssl dgst -sha256 -sign "$PRIVATE_KEY" -out "$SIGNATURE_FILE" "$ZIP_FILE"
echo "Appending the signature to the end of the ZIP file..."
cat "$SIGNATURE_FILE" >> "$ZIP_FILE"
echo "Done. The ZIP file is now signed."

Usage:

./signzip.sh your_application.zip private_key.pem

Important: Run the script only on the final ZIP file. If you sign a ZIP file twice, or edit it after signing, signature verification will fail.

Embed the Public Key in BAS

To enforce signed ZIP files, embed the public key in your BAS startup code and assign it to BaLua_param.zipPubKey.

Convert the Public Key for C Code

Use the SharkSSLParseKey command-line tool to convert the PEM public key into a C array:

SharkSSLParseKey public_key.pem

This produces C data similar to:

const U8 sharkSslPubECKey[72] = {
/* SharkSSLParseKey output */
};
uint8_t U8
Unsigned 8-bit integer.
Definition: GenPrimT.h:89

Assign the Public Key in Startup Code

const U8 sharkSslPubECKey[72] = {
/* SharkSSLParseKey output */
};
memset(&blp, 0, sizeof(blp));
blp.zipPubKey = sharkSslPubECKey;
Startup and runtime parameters for a BAS Lua VM.
Definition: balua.h:178
const U8 * zipPubKey
Borrowed SharkSSL ECC public key, or NULL to disable ZIP signature checks.
Definition: balua.h:186

With zipPubKey configured, the Lua ZIP creation paths verify archives against that borrowed key. Keep its storage alive for the VM lifetime.

How ZIP Encryption Works in BAS

ZIP encryption uses a symmetric password. The same password is used to encrypt and decrypt the protected files inside the ZIP archive.

The binary password can be embedded in compiled code. The password conversion tool changes its representation; it does not itself provide white-box protection or make an embedded password impossible to recover. BAS uses the matching password to decrypt entries when accessed.

When to Use ZIP Encryption

Use ZIP encryption when your deployed ZIP contains secrets that should not be visible just because someone can copy the ZIP file. This works best for secrets that are static: files that never change after deployment, or that only change when you deliver a new signed application or OTA upgrade. In practice, ZIP encryption should be combined with ZIP signing.

Examples:

  • a configuration file containing passwords
  • private key material stored as files
  • deployment-specific secrets
  • other data that is packaged once and replaced only during an upgrade

ZIP encryption is not intended for data that your application must update continuously at runtime. If you need encrypted read/write storage for files that are created or modified while the system is running, use a runtime encryption layer such as CryptoIO.

Do not treat ZIP encryption as a substitute for ZIP signing. ZIP signing controls what code BAS is willing to trust. ZIP encryption only controls who can read selected file contents. If signing is not enabled, an attacker may be able to replace encrypted files with plaintext files containing spoofed data.

Enable ZIP AES Password Protection

To prepare a ZIP password for BAS, use the binpwd2str command line tool. This tool is designed for BAS deployments and produces three forms of the same password:

  • a readable password for use with your AES-capable ZIP tool
  • a binary form that can be used from Lua with io:setpasswd()
  • a C array for embedding the password in your BAS startup code

Typical Workflow

  1. Compile binpwd2str (source in the SDK's bin/binpwd2str.c).
  2. Supply a binary password file to binpwd2str input-file to produce the corresponding C array and ZIP-tool password. Use externally generated random bytes for production passwords; the tool's no-argument generator uses C rand.
  3. Use the readable password with your ZIP tool to encrypt the sensitive files in the ZIP archive.
  4. Embed the generated C array in your BAS startup code, or load the generated binary password from Lua and call io:setpasswd().

Embed the ZIP Password in Startup Code

const U8 zipBinPwd[] = {
/* binpwd2str output */
};
memset(&blp, 0, sizeof(blp));
blp.zipBinPwd = zipBinPwd;
blp.zipBinPwdLen = sizeof(zipBinPwd);
const U8 * zipBinPwd
Borrowed password bytes, or NULL for no default ZIP password.
Definition: balua.h:187
U16 zipBinPwdLen
Password byte count, matching zipBinPwd.
Definition: balua.h:188

With zipBinPwd configured, BAS can automatically decrypt encrypted ZIP entries that use the matching password.

zipBinPwd is a borrowed const U8*; zipBinPwdLen is its byte count as U16, so the array must fit that type and remain alive for the VM lifetime. With a default password configured, pwdRequired (BaBool) additionally controls whether plaintext entries are rejected. Leave it FALSE when encrypting only selected files; TRUE requires every accessed entry to be encrypted.

The snippets show only ZIP policy fields. Also initialize the required vmio and other host fields before calling balua_create, and check its return.

Combined Startup Example

If you want both protections, embed both the public key and the ZIP password:

const U8 sharkSslPubECKey[72] = {
/* SharkSSLParseKey output */
};
const U8 zipBinPwd[] = {
/* binpwd2str output */
};
memset(&blp, 0, sizeof(blp));
blp.zipPubKey = sharkSslPubECKey;
blp.zipBinPwd = zipBinPwd;
blp.zipBinPwdLen = sizeof(zipBinPwd);

Secure OTA Upgrades

The Barracuda App Server can support secure OTA upgrades both manually, for example through a web interface, and automatically through IoT protocols. A practical way to deliver an upgrade is to package it as a ZIP file and then protect that ZIP with the same signing and encryption mechanisms described in this document.

An OTA ZIP package can contain the new firmware image and any additional files required by the upgrade process, such as standalone applications, configuration files, or other deployment assets. This makes the ZIP file a convenient upgrade container for both firmware and application-level updates.

When ZIP signing is enabled, opening the OTA package with ba.mkio(baseio, path) automatically triggers signature verification. If the ZIP file is unsigned or has been modified, the call fails. This gives the upgrade logic a strong integrity and authenticity check before Lua code reads any data from the package.

If ZIP encryption is also enabled, the OTA package can additionally protect the confidentiality of sensitive upgrade files (secrets) stored inside the ZIP archive. In other words, signing protects the upgrade package from tampering, while encryption keeps selected files inside the package confidential.

Lua code can then be designed to open the verified ZIP package, extract the required files, and deploy the new firmware or accompanying resources. This approach works well when you want one upgrade artifact to carry everything needed for a secure field update.

Practical Recommendations

  • Sign all deployed Lua ZIP applications in production.
  • Encrypt only the files that actually contain secrets.
  • Keep the private signing key offline or otherwise tightly controlled.
  • Treat the embedded public key as part of your runtime trust policy.
  • If the ZIP changes, sign it again.
  • If you are using both features, encrypt first and sign last.

Troubleshooting Checklist

If a ZIP file does not load as expected, check the following:

  • Was the ZIP modified after it was signed?
  • Was the ZIP accidentally signed more than once?
  • Does the embedded public key match the private key that signed the ZIP?
  • Is the signed archive at least 512 bytes, with no archive comment?
  • If files are encrypted, does BAS have the correct ZIP password?
  • Are you encrypting too many frequently accessed files, causing unnecessary CPU load?