---
title: "Code signing"
slug: "code-signing"
updated: 2024-04-25T14:12:06Z
published: 2024-04-25T14:12:06Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://traceabledocs.document360.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Code signing

Traceable publishes many artifacts that run in your environment, such as docker images, archives, installers, and helm charts. To make sure that you are running the right and secure artifacts, Traceable provides you with an option to check the authenticity of such artifacts. The steps detailed in this topic are optional, and you should use them only when you wish to check the authenticity of artifacts.

Traceable provides the option to check the following artifacts:

- JAR
- Archive or any arbitrary file types
- Debian package
- RPM package
- Docker image
- Terraform archives
- Helm charts

### GPG key

Traceable provides a GPG public key that is available at [https://packages.traceable.ai/public-key.asc](https://packages.traceable.ai/public-key.asc). You can use the GPG public key to verify JARs, Debian distributions(apt, deb), rpm for centos7/8.

---

## Signing JARs

Traceable signs and publishes maven jar, which is signed via the Gradle Publish plugin. The Maven central server makes it mandatory to upload only signed JARs. The public key is available in key servers: `keyserver.ubuntu.com`, `keys.openpgp.org`, `pgp.mit.edu`.

---

## Archive checksum verification

#### Signing

With each archive, Traceable uploads its signature, for example:

**Archive-name** — `traceable-cli-1.8.7-macosx-x86_64.tar.gz`

**Signature** — `traceable-cli-1.8.7-macosx-x86_64.tar.gz.sig`

Note that it has the same path and name as the `.tar.gz` file it corresponds to but has the extension `.sig`

Following is a typical command to create a detached signature interactively:

```plaintext
$ gpg --detach-sign -o traceable-cli-1.8.7-macosx-x86_64.tar.gz.sig traceable-cli-1.8.7-macosx-x86_64.tar.gz
```

#### Verification

Download and install the `gpg` command using your package manager. For more information about `GnuPG`, see the [GnuPG website](https://www.gnupg.org/).

Import the Traceable AI GPG public key with the following commands:

```plaintext
# Download TraceableAI's public PGP key.
$ curl https://packages.traceable.ai/public-key.asc -o traceableai.asc

# Import the public key as referenced above, or available in full below.
$ gpg --import traceableai.asc
gpg: key CFFAC4BBE2B0C74E: public key "Traceable Inc. <support@traceable.ai>" imported
gpg: Total number processed: 1
gpg:               imported: 1

# Verify the public key ID and fingerprint with gpg
$ gpg --list-keys "Traceable"
pub   rsa4096 2023-12-27 [SC]
      95014EA2C6FC41273BC758DBCFFAC4BBE2B0C74E
uid           [unknown] Traceable Inc. <support@traceable.ai>
```

Download the signature file for the package you downloaded. It has the same path and name as the package it corresponds to but has the extension `.sig` . For example:

```plaintext
# Download the archive and signature files.
$ curl -Os https://downloads.traceable.ai/cli/release/1.8.7/traceable-cli-1.8.7-macosx-x86_64.tar.gz
$ curl -Os https://downloads.traceable.ai/cli/release/1.8.7/traceable-cli-1.8.7-macosx-x86_64.tar.gz.sig
```

Verify the signature by providing both the downloaded `.sig` and package names as parameters to the `gpg` command as shown below:

```plaintext
$ gpg --verify traceable-cli-1.8.7-macosx-x86_64.tar.gz.sig traceable-cli-1.8.7-macosx-x86_64.tar.gz
```

The output should look similar to the following:

```plaintext
gpg: Signature made Mon Jan 22 12:40:42 2024 IST
gpg:                using RSA key 95014EA2C6FC41273BC758DBCFFAC4BBE2B0C74E
gpg: Good signature from "Traceable Inc. <support@traceable.ai>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 9501 4EA2 C6FC 4127 3BC7 58DB CFFA C4BB E2B0 C74E
```

> [!NOTE]
> Note
> 
> The warning in the output is expected and doesn't indicate a problem. It occurs because there is a chain of trust missing between your personal PGP key (if you have one) and the Traceable AI PGP key. For more information, see [Web of trust](https://wikipedia.org/wiki/Web_of_trust).

---

## Linux package checksum verification

Traceable’s Linux repositories and packages are signed with the same GPG key. Follow the same procedure of key import as described in *Releases Archive Checksum Verification*.

### Debian/Ubuntu

#### Verification

**.deb binaries**

The Debian packages are signed using `debsigs`. You will need to install the program `debsig-verify` to verify the packages. Complete the following steps:

1. Install `debsigs`. Enter the following command:

```plaintext
sudo apt install debsig-verify
```
2. Download Traceable’s public key. Enter the following command:

```plaintext
curl https://packages.traceable.ai/public-key.asc -o traceableai.asc
```
3. Create directories to store `debsigs` policies and keyrings for Traceable’s public key. Enter the following command:

```plaintext
sudo mkdir -p /usr/share/debsig/keyrings/CFFAC4BBE2B0C74E/
sudo mkdir -p /etc/debsig/policies/CFFAC4BBE2B0C74E/
```
4. Initialize an empty keyring. Enter the following command:

```plaintext
sudo touch /usr/share/debsig/keyrings/CFFAC4BBE2B0C74E/debsig.gpg
```
5. Import Slack’s public key into the corresponding `debsigs` keyring. Enter the following command:

```plaintext
sudo gpg --no-default-keyring --keyring /usr/share/debsig/keyrings/CFFAC4BBE2B0C74E/debsig.gpg --import traceableai.asc
```
6. Create a new file in your editor of choice. Enter the following command:

```plaintext
/etc/debsig/policies/CFFAC4BBE2B0C74E/traceable.pol
```
7. Paste the following in the file that you created in the previous step. Save the file and exit the editor.

```xml
<?xml version="1.0"?>
<!DOCTYPE Policy SYSTEM "https://www.debian.org/debsig/1.0/policy.dtd">
<Policy xmlns="https://www.debian.org/debsig/1.0/">
<Origin Name="Traceable Inc" id="CFFAC4BBE2B0C74E" Description="Traceable Inc. support@traceable.ai"/>
<Selection>
    <Required Type="origin" File="debsig.gpg" id="CFFAC4BBE2B0C74E"/>
</Selection>
<Verification MinOptional="0">
    <Required Type="origin" File="debsig.gpg" id="CFFAC4BBE2B0C74E"/>
</Verification>
</Policy>
```
8. Check the package signature. Enter the following command:

```plaintext
debsig-verify traceable-cli-1.8.7.deb
```

The output should be similar:

```plaintext
debsig: Verified package from 'Traceable Inc. support@traceable.ai' (Traceable Inc)
```

**APT**

For all existing users, if the following changes are not done or yet to be done, they will see:

```plaintext
W: GPG error: https://packages.traceable.ai/ubuntu focal InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY CFFAC4BBE2B0C74E
```

To avoid the above problem and start verifying traceable apt repo, set the repository using the following:

```plaintext
$ sudo apt-get update
$ sudo apt-get install -y ca-certificates
# Download the public GPG key to /usr/share/keys/traceable.gpg
$ curl https://packages.traceable.ai/public-key.asc | gpg --dearmor -o /usr/share/keyrings/traceable.gpg
```

Install the Debian artifacts using the following `sources.list,` so that apt can only install verified packages.

```plaintext
sudo echo "deb [signed-by=/usr/share/keyrings/traceable.gpg] https://packages.traceable.ai/ubuntu/ focal main" | sudo tee -a /etc/apt/sources.list.d/traceable.list
```

Update apt again and install Traceable:

```plaintext
sudo apt-get update
sudo apt-get install -y traceable
```

---

### Red Hat/CentOS/Amazon Linux 2

### .rpm binaries

On RedHat-based Linux systems, validation is built into the `rpm` command; however, `rpm` does not use the GnuPG key store, so you first need to import the public key.

You can validate the signature as follows:

```plaintext
# Import the Public PGP key
$ rpm --import https://packages.traceable.ai/public-key.asc

# Verify the binary
$ rpm -qip traceable-1.0.0-1.el8.src.rpm
Name        : traceable
Version     : 1.0.0
Release     : 1.el8
Architecture: x86_64
Install Date: (not installed)
Group       : Unspecified
Size        : 477669023
License     : Traceable
Signature   : RSA/SHA256, Mon Jan  8 15:32:47 2024, Key ID cffac4bbe2b0c74e
Source RPM  : traceable-1.0.0-1.el8.src.rpm
Build Date  : Mon Jan  8 15:28:24 2024
Build Host  : 96d89d3a0cf4
Relocations : /etc /var/traceable/log /var/traceable/persistence 
Summary     : traceable agent
Description :
traceable agent

$ rpm --checksig -v traceable-1.0.0-1.el8.x86_64.rpm
traceable-1.0.0-1.el8.x86_64.rpm:
    Header V3 RSA/SHA256 Signature, key ID e2b0c74e: OK
    Header SHA1 digest: OK (2c4e67d8688a3ff4b2e500248a9fea416912c1d0)
    V3 RSA/SHA256 Signature, key ID e2b0c74e: OK
    MD5 digest: OK (b5e3e88056c2a7d5418fb596e0fa28ba)
```

### yum

If you are installing the packages using `yum`, it uses configuration files in `/etc/yum.repos.d` to specify a URL for the GPG key used to verify packages in that repository. If the key is not already available for verification, the utilities can import it.

Create a file named `/etc/yum.repos.d/traceable.repo` with the following content:

```plaintext
[traceable]
name=Traceable repository
baseurl=https://packages.traceable.ai/centos[7|8]/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.traceable.ai/public-key.asc
```

Make sure to change the base to match your OS. Replace [7|8] with the version of CentOS you are using. Execute `rpm -E %{rhel}` to fetch the CentOS version.

```plaintext
[traceable]
name=Traceable repository
baseurl=https://packages.traceable.ai/centos7/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.traceable.ai/public-key.asc
```

#### Install Traceable

Enter the following command:

```plaintext
sudo yum install traceable
```

---

## Docker image signing validation

This section describes how to use [Cosign](https://github.com/sigstore/cosign) to validate the provenance of Traceable’s image artifacts.

Cosign is a tool developed as part of the [sigstore](https://www.sigstore.dev/) project. It simplifies signing and validating signed Open Container Initiative (OCI) artifacts, such as container images.

We sign all officially published container images as part of our release process. End users can then verify these images using the process described below.

This process is suitable for either manual execution or integration with build or deployment pipelines to automate artifact verification.

### Before you begin

Complete the following steps:

1. Download the latest [Cosign](https://github.com/sigstore/cosign/releases/latest) build for your architecture, as well as its signature.
2. Validate the `cosign` binary signature:

```plaintext
$ openssl dgst -sha256 \
    -verify <(curl -ssL https://raw.githubusercontent.com/sigstore/cosign/main/release/release-cosign.pub) \
    -signature <(cat /path/to/cosign.sig | base64 -d) \
    /path/to/cosign-binary
```
3. Make the binary executable (`chmod +x`) and move to a location on the `PATH`

### Validating image

To validate a container image, do the following:

```plaintext
$ ./cosign verify --key "https://packages.traceable.ai/cosign.pub" traceableai/section-io-nginx:0.1.48 | jq .
```

This process will work for any released image or release candidate built with the Traceable’s build infrastructure.

Following is an example with output:

```json
Verification for index.docker.io/traceableai/section-io-nginx:0.1.48 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key
[
  {
    "critical": {
      "identity": {
        "docker-reference": "index.docker.io/traceableai/section-io-nginx"
      },
      "image": {
        "docker-manifest-digest": "sha256:661671eec49bb224603dcbe32c54c0bda18afbd2803af8aa78fb9888ec6b496b"
      },
      "type": "cosign container image signature"
    },
    "optional": {
      "Bundle": {
        "SignedEntryTimestamp": "MEQCIB/HA/V6kxekBKHLWhZQ0h7K5d1gO1SgnOawM8DIJv3vAiAmgqpQEa8PuIk8KzdFPYqQdXp/+R/kIMyLmzfNOWHf7w==",
        "Payload": {
          "body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1MjgzMjJkZmYxMTVmYTZiNjMyZWIxNmU0NDk4MDU5MWJjNmE2YjQ2YjUxYzkzOTZkNzg1ZGM4NThmMDdjMzVkIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRGpGZ3JMY2ZkeE55MzFGVDROazllNE1jTC9oYlovT1dDYk5tK2pOTDVCbEFpQmxGVmd1ZEFldVArenEvbDZkRFVBQTFwQ000WHBiTmdWUHVKS1k2Z3VybFE9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCUVZVSk1TVU1nUzBWWkxTMHRMUzBLVFVacmQwVjNXVWhMYjFwSmVtb3dRMEZSV1VsTGIxcEplbW93UkVGUlkwUlJaMEZGY2xwMFZsRlBhWEZMYm0wck5qaHdlR05EY214RWFYWnNlamxhS3dwYU5EWjZkM2ROTnprMmNWaGFNVUZUZGsxRGRXaFhVelJ4T0c0eldscDRkRmxSY25KdVpsUndlWEUyYVdkWWNEWnNhbFJZVkhZelMwRkJQVDBLTFMwdExTMUZUa1FnVUZWQ1RFbERJRXRGV1MwdExTMHRDZz09In19fX0=",
          "integratedTime": 1706695456,
          "logIndex": 67976224,
          "logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
        }
      },
      "SignedBy": "Traceable Inc. <support@traceable.ai>"
    }
  }
]
```

---

## Helm charts provenance

Traceable’s helm charts are signed using the same PGP key shared above. Import the Public PGP key using the following method:

```plaintext
# Download TraceableAI's public PGP key.
$ curl https://packages.traceable.ai/public-key.asc -o traceableai.asc
# Import the public key.
$ gpg --import traceableai.asc
$ gpg --export 'Traceable Inc' > ~/.gnupg/pubring.gpg
```

Alternatively, you may download and import Traceable’s public key from the Ubuntu keyserver with a command like this:

```plaintext
$ gpg --recv-keys --keyserver keyserver.ubuntu.com 95014EA2C6FC41273BC758DBCFFAC4BBE2B0C74E
```

### Verification

Integrity is established by comparing a chart to a provenance record. Provenance records are stored in provenance files, which are stored alongside a packaged chart. For example, if a chart is named `traceable-agent-1.42.1.tgz`, its provenance file will be `traceable-agent-1.42.1.tgz.prov`

Provenance files are generated at packaging time (helm package --sign ...) and pushed to our chart repository, which can be checked by multiple commands (The following steps assume you have the public key in binary format in `~/.gnupg/pubring.gpg`).

```plaintext
# Add traceableai helm repo
$ helm repo add traceableai https://helm.traceable.ai

# Update repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "traceableai" chart repository
Update Complete. ⎈Happy Helming!⎈

$ helm pull traceableai/traceable-agent
$ helm verify traceable-agent-1.41.2.tgz
Signed by: Traceable Inc. <support@traceable.ai>
Using Key With Fingerprint: 95014EA2C6FC41273BC758DBCFFAC4BBE2B0C74E
Chart Hash Verified: sha256:82c1614bb161084454cb9f7a41be91013c0ba8569a9af3da440a4b2c98cb80ac
```

The verification phase can also be integrated into the regular Helm commands we used so far. For example, to verify when we download a chart from the Internet or when installing a chart, we add the `--verify` parameter to the commands:

```plaintext
$ helm pull --verify NAME_OF_REPO/NAME_OF_CHART
$ helm pull --verify traceableai/traceable-agent
Signed by: Traceable Inc. <support@traceable.ai>
Using Key With Fingerprint: 95014EA2C6FC41273BC758DBCFFAC4BBE2B0C74E
Chart Hash Verified: sha256:cc550494ca57f2d00defc28db9b6d7a62dbc29442711b5e8b0524701fe33e35d

$ helm install --verify NAME_OF_RELEASE NAME_OF_CHART
```

#### Failed verification

If the signature verification fails, the installation phase is abandoned. In such a case, do not install charts you do not trust.

A failed verification may look like this:

```plaintext
$ helm verify --keyring ~/.gnupg/pubring.gpg altered-traceable-agent-1.32.1.tgz
Error: sha256 sum does not match for traceable-agent-1.32.1.tgz: "sha256:1939fbf7c1023d2f6b865d137bbb600e0c42061c3235528b1e8c82f4450c12a7" != "sha256:5a391a90de56778dd3274e47d789a2c84e0e106e1a37ef8cfa51fd60ac9e623a"
```

Or if the chart is unsigned/Provenance file is missing:

```plaintext
$ helm verify traceable-agent-1.40.1.tgz
Error: could not load provenance file traceable-agent-1.40.1.tgz.prov: stat traceable-agent-1.40.1.tgz.prov: no such file or directory
```

For more information, see [Helm | Helm Provenance and Integrity](https://helm.sh/docs/topics/provenance/).

---

## Terraform modules checksum verification

Traceable’s terraform modules are signed the same way as any other archive provided by Traceable. Follow *Releases Archive Checksum Signing & Verification*******instructions to sign and check integrity of the terraform modules.

```plaintext
# Download TraceableAI's public PGP key.
$ curl https://packages.traceable.ai/public-key.asc -o traceableai.asc

# Import the public key as referenced above, or available in full below.
$ gpg --import traceableai.asc

# Download a terraform module
$ curl -O https://downloads.traceable.ai/install/traceable-agent/terraform/kubernetes/latest/traceable-agent-tf-k8s.tar.gz

# Download the signature of the terraform archive
$ curl -O https://downloads.traceable.ai/install/traceable-agent/terraform/kubernetes/latest/traceable-agent-tf-k8s.tar.gz.sig

# Verify the signature
$ gpg --verify traceable-agent-tf-k8s.tar.gz.sig traceable-agent-tf-k8s.tar.gz
```

---

## Windows artifacts signing verification

The best way to verify if a Windows artifact is signed is via UI: right-click on the artifact and select the properties option. If the artifact is signed, there will be a digital signature tab in the properties dialog box. Check if the name of the signer is Traceable Inc.

![](https://cdn.document360.io/24f14f07-13d1-4684-8fae-6d8f811768ee/Images/Documentation/traceable_windows_artifacts_signing_verification.png)

In case you want to verify via command line tools, you can do so using Powershell.

```plaintext
$file = "C:\path\to\your\file.exe"

$signature = Get-AuthenticodeSignature $file
if ($signature -eq $null) {
    Write-Host "The file '$file' is not signed."
} else {
    Write-Host "The file '$file' is signed by:"
    $organization = $signature.SignerCertificate.Subject.Split(',')[1].TrimStart('O=')
    Write-Host $organization
}
```

A GPG (GNU Privacy Guard) public key is a cryptographic key used in public key encryption systems to encrypt data or verify digital signatures. GPG is an implementation of the OpenPGP standard designed for secure communication and data integrity.
