Skip to main content

Sigstore bundle format

· 7 min read
Daniel Bevenius
Maintainer

This post takes a look at Sigstore's bundle format which is the format of Sigstore's offline verification data.

Offline verification is described like this in busting-5-sigstore-myths:

Another common use case is that organizations need to run systems in air-gapped
environments with no outside network access. That means it’s not possible to
look up a signature in the transparency log, Rekor, right? Wrong! We use what’s
called "stapled inclusion proofs" by default, meaning you can verify an object
is present in the transparency log without needing to contact the transparency
log! The signer is responsible for gathering this evidence from the log and
presenting it alongside the artifact and signature. We store this in an OCI
image automatically, but you can treat it like a normal file and copy it around
for verification as well.

So, lets create a bundle and inspect the contents. First, we need to sign an artifact and in this case we are going to use a simple text file:

$ echo "some data" > artifact.txt

As mentioned, Sigstore can create a bundle, which contains all the information required for "stapled inclusion proofs". A bundle can be generated using the following command:

$ COSIGN_EXPERIMENTAL=1 cosign sign-blob --bundle=artifact.bundle artifact.txt
Using payload from: artifact.txt
Generating ephemeral keys...
Retrieving signed certificate...

Note that there may be personally identifiable information associated with this signed artifact.
This may include the email address associated with the account with which you authenticate.
This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.

Are you sure you want to continue? (y/[N]): y
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=online&client_id=sigstore&code_challenge=gGdRPWHb4ZNnBjRIEs9wbBhI3bqVriOCyq2W98YuqQ0&code_challenge_method=S256&nonce=2KGHDNf4CZ4gXINF9A12quVVxHl&redirect_uri=http%3A%2F%2Flocalhost%3A41711%2Fauth%2Fcallback&response_type=code&scope=openid+email&state=2KGHDOhtlyDhCegsNy1qPuKAWbd
Successfully verified SCT...
using ephemeral certificate:
-----BEGIN CERTIFICATE-----
MIICpzCCAi6gAwIBAgIUb6LDCNlvHnUGD55dbYuRq9BEB7gwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjMwMTEzMDcxMTIyWhcNMjMwMTEzMDcyMTIyWjAAMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZk/BAIoz2
GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyKOCAU0wggFJMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUdZPv
Pd5abMkW8mcBgb3umAmHTcUwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4Y
ZD8wJwYDVR0RAQH/BB0wG4EZZGFuaWVsLmJldmVuaXVzQGdtYWlsLmNvbTAsBgor
BgEEAYO/MAEBBB5odHRwczovL2dpdGh1Yi5jb20vbG9naW4vb2F1dGgwgYoGCisG
AQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynu
jgAAAYWp+AiYAAAEAwBHMEUCIAlfL870WJta7pD97Yiw0JbvY7YGg604cGxXEXtQ
tzoaAiEA+VWQiz+JPEsLBLbtclfhXFhn/C4kTyaS2Fj12+voTt4wCgYIKoZIzj0E
AwMDZwAwZAIwUtBB+1H6177KW3nfTpK9unSGgwIPEuNqQviJyeZRjkK85pnfk0p5
lwQVbfekXYq+AjBgJA/xjX5+UqRh+O1LqxBIun1gYhIwK+UUZq49SH0uP2sQL5un
ILHOPrBw0f00Q68=
-----END CERTIFICATE-----

tlog entry created with index: 11074687
Bundle wrote in the file artifact.bundle
MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=

After this there will be an file named artifact.bundle in the directory where the above command was executed.

So lets take a look at the bundle:

$ cat artifact.bundle | jq
{
"base64Signature": "MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=",
"cert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwekNDQWk2Z0F3SUJBZ0lVYjZMRENObHZIblVHRDU1ZGJZdVJxOUJFQjdnd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpNd01URXpNRGN4TVRJeVdoY05Nak13TVRFek1EY3lNVEl5V2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVEVHZMMFBSc3hveE1YZlNhWHUrN3cwb3ZWTnpaay9CQUlvejIKR0wyY1BZM3FaRU5VLytZclI5MkF1WkZYbjBqU21tdk9rdHBBekdobkRodGlkb25reUtPQ0FVMHdnZ0ZKTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVkWlB2ClBkNWFiTWtXOG1jQmdiM3VtQW1IVGNVd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0p3WURWUjBSQVFIL0JCMHdHNEVaWkdGdWFXVnNMbUpsZG1WdWFYVnpRR2R0WVdsc0xtTnZiVEFzQmdvcgpCZ0VFQVlPL01BRUJCQjVvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2Ykc5bmFXNHZiMkYxZEdnd2dZb0dDaXNHCkFRUUIxbmtDQkFJRWZBUjZBSGdBZGdEZFBUQnF4c2NSTW1NWkhoeVpaemNDb2twZXVONDhyZitIaW5LQUx5bnUKamdBQUFZV3ArQWlZQUFBRUF3QkhNRVVDSUFsZkw4NzBXSnRhN3BEOTdZaXcwSmJ2WTdZR2c2MDRjR3hYRVh0UQp0em9hQWlFQStWV1FpeitKUEVzTEJMYnRjbGZoWEZobi9DNGtUeWFTMkZqMTIrdm9UdDR3Q2dZSUtvWkl6ajBFCkF3TURad0F3WkFJd1V0QkIrMUg2MTc3S1czbmZUcEs5dW5TR2d3SVBFdU5xUXZpSnllWlJqa0s4NXBuZmswcDUKbHdRVmJmZWtYWXErQWpCZ0pBL3hqWDUrVXFSaCtPMUxxeEJJdW4xZ1loSXdLK1VVWnE0OVNIMHVQMnNRTDV1bgpJTEhPUHJCdzBmMDBRNjg9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
"rekorBundle": {
"SignedEntryTimestamp": "MEUCIQDYiu9WHR4eCJ2JGPCfwWYg/lILIM+9IvDEb3Nq2MYIUAIgK2tRLSYDLuU0uaywKy8C+3ETUBKfw1lds4Q4Bw4l8jQ=",
"Payload": {
"body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1YWEwM2Y5NmM3NzUzNjU3OTE2NmZiYTE0NzkyOTYyNmNjM2E5Nzk2MGU5OTQwNTdhOWQ4MDI3MWE3MzZkMTBmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJQmJmVnIwclJFZ2syeVhmRU5NelRkdVhuU1JjMkdrSkVVT2I1dEJuY0ZnU0FpRUF0QzRmMUNBNFlpbzlOM3dqZE1BYlk2aENlckNLd3lNK2huOEwxa24zM0dFPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTndla05EUVdrMlowRjNTVUpCWjBsVllqWk1SRU5PYkhaSWJsVkhSRFUxWkdKWmRWSnhPVUpGUWpkbmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5kMDFVUlhwTlJHTjRUVlJKZVZkb1kwNU5hazEzVFZSRmVrMUVZM2xOVkVsNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFVkhaTU1GQlNjM2h2ZUUxWVpsTmhXSFVyTjNjd2IzWldUbnBhYXk5Q1FVbHZlaklLUjB3eVkxQlpNM0ZhUlU1Vkx5dFpjbEk1TWtGMVdrWlliakJxVTIxdGRrOXJkSEJCZWtkb2JrUm9kR2xrYjI1cmVVdFBRMEZWTUhkblowWktUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZrV2xCMkNsQmtOV0ZpVFd0WE9HMWpRbWRpTTNWdFFXMUlWR05WZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBwM1dVUldVakJTUVZGSUwwSkNNSGRITkVWYVdrZEdkV0ZYVm5OTWJVcHNaRzFXZFdGWVZucFJSMlIwV1Zkc2MweHRUblppVkVGelFtZHZjZ3BDWjBWRlFWbFBMMDFCUlVKQ1FqVnZaRWhTZDJONmIzWk1NbVJ3WkVkb01WbHBOV3BpTWpCMllrYzVibUZYTkhaaU1rWXhaRWRuZDJkWmIwZERhWE5IQ2tGUlVVSXhibXREUWtGSlJXWkJValpCU0dkQlpHZEVaRkJVUW5GNGMyTlNUVzFOV2tob2VWcGFlbU5EYjJ0d1pYVk9ORGh5Wml0SWFXNUxRVXg1Ym5VS2FtZEJRVUZaVjNBclFXbFpRVUZCUlVGM1FraE5SVlZEU1VGc1prdzROekJYU25SaE4zQkVPVGRaYVhjd1NtSjJXVGRaUjJjMk1EUmpSM2hZUlZoMFVRcDBlbTloUVdsRlFTdFdWMUZwZWl0S1VFVnpURUpNWW5SamJHWm9XRVpvYmk5RE5HdFVlV0ZUTWtacU1USXJkbTlVZERSM1EyZFpTVXR2V2tsNmFqQkZDa0YzVFVSYWQwRjNXa0ZKZDFWMFFrSXJNVWcyTVRjM1MxY3pibVpVY0VzNWRXNVRSMmQzU1ZCRmRVNXhVWFpwU25sbFdsSnFhMHM0TlhCdVptc3djRFVLYkhkUlZtSm1aV3RZV1hFclFXcENaMHBCTDNocVdEVXJWWEZTYUN0UE1VeHhlRUpKZFc0eFoxbG9TWGRMSzFWVlduRTBPVk5JTUhWUU1uTlJURFYxYmdwSlRFaFBVSEpDZHpCbU1EQlJOamc5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLIn19fX0=",
"integratedTime": 1673593883,
"logIndex": 11074687,
"logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
}
}

So we have a json object with three fields, a base64Signature, a cert, and a rekorBundle field.

Lets start with base64Signature field:

$ cat artifact.bundle | jq '.base64Signature'
"MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE="

As the name of this field implies it contains a base64 encoded signature.

Lets be decode the signature and store it in a file:

$ cat artifact.bundle | jq -r '.base64Signature' | base64 -d - > signature

We will use this file shortly.

The cert field contains a base64 encoded certificate in pem format:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.signature.publicKey.content' | base64 -d -
-----BEGIN CERTIFICATE-----
MIICpzCCAi6gAwIBAgIUb6LDCNlvHnUGD55dbYuRq9BEB7gwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjMwMTEzMDcxMTIyWhcNMjMwMTEzMDcyMTIyWjAAMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZk/BAIoz2
GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyKOCAU0wggFJMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUdZPv
Pd5abMkW8mcBgb3umAmHTcUwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4Y
ZD8wJwYDVR0RAQH/BB0wG4EZZGFuaWVsLmJldmVuaXVzQGdtYWlsLmNvbTAsBgor
BgEEAYO/MAEBBB5odHRwczovL2dpdGh1Yi5jb20vbG9naW4vb2F1dGgwgYoGCisG
AQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynu
jgAAAYWp+AiYAAAEAwBHMEUCIAlfL870WJta7pD97Yiw0JbvY7YGg604cGxXEXtQ
tzoaAiEA+VWQiz+JPEsLBLbtclfhXFhn/C4kTyaS2Fj12+voTt4wCgYIKoZIzj0E
AwMDZwAwZAIwUtBB+1H6177KW3nfTpK9unSGgwIPEuNqQviJyeZRjkK85pnfk0p5
lwQVbfekXYq+AjBgJA/xjX5+UqRh+O1LqxBIun1gYhIwK+UUZq49SH0uP2sQL5un
ILHOPrBw0f00Q68=
-----END CERTIFICATE-----

We can inspect this certificate using openssl:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.signature.publicKey.content' | base64 -d - | openssl x509 -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
6f:a2:c3:08:d9:6f:1e:75:06:0f:9e:5d:6d:8b:91:ab:d0:44:07:b8
Signature Algorithm: ecdsa-with-SHA384
Issuer: O = sigstore.dev, CN = sigstore-intermediate
Validity
Not Before: Jan 13 07:11:22 2023 GMT
Not After : Jan 13 07:21:22 2023 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:0d:3b:cb:d0:f4:6c:c6:8c:4c:5d:f4:9a:5e:ef:
bb:c3:4a:2f:54:dc:d9:93:f0:40:22:8c:f6:18:bd:
9c:3d:8d:ea:64:43:54:ff:e6:2b:47:dd:80:b9:91:
57:9f:48:d2:9a:6b:ce:92:da:40:cc:68:67:0e:1b:
62:76:89:e4:c8
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
Code Signing
X509v3 Subject Key Identifier:
75:93:EF:3D:DE:5A:6C:C9:16:F2:67:01:81:BD:EE:98:09:87:4D:C5
X509v3 Authority Key Identifier:
keyid:DF:D3:E9:CF:56:24:11:96:F9:A8:D8:E9:28:55:A2:C6:2E:18:64:3F

X509v3 Subject Alternative Name: critical
email:daniel.bevenius@gmail.com
1.3.6.1.4.1.57264.1.1:
https://github.com/login/oauth
CT Precertificate SCTs:
Signed Certificate Timestamp:
Version : v1 (0x0)
Log ID : DD:3D:30:6A:C6:C7:11:32:63:19:1E:1C:99:67:37:02:
A2:4A:5E:B8:DE:3C:AD:FF:87:8A:72:80:2F:29:EE:8E
Timestamp : Jan 13 07:11:22.776 2023 GMT
Extensions: none
Signature : ecdsa-with-SHA256
30:45:02:20:09:5F:2F:CE:F4:58:9B:5A:EE:90:FD:ED:
88:B0:D0:96:EF:63:B6:06:83:AD:38:70:6C:57:11:7B:
50:B7:3A:1A:02:21:00:F9:55:90:8B:3F:89:3C:4B:0B:
04:B6:ED:72:57:E1:5C:58:67:FC:2E:24:4F:26:92:D8:
58:F5:DB:EB:E8:4E:DE
Signature Algorithm: ecdsa-with-SHA384
30:64:02:30:52:d0:41:fb:51:fa:d7:be:ca:5b:79:df:4e:92:
bd:ba:74:86:83:02:0f:12:e3:6a:42:f8:89:c9:e6:51:8e:42:
bc:e6:99:df:93:4a:79:97:04:15:6d:f7:a4:5d:8a:be:02:30:
60:24:0f:f1:8d:7e:7e:52:a4:61:f8:ed:4b:ab:10:48:ba:7d:
60:62:12:30:2b:e5:14:66:ae:3d:48:7d:2e:3f:6b:10:2f:9b:
a7:20:b1:ce:3e:b0:70:d1:fd:34:43:af
-----BEGIN CERTIFICATE-----
MIICpzCCAi6gAwIBAgIUb6LDCNlvHnUGD55dbYuRq9BEB7gwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjMwMTEzMDcxMTIyWhcNMjMwMTEzMDcyMTIyWjAAMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZk/BAIoz2
GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyKOCAU0wggFJMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUdZPv
Pd5abMkW8mcBgb3umAmHTcUwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4Y
ZD8wJwYDVR0RAQH/BB0wG4EZZGFuaWVsLmJldmVuaXVzQGdtYWlsLmNvbTAsBgor
BgEEAYO/MAEBBB5odHRwczovL2dpdGh1Yi5jb20vbG9naW4vb2F1dGgwgYoGCisG
AQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynu
jgAAAYWp+AiYAAAEAwBHMEUCIAlfL870WJta7pD97Yiw0JbvY7YGg604cGxXEXtQ
tzoaAiEA+VWQiz+JPEsLBLbtclfhXFhn/C4kTyaS2Fj12+voTt4wCgYIKoZIzj0E
AwMDZwAwZAIwUtBB+1H6177KW3nfTpK9unSGgwIPEuNqQviJyeZRjkK85pnfk0p5
lwQVbfekXYq+AjBgJA/xjX5+UqRh+O1LqxBIun1gYhIwK+UUZq49SH0uP2sQL5un
ILHOPrBw0f00Q68=
-----END CERTIFICATE-----

Lets store the certificate in a file, and extract the public key:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.signature.publicKey.content' | base64 -d -  > cert.pem
$ openssl x509 -pubkey -noout -in cert.pem > pub.pem

With those files, the signature, the public key, and the blob we should be able to verify the signature from the base64Signature field using the following command:

$ openssl dgst -verify pub.pem -keyform PEM -sha256 -signature signature -binary artifact.txt
Verified OK

The motivation of doing that was to show that the base64Signature is just the signature of the blob.

Next, lets take a look at the rekorBundle field:

$ cat artifact.bundle | jq -r '.rekorBundle' |  jq '.'
{
"SignedEntryTimestamp": "MEUCIQDYiu9WHR4eCJ2JGPCfwWYg/lILIM+9IvDEb3Nq2MYIUAIgK2tRLSYDLuU0uaywKy8C+3ETUBKfw1lds4Q4Bw4l8jQ=",
"Payload": {
"body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1YWEwM2Y5NmM3NzUzNjU3OTE2NmZiYTE0NzkyOTYyNmNjM2E5Nzk2MGU5OTQwNTdhOWQ4MDI3MWE3MzZkMTBmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJQmJmVnIwclJFZ2syeVhmRU5NelRkdVhuU1JjMkdrSkVVT2I1dEJuY0ZnU0FpRUF0QzRmMUNBNFlpbzlOM3dqZE1BYlk2aENlckNLd3lNK2huOEwxa24zM0dFPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTndla05EUVdrMlowRjNTVUpCWjBsVllqWk1SRU5PYkhaSWJsVkhSRFUxWkdKWmRWSnhPVUpGUWpkbmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5kMDFVUlhwTlJHTjRUVlJKZVZkb1kwNU5hazEzVFZSRmVrMUVZM2xOVkVsNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFVkhaTU1GQlNjM2h2ZUUxWVpsTmhXSFVyTjNjd2IzWldUbnBhYXk5Q1FVbHZlaklLUjB3eVkxQlpNM0ZhUlU1Vkx5dFpjbEk1TWtGMVdrWlliakJxVTIxdGRrOXJkSEJCZWtkb2JrUm9kR2xrYjI1cmVVdFBRMEZWTUhkblowWktUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZrV2xCMkNsQmtOV0ZpVFd0WE9HMWpRbWRpTTNWdFFXMUlWR05WZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBwM1dVUldVakJTUVZGSUwwSkNNSGRITkVWYVdrZEdkV0ZYVm5OTWJVcHNaRzFXZFdGWVZucFJSMlIwV1Zkc2MweHRUblppVkVGelFtZHZjZ3BDWjBWRlFWbFBMMDFCUlVKQ1FqVnZaRWhTZDJONmIzWk1NbVJ3WkVkb01WbHBOV3BpTWpCMllrYzVibUZYTkhaaU1rWXhaRWRuZDJkWmIwZERhWE5IQ2tGUlVVSXhibXREUWtGSlJXWkJValpCU0dkQlpHZEVaRkJVUW5GNGMyTlNUVzFOV2tob2VWcGFlbU5EYjJ0d1pYVk9ORGh5Wml0SWFXNUxRVXg1Ym5VS2FtZEJRVUZaVjNBclFXbFpRVUZCUlVGM1FraE5SVlZEU1VGc1prdzROekJYU25SaE4zQkVPVGRaYVhjd1NtSjJXVGRaUjJjMk1EUmpSM2hZUlZoMFVRcDBlbTloUVdsRlFTdFdWMUZwZWl0S1VFVnpURUpNWW5SamJHWm9XRVpvYmk5RE5HdFVlV0ZUTWtacU1USXJkbTlVZERSM1EyZFpTVXR2V2tsNmFqQkZDa0YzVFVSYWQwRjNXa0ZKZDFWMFFrSXJNVWcyTVRjM1MxY3pibVpVY0VzNWRXNVRSMmQzU1ZCRmRVNXhVWFpwU25sbFdsSnFhMHM0TlhCdVptc3djRFVLYkhkUlZtSm1aV3RZV1hFclFXcENaMHBCTDNocVdEVXJWWEZTYUN0UE1VeHhlRUpKZFc0eFoxbG9TWGRMSzFWVlduRTBPVk5JTUhWUU1uTlJURFYxYmdwSlRFaFBVSEpDZHpCbU1EQlJOamc5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLIn19fX0=",
"integratedTime": 1673593883,
"logIndex": 11074687,
"logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
}

SignedEntryTimestamp is a signature of the logIndex, the body, and the integratedTime time fields created by Rekor. We can inspect the Rekor log entry to verify:

$ curl --silent https://rekor.sigstore.dev/api/v1/log/entries?logIndex=11074687 | jq -r '.[]'
{
"body": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI1YWEwM2Y5NmM3NzUzNjU3OTE2NmZiYTE0NzkyOTYyNmNjM2E5Nzk2MGU5OTQwNTdhOWQ4MDI3MWE3MzZkMTBmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJQmJmVnIwclJFZ2syeVhmRU5NelRkdVhuU1JjMkdrSkVVT2I1dEJuY0ZnU0FpRUF0QzRmMUNBNFlpbzlOM3dqZE1BYlk2aENlckNLd3lNK2huOEwxa24zM0dFPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTndla05EUVdrMlowRjNTVUpCWjBsVllqWk1SRU5PYkhaSWJsVkhSRFUxWkdKWmRWSnhPVUpGUWpkbmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5kMDFVUlhwTlJHTjRUVlJKZVZkb1kwNU5hazEzVFZSRmVrMUVZM2xOVkVsNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZFVkhaTU1GQlNjM2h2ZUUxWVpsTmhXSFVyTjNjd2IzWldUbnBhYXk5Q1FVbHZlaklLUjB3eVkxQlpNM0ZhUlU1Vkx5dFpjbEk1TWtGMVdrWlliakJxVTIxdGRrOXJkSEJCZWtkb2JrUm9kR2xrYjI1cmVVdFBRMEZWTUhkblowWktUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZrV2xCMkNsQmtOV0ZpVFd0WE9HMWpRbWRpTTNWdFFXMUlWR05WZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBwM1dVUldVakJTUVZGSUwwSkNNSGRITkVWYVdrZEdkV0ZYVm5OTWJVcHNaRzFXZFdGWVZucFJSMlIwV1Zkc2MweHRUblppVkVGelFtZHZjZ3BDWjBWRlFWbFBMMDFCUlVKQ1FqVnZaRWhTZDJONmIzWk1NbVJ3WkVkb01WbHBOV3BpTWpCMllrYzVibUZYTkhaaU1rWXhaRWRuZDJkWmIwZERhWE5IQ2tGUlVVSXhibXREUWtGSlJXWkJValpCU0dkQlpHZEVaRkJVUW5GNGMyTlNUVzFOV2tob2VWcGFlbU5EYjJ0d1pYVk9ORGh5Wml0SWFXNUxRVXg1Ym5VS2FtZEJRVUZaVjNBclFXbFpRVUZCUlVGM1FraE5SVlZEU1VGc1prdzROekJYU25SaE4zQkVPVGRaYVhjd1NtSjJXVGRaUjJjMk1EUmpSM2hZUlZoMFVRcDBlbTloUVdsRlFTdFdWMUZwZWl0S1VFVnpURUpNWW5SamJHWm9XRVpvYmk5RE5HdFVlV0ZUTWtacU1USXJkbTlVZERSM1EyZFpTVXR2V2tsNmFqQkZDa0YzVFVSYWQwRjNXa0ZKZDFWMFFrSXJNVWcyTVRjM1MxY3pibVpVY0VzNWRXNVRSMmQzU1ZCRmRVNXhVWFpwU25sbFdsSnFhMHM0TlhCdVptc3djRFVLYkhkUlZtSm1aV3RZV1hFclFXcENaMHBCTDNocVdEVXJWWEZTYUN0UE1VeHhlRUpKZFc0eFoxbG9TWGRMSzFWVlduRTBPVk5JTUhWUU1uTlJURFYxYmdwSlRFaFBVSEpDZHpCbU1EQlJOamc5Q2kwdExTMHRSVTVFSUVORlVsUkpSa2xEUVZSRkxTMHRMUzBLIn19fX0=",
"integratedTime": 1673593883,
"logID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d",
"logIndex": 11074687,
"verification": {
"inclusionProof": {
"checkpoint": "rekor.sigstore.dev - 2605736670972794746\n6915767\nIDKYzW3/yaZoFrPpz2HKEReyArFz47FmWC3Z9REfsCY=\nTimestamp: 1673599771028600100\n\n— rekor.sigstore.dev wNI9ajBFAiBcmpywRj3UZCOMIzwlHzd5eNYEG1rQgX5VKhHAqM49iQIhAPxul/hYfn7wHRCh8/LTXFpLbB3vieU4mqLEPZSUdX4L\n",
"hashes": [
"e5871beb5d6ffc577b31f4b0f14763adb1a231d52f2f15dd8c44f4925e402d1d",
"1d2962738aaebe76a8497de8615fadb0b8a52db957ccfb37b87719131abb53bd",
"62c6f1d6610f123395faffd632dc853f682a7f1bd93e36c08e53f8591b2b50d7",
"c1bb29369643451e47467ce1293a981ee4bd00a019a0a5bf77dacfd0aa15eff7",
"fec4c3b5bfb7783f8eee0e83af6e781f49825efb515bd70b2745b4d15b0b56f5",
"aaee4f535cb2dca6853ab13d2f2eda182dd72aa708824d6281182009763e753e",
"22430b589e10029a924c4ec50a96b51fa0aff8b461b205dc9e02d3eb588bcd98",
"067da42bda7c3c476cbd160a7df567266e3c4788d38d214b44774907a1e1bd27",
"2269e80ae081e893a5e7a6350826b29bdf890afa397110c632910acf895e7a26",
"7c4a791951a23906049a3060ac3f29e571df225f0d7eadeb5417dff7631c8cec",
"3648d28ef4842a998b3f22755750e99a81a74d6567166831e325f044cde6162b",
"0cd1da2cb04f7956568f32c500bad03be8a022faa50f393c185ac5ac201f3339",
"a14a3e23a363f496dc96a3061d454e1f0629ea94c0664991d4e5eab4d29306cb",
"4c00279b889607cf1f98294f05dc3f10ffecd2a87df4af3e4360a039ff3421c9",
"35da85b3d8a823b9040af497f298dc7c517236e78a98b1b426251b9ecde33628",
"9d57b977c2a8ebeb68d127df7be605c849c732275a0b05db00264a59f4ca0834",
"9eb0417210c64dcc971f58268b5aaa968ce2c2d200c41b346f50a100728ebc72",
"e7d67f5102ddeda58eda651dcba76876d01955a4eca9fce4caaf9e0ba7521cdd",
"616429db6c7d20c5b0eff1a6e512ea57a0734b94ae0bc7c914679463e01a7fba",
"5a4ad1534b1e770f02bfde0de15008a6971cf1ffbfa963fc9c2a644973a8d2d1"
],
"logIndex": 6911256,
"rootHash": "203298cd6dffc9a66816b3e9cf61ca1117b202b173e3b166582dd9f5111fb026",
"treeSize": 6915767
},
"signedEntryTimestamp": "MEUCIGicHWGa0XI3perd9LM64+tdneXvvVsOrWxn7pCoUbuNAiEAjmgWIxOH8itbqYjAgkiilYmNVR/hewmfatviQZf3Wr8="
}
}

The Rekor log can also be accessed using https: https://rekor.tlog.dev/?logIndex=11074687

Now, lets inspect the body field of the bundle:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq
{
"apiVersion": "0.0.1",
"kind": "hashedrekord",
"spec": {
"data": {
"hash": {
"algorithm": "sha256",
"value": "5aa03f96c77536579166fba147929626cc3a97960e994057a9d80271a736d10f"
}
},
"signature": {
"content": "MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=",
"publicKey": {
"content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwekNDQWk2Z0F3SUJBZ0lVYjZMRENObHZIblVHRDU1ZGJZdVJxOUJFQjdnd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpNd01URXpNRGN4TVRJeVdoY05Nak13TVRFek1EY3lNVEl5V2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVEVHZMMFBSc3hveE1YZlNhWHUrN3cwb3ZWTnpaay9CQUlvejIKR0wyY1BZM3FaRU5VLytZclI5MkF1WkZYbjBqU21tdk9rdHBBekdobkRodGlkb25reUtPQ0FVMHdnZ0ZKTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVkWlB2ClBkNWFiTWtXOG1jQmdiM3VtQW1IVGNVd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0p3WURWUjBSQVFIL0JCMHdHNEVaWkdGdWFXVnNMbUpsZG1WdWFYVnpRR2R0WVdsc0xtTnZiVEFzQmdvcgpCZ0VFQVlPL01BRUJCQjVvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2Ykc5bmFXNHZiMkYxZEdnd2dZb0dDaXNHCkFRUUIxbmtDQkFJRWZBUjZBSGdBZGdEZFBUQnF4c2NSTW1NWkhoeVpaemNDb2twZXVONDhyZitIaW5LQUx5bnUKamdBQUFZV3ArQWlZQUFBRUF3QkhNRVVDSUFsZkw4NzBXSnRhN3BEOTdZaXcwSmJ2WTdZR2c2MDRjR3hYRVh0UQp0em9hQWlFQStWV1FpeitKUEVzTEJMYnRjbGZoWEZobi9DNGtUeWFTMkZqMTIrdm9UdDR3Q2dZSUtvWkl6ajBFCkF3TURad0F3WkFJd1V0QkIrMUg2MTc3S1czbmZUcEs5dW5TR2d3SVBFdU5xUXZpSnllWlJqa0s4NXBuZmswcDUKbHdRVmJmZWtYWXErQWpCZ0pBL3hqWDUrVXFSaCtPMUxxeEJJdW4xZ1loSXdLK1VVWnE0OVNIMHVQMnNRTDV1bgpJTEhPUHJCdzBmMDBRNjg9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
}
}
}

Now, when an online verification is done, that is when the bundle is not specified on the command line, the Rekor bundle is looked up in the transparency log. Notice for example that the same information is also available in the Rekor log:

$ curl --silent https://rekor.sigstore.dev/api/v1/log/entries?logIndex=11074687 | jq -r '.[].body' | base64 -d | jq
{
"apiVersion": "0.0.1",
"kind": "hashedrekord",
"spec": {
"data": {
"hash": {
"algorithm": "sha256",
"value": "5aa03f96c77536579166fba147929626cc3a97960e994057a9d80271a736d10f"
}
},
"signature": {
"content": "MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=",
"publicKey": {
"content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwekNDQWk2Z0F3SUJBZ0lVYjZMRENObHZIblVHRDU1ZGJZdVJxOUJFQjdnd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpNd01URXpNRGN4TVRJeVdoY05Nak13TVRFek1EY3lNVEl5V2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVEVHZMMFBSc3hveE1YZlNhWHUrN3cwb3ZWTnpaay9CQUlvejIKR0wyY1BZM3FaRU5VLytZclI5MkF1WkZYbjBqU21tdk9rdHBBekdobkRodGlkb25reUtPQ0FVMHdnZ0ZKTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVkWlB2ClBkNWFiTWtXOG1jQmdiM3VtQW1IVGNVd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d0p3WURWUjBSQVFIL0JCMHdHNEVaWkdGdWFXVnNMbUpsZG1WdWFYVnpRR2R0WVdsc0xtTnZiVEFzQmdvcgpCZ0VFQVlPL01BRUJCQjVvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2Ykc5bmFXNHZiMkYxZEdnd2dZb0dDaXNHCkFRUUIxbmtDQkFJRWZBUjZBSGdBZGdEZFBUQnF4c2NSTW1NWkhoeVpaemNDb2twZXVONDhyZitIaW5LQUx5bnUKamdBQUFZV3ArQWlZQUFBRUF3QkhNRVVDSUFsZkw4NzBXSnRhN3BEOTdZaXcwSmJ2WTdZR2c2MDRjR3hYRVh0UQp0em9hQWlFQStWV1FpeitKUEVzTEJMYnRjbGZoWEZobi9DNGtUeWFTMkZqMTIrdm9UdDR3Q2dZSUtvWkl6ajBFCkF3TURad0F3WkFJd1V0QkIrMUg2MTc3S1czbmZUcEs5dW5TR2d3SVBFdU5xUXZpSnllWlJqa0s4NXBuZmswcDUKbHdRVmJmZWtYWXErQWpCZ0pBL3hqWDUrVXFSaCtPMUxxeEJJdW4xZ1loSXdLK1VVWnE0OVNIMHVQMnNRTDV1bgpJTEhPUHJCdzBmMDBRNjg9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
}
}
}

Now, let first look at the spec.data.hash field which contains a hash algorithm that was used, and a value. The value is the hash of our blob, the artifact.txtfile:

$ sha256sum artifact.txt
5aa03f96c77536579166fba147929626cc3a97960e994057a9d80271a736d10f artifact.txt

And we can compare this with the value in the spec.data.hash.value field and check that they indeed are the same:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.data.hash.value'
5aa03f96c77536579166fba147929626cc3a97960e994057a9d80271a736d10f

Next we have signature field:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.signature.content'
MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=

Notice that this is the same value as the toplevel base64Signature field:

$ cat artifact.bundle | jq -r '.base64Signature'
MEUCIBbfVr0rREgk2yXfENMzTduXnSRc2GkJEUOb5tBncFgSAiEAtC4f1CA4Yio9N3wjdMAbY6hCerCKwyM+hn8L1kn33GE=

And there is also a publicKey field in the body which contains:

$ cat artifact.bundle | jq -r '.rekorBundle.Payload.body' | base64 -d - | jq -r '.spec.signature.publicKey.content' | base64 -d
-----BEGIN CERTIFICATE-----
MIICpzCCAi6gAwIBAgIUb6LDCNlvHnUGD55dbYuRq9BEB7gwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjMwMTEzMDcxMTIyWhcNMjMwMTEzMDcyMTIyWjAAMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEDTvL0PRsxoxMXfSaXu+7w0ovVNzZk/BAIoz2
GL2cPY3qZENU/+YrR92AuZFXn0jSmmvOktpAzGhnDhtidonkyKOCAU0wggFJMA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUdZPv
Pd5abMkW8mcBgb3umAmHTcUwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4Y
ZD8wJwYDVR0RAQH/BB0wG4EZZGFuaWVsLmJldmVuaXVzQGdtYWlsLmNvbTAsBgor
BgEEAYO/MAEBBB5odHRwczovL2dpdGh1Yi5jb20vbG9naW4vb2F1dGgwgYoGCisG
AQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynu
jgAAAYWp+AiYAAAEAwBHMEUCIAlfL870WJta7pD97Yiw0JbvY7YGg604cGxXEXtQ
tzoaAiEA+VWQiz+JPEsLBLbtclfhXFhn/C4kTyaS2Fj12+voTt4wCgYIKoZIzj0E
AwMDZwAwZAIwUtBB+1H6177KW3nfTpK9unSGgwIPEuNqQviJyeZRjkK85pnfk0p5
lwQVbfekXYq+AjBgJA/xjX5+UqRh+O1LqxBIun1gYhIwK+UUZq49SH0uP2sQL5un
ILHOPrBw0f00Q68=
-----END CERTIFICATE-----

Notice that this is the same certificate as the toplevel cert field. Using the base64Signature field, and the cert field we are able to verify a blob which we saw an example of previously.

Hopefully this has given some insight into the bundle format and given some example of how one can inspect the fields.