The Barracuda App Server (BAS) supports both signed and encrypted ZIP files, enhancing the security of your deployed Lua applications. This is particularly useful when your ZIP applications (deployed apps) are stored externally as files rather than being embedded within the binary or firmware.
Why Sign and Encrypt ZIP Files?
Ensuring Authenticity and Integrity with Signing
When deploying an application, it's crucial to ensure that it comes from you as a trusted source and hasn't been tampered with. By signing the deployed ZIP file:
- Authenticity: You verify that the application genuinely originates from you.
- Integrity: You confirm that the content hasn't been altered since it was signed.
This process prevents tampering and impersonation, safeguarding your applications from unauthorized modifications.
Protecting Sensitive Information with Encryption
Consider encrypting parts of the ZIP file that contain sensitive data, such as plain text passwords and private keys. Encrypting these elements ensures that even if someone gains access to the ZIP file, they cannot read your secrets.
Note: We do not recommend encrypting every file in the ZIP archive, as this can increase CPU load during decryption, especially for Lua Server Pages. Since ZIP encryption operates on a per-file basis, you can selectively encrypt only the files that contain sensitive information.
Signature vs. Password
- When you embed the public key into your C code, you enforce a policy that requires all mounted ZIP files to be signed. BAS will verify the signature of each ZIP file using the embedded public key before allowing it to be used.
- Setting a password in your C code enables automatic password management for encrypted files within mounted ZIP archives. This means BAS will automatically use the provided password to decrypt encrypted files when accessed. In scenarios where ZIP archives use different passwords, or you prefer not to embed the password in the C code, you can set individual passwords in your Lua scripts using io:setpasswd().
Understanding the Encryption and Signing Mechanisms
Asymmetric Encryption for Signing
The signing process uses asymmetric encryption involving a pair of keys:
- Private Key: Used to sign the ZIP file. Important: Keep this key secure and never share it.
- Public Key: Embedded in the compiled code and used during verification to validate the signature.
This mechanism ensures that only someone with the private key can sign the ZIP file, and anyone with the public key (in this case, BAS) can verify its authenticity.
Symmetric Encryption for File Content
ZIP file encryption utilizes symmetric encryption, meaning the same password is used to encrypt and decrypt the content. This password is:
- Embedded in the compiled code of your application.
- Protected using white-box cryptography, which obfuscates the cryptographic algorithms and keys, making it challenging for attackers to extract them even if they have access to the binary.
How to Sign ZIP Files
An interesting feature of ZIP files is that you can append data to the end of the file without corrupting it. This allows you to attach a digital signature directly to the ZIP file.
Steps to Sign a ZIP File
- Calculate a SHA-256 Hash: Generate a SHA-256 hash of the ZIP file's contents.
- Sign the Hash: Use your ECC (Elliptic Curve Cryptography) private key to sign the hash.
- Append the Signature: Attach the digital signature to the end of the ZIP file.
When BAS mounts the ZIP file, it uses the embedded public key to:
- Verify the signature.
- Check the integrity of the ZIP file before executing it.
Generating ECC Keys with OpenSSL
If you don't have an ECC key pair, you can create one using the OpenSSL command-line tool:
# 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
- private_key.pem: Your private key used for signing the ZIP files.
- public_key.pem: The public key to be embedded in BAS for signature verification.
Bash Script to Sign a ZIP File
Below is a Bash script that demonstrates how to sign a ZIP file using OpenSSL:
#!/bin/bash
# Check if the correct number of arguments were passed
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <zipfile> <privatekey>"
exit 1
fi
# Input arguments
ZIP_FILE="$1"
PRIVATE_KEY="$2"
SIGNATURE_FILE="signature.bin"
echo "Creating the hash and signing the hash of the ZIP file using the ECC..."
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"
# Clean up the temporary signature file
rm "$SIGNATURE_FILE"
echo "Signature has been successfully appended to the ZIP file."
Usage Example:
./signzip.sh your_application.zip private_key.pem
This script performs the following actions:
- Creates the SHA-256 hash.
- Signs the SHA-256 hash of the ZIP file using your private key.
- Appends the signature to the end of the ZIP file without corrupting it.
- Cleans up any temporary files created during the process.
Note: Make sure to run the above script only once on a fresh ZIP file; otherwise, the verification process will fail.
How to Embed the Public Key in the Binary
You need to embed the public key into your application's binary to enable BAS to verify the signatures of your signed ZIP files. This ensures that the server can enforce authentication for all mounted ZIP files.
Steps to Embed the Public Key in Your Code
Convert the Public Key Using the SharkSSLParseKey command line tool
First, you need to convert your public key from PEM format to a format suitable for embedding in C code. Use the SharkSSLParseKey command line tool provided by the SharkSSL package.
SharkSSLParseKey public_key.pem
- public_key.pem: This is the PEM-formatted public key you generated earlier using OpenSSL.
This command will output an optimized version of your public key as a C array, which looks something like:
const U8 sharkSslPubECKey[72] = {
// SharkSSLParseKey produced data here
};
Embed the Public Key in Your Code
Copy the generated C array and paste it into your source code, where you initialize the BAS's Lua virtual machine.
// Paste the generated code here
const U8 sharkSslPubECKey[72] = {
// SharkSSLParseKey produced data here
};
// Configuration parameters for the Lua virtual machine
BaLua_param blp;
// Initialize the configuration parameters to zero
memset(&blp, 0, sizeof(blp));
// Assign the embedded public key to the zipPubKey parameter
blp.zipPubKey = sharkSslPubECKey;
// Proceed with initializing the Lua virtual machine as per your application logic
- BaLua_param: A structure that holds configuration parameters for the BAS Lua virtual machine.
- zipPubKey: A parameter within BaLua_param where you assign your embedded public key.
How to Enable ZIP File AES Password Protection
To securely encrypt ZIP files using AES, you must obfuscate the encryption key using the binpwd2str command line tool, which has been designed to generate passwords for your ZIP file and for being used by BAS. The binpwd2str tool creates three password types: one for being used with your AES-enabled ZIP tool, one binary file that can be used as a password when using io:setpasswd(), and C code designed to be embedded in your BAS startup code.
Steps to Enable a Global ZIP Password:
- Compile the binpwd2str tool: Ensure the binpwd2str command-line tool is compiled and ready to run.
- Generate the Password: Run binpwd2str to generate three versions of the password:
- A readable password for manual entry (to be used by your AES ZIP tool).
- A binary format suitable for programmatic use with Lua when calling io:setpasswd().
- C code for embedding the password in your BAS codebase, thus enabling automatic password management for encrypted files.
- Encrypt the ZIP File: Use an AES-enabled ZIP tool to encrypt the files containing sensitive data, such as configuration files or secrets. Use the readable password provided by binpwd2str.
- Embed the C Code in Your Startup Code: Insert the generated C code in your BAS startup sequence as shown in the example below:
// Paste the generated code here
const U8 zipBinPwd[] = {
// binpwd2str produced data here
};
// Configuration parameters for the Lua virtual machine
BaLua_param blp;
// Initialize the configuration parameters to zero
memset(&blp, 0, sizeof(blp));
blp.zipBinPwd = zipBinPwd;
blp.zipBinPwdLen = sizeof(zipBinPwd);
// Proceed with initializing the Lua virtual machine as per your application logic