This document describes a method for producing cryptographically
signed tar files.
The suggested file extension is stf
.
Any files can be placed inside a tar archive, excluding symlinks and other shenanigans. Just plain files.
There are two reserved filenames inside the tar:
_manifest
_manifest.sig
The _manifest
is a plain-text ASCII file, listing the SHA-256
hashes of the files and the public key fingerprint of the
public key used to sign the manifest.
An example _manifest
file might look like:
[manifest]
key=751306bfafae00f2417a7b7c7b7750e263838dc1
84784533571ed086a3cdff9fd41f89b43863a7314660442616fd02ee51a9608b=file.ext
3de4c18609d8069edf84538a0b4d27140565b72f894c35701a3a737353cb5fe3=folder path/file.ext
The file starts with the header [manifest]
.
The property key
is the hash of the public key used to sign
the manifest.
Following this is a list of all files inside the tar archive, except the two manifest files. The "property" is the SHA-256 hash of the file, and the "value" is the file name.
File naming restrictions:
- The filename uses all characters after the
=
up to the end of the line. - The file name is constructed using the normal unix syntax of a forward
slash (
/
) as the folder separator.
The file structure inside the tar archive for the above manifest would look something like this:
package.tar/
_manifest
_manifest.sig
file.ext
folder path/
file.ext
The _manifest.sig
is a binary signature file. The signature is generated
by taking the SHA-256 of the _manifest
file and signing the hash
with the public key.
In the above example _manifest
file, the SHA-256 hash would be:
3656ad41d1c95306d324c827faf88bce354a4f27c0ba220c60cd10baa4ec8e99
This hash is signed, and the signature and stored in binary format as
the _manifest.sig
file.
Where the phrase public key
, private key
, or key pair
is used, it is meant
an asymmetric RSA key pair.
The bit length of the RSA key must be at least 2048 bits.
Where the phrase hash
or digest
is used, it is meant the SHA-256
hashing
algorithm as specified in FIPS PUB 180-2, encoded to lower-case hexadecimal.
Where a key hash is specified, it is meant the PGP fingerprint.
Where a PGP fingerprint is used, it is the complete V4 fingerprint as specified in RFC 4880, encoded to lower-case hexadecimal, with no spaces or semicolons.
E.g., cd92815bf6273acbaf834b9faed277c722068291
.
Where the phrase "session key" is used, it is meant an AES compatible key of at least 256 bits.
A complete example is found in the example module.
The files named file.ext
are simply random bytes
generated using random.org.
First start by generating an OpenPGP key. In this example we use GPG.
Create a new key:
gpg --gen-key
Select the option RSA and RSA
, and then select a bit size
of at least 2048 bits
.
In this example the expiration date does not matter, so we
will select 0 = key does not expire
.
For this example we use the name:
John Doe (Example user) <john.doe@email.com>
And the password:
abc.123.my.super.secret.password
In order for you to follow this demo and verify the outputs, the keys generated for this example were exported to an example folder using the following commands:
Public key:
gpg --armor --export john.doe@email.com
Private key:
gpg --armor --output demo_key.asc --export-secret-keys John
Using GPG and generating a "detached" signature is equivalent
to generating the file hash and signing it. Therefore, signing
the _manifest
file is done:
gpg --detach-sign _manifest
GPG automatically generates the signature file named _manifest.sig
.
Together these files are placed inside the folder such that the folder looks like:
package/
_manifest
_manifest.sig
file.ext
folder path/
file.ext
This folder is packaged together as a tar archive, with the appropriate file extension:
tar -cvf package.stf package
Or alternately, as a tar+gzip file:
tar -zcvf package.stf.gz package