Implementation:Duckdb Duckdb Extension Sign
| Field | Value |
|---|---|
| source | scripts/compute-extension-hash.sh, scripts/extension-upload-single.sh
|
| domains | Extension_Development, Security |
| last_updated | 2026-02-07 |
Overview
Concrete tool for cryptographically signing DuckDB extension binaries using OpenSSL and custom hash computation. This implementation uses two shell scripts: one to compute a composite SHA-256 hash of the extension binary, and another to orchestrate the full signing flow including hash computation, RSA signature generation, and signature embedding into the binary.
Code Reference
Hash Computation
Source: scripts/compute-extension-hash.sh (lines 1-19)
This script computes a composite SHA-256 hash of the extension binary using a chunked approach:
- The input file is split into 1 MB chunks
- Each chunk is individually hashed with
sha256sum - The hex-encoded hashes are concatenated into a single string
- The concatenated string is hashed once more with
sha256sumto produce the final digest
# Simplified logic from compute-extension-hash.sh
split -b 1048576 "$EXTENSION_FILE" chunk_
HASHES=""
for chunk in chunk_*; do
HASH=$(sha256sum "$chunk" | awk '{print $1}')
HASHES="${HASHES}${HASH}"
done
FINAL_HASH=$(echo -n "$HASHES" | sha256sum | awk '{print $1}')
Signing Flow
Source: scripts/extension-upload-single.sh (lines 40-70)
This section of the upload script handles the signing workflow:
- Calls
compute-extension-hash.shto obtain the composite hash - Writes the raw hash bytes to a temporary file
- Invokes
openssl pkeyutlto produce the RSA signature - Uses
ddto write the 256-byte signature into the signature placeholder region at the end of the binary (overwriting the zeroed placeholder from the metadata step)
# Simplified signing flow
HASH=$(scripts/compute-extension-hash.sh "$EXTENSION_PATH")
echo -n "$HASH" | xxd -r -p > hash.bin
# Generate 256-byte RSA signature
openssl pkeyutl -sign \
-in hash.bin \
-inkey private.pem \
-pkeyopt digest:sha256 \
-out signature.bin
# Write signature into the placeholder region at the end of the binary
# The signature placeholder starts at offset (filesize - 256 - footer_size)
dd if=signature.bin of="$EXTENSION_PATH" \
bs=1 seek=$SIGNATURE_OFFSET conv=notrunc
I/O Contract
API
Hash computation:
scripts/compute-extension-hash.sh <path_to_extension.duckdb_extension>
Full signing flow (within extension-upload-single.sh):
# The signing is performed as part of the upload script
# The private key is provided via environment variable
export DUCKDB_EXTENSION_SIGNING_PK="<base64-encoded-private-key>"
scripts/extension-upload-single.sh <extension_path> <platform> <version>
Standalone signing with OpenSSL:
openssl pkeyutl -sign \
-in hash.bin \
-inkey private.pem \
-pkeyopt digest:sha256 \
-out signature.bin
External Dependencies
| Tool | Purpose | Version |
|---|---|---|
openssl |
RSA signature generation and verification | 1.1+ or 3.x |
sha256sum |
SHA-256 hash computation for each chunk | GNU coreutils |
truncate |
File size manipulation during signing | GNU coreutils |
dd |
Writing signature bytes at a specific offset in the binary | GNU coreutils |
Inputs
- Built
.duckdb_extensionfile with metadata already appended (including the 256-byte zeroed signature placeholder) - RSA private key (PEM format), typically provided via the
DUCKDB_EXTENSION_SIGNING_PKenvironment variable
Outputs
- Signed
.duckdb_extensionfile where the 256-byte signature placeholder has been replaced with the actual RSA signature computed over the composite SHA-256 hash of the binary content
Usage Examples
Computing the extension hash:
# Compute composite hash for an extension binary
HASH=$(scripts/compute-extension-hash.sh \
build/release/extension/httpfs/httpfs.duckdb_extension)
echo "Composite hash: $HASH"
Signing an extension manually:
# Step 1: Compute hash
HASH=$(scripts/compute-extension-hash.sh httpfs.duckdb_extension)
echo -n "$HASH" | xxd -r -p > hash.bin
# Step 2: Sign with RSA private key
openssl pkeyutl -sign \
-in hash.bin \
-inkey private.pem \
-pkeyopt digest:sha256 \
-out signature.bin
# Step 3: Embed signature into the extension binary
dd if=signature.bin of=httpfs.duckdb_extension \
bs=1 seek=$(($(stat -c%s httpfs.duckdb_extension) - 256 - 32)) \
conv=notrunc
Signing via the upload script (CI/CD):
export DUCKDB_EXTENSION_SIGNING_PK="$(cat private_key_base64.txt)"
scripts/extension-upload-single.sh \
build/release/extension/httpfs/httpfs.duckdb_extension \
linux_amd64 \
v0.10.0