sceau v1.3.0
Installation
Using your favourite package manager:
pnpm add -D sceau
yarn add -D sceau
npm install -D sceauCLI usage
First off, you'll need a signature private key.
Keygen
You can generate one from the CLI:
$ sceau keygen
Run the following command in your terminal to use this private key:
export SCEAU_PRIVATE_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
Associated public key:
0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefThis will give you an environment variable definition for the private key, and the associated public key.
Note about keys: The underlying signature is Ed25519, which stores the public key as part of the private key.
If you misplace your public key, it can be obtained from the private key: the public key is the LAST half (64 hex characters) of the private key.
Signing packages
To sign a package, run the following command:
$ sceau signThis will:
- Collect a list of files to be published (based on the
filesoption in package.json and the .npmignore file) - Hash and sign each file into a manifest
- Inject some metadata, like:
- A URL to the JSON schema of the resulting file, serving as a version identifier
- The current time
- A permalink to the sources (see CI usage)
- A permalink to the build process (see CI usage)
- Sign the whole thing
- Store it in a
sceau.jsonfile next to package.json
CI usage
Links to source and build process are injected to provide transparency and traceability to a package being built.
The idea is that the signing step would occur in a public CI/CD context.
You can specify the URLs to the sources and build process either via the command-line, or via environment variables:
| CLI argument | Environment variable | Description |
|---|---|---|
--source | SCEAU_SOURCE_URL | Permalink to the source code |
--build | SCEAU_BUILD_URL | Permalink to the build process |
Note: those two URLs are automatically populated for you if sceau runs in a GitHub Actions context. PRs for more CI contributions are welcome!
If those are not provided, sceau will still sign your package, but the URLs
will be set to unknown://local.
Sceau will write to a file, but will also print to the standard output, so this signature process can be audited by third parties.
Setting up package.json
Because sceau should run right before NPM packs your artifacts to publish them,
you should run the signature step in the prepack script:
{
"files": [
// ...
"sceau.json"
],
"scripts": {
"prepack": "sceau sign"
}
}Note that it's also required to add sceau.json to the list of files, otherwise
the signature would be left behind when your package is packed.
Options
--packageDir lets you specify a path to a pacakge to sign.
By default, sceau will try to look for a package to sign at the current working
directory.
--file lets you choose the output file (defaults to sceau.json). It should
be a path relative to the package directory (where package.json is located).
Example:
$ sceau sign --packageDir packages/my-package --file build/signature.jsonThis will sign package <cwd>/packages/my-package, and store the output at
<cwd>/packages/my-package/build/signature.json.
--ignore lets you specify RegExp patterns to match against file paths.
Files matching those patterns won't be included in the manifest and therefore
won't be part of the final signature.
Note that the output file is always automatically included in those patterns.
Verifying
You can verify a package signed with sceau using the following command:
$ sceau verify --packageDir path/to/packageOptions
You should provide the public key to verify a signature against, obtained from a trusted source (ideally one not under GitHub's or NPM's control, in case those were to be compromised).
$ sceau verify --publicKey 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefIf the package uses a non-standard <packageDir>/sceau.json signature file,
you can specify its location (relative to the package directory):
$ sceau verify --file build/signature.jsonBy default, calling verify on an unsigned package will only print that fact and exit cleanly. If you expect a package to be signed, you can use strict verification, that will fail on unsigned packages:
$ sceau verify --strictProgrammatic usage
Sceau can be imported as a library (ESM only).
You can access the commands using the same arguments as the CLI:
import {
generateKeyPair,
signCommand,
verifyCommand,
SCEAU_FILE_NAME,
} from 'sceau'
// Random keypair
const { publicKey, privateKey } = await generateKeyPair()
// Seeded keypair
const { publicKey, privateKey } = await generateKeyPair('baadf00d...')
await signCommand({
file: SCEAU_FILE_NAME,
quiet: true,
privateKey: '...', // will default to SCEAU_PRIVATE_KEY env if unspecified
packageDir: 'packages/my-package',
build: 'https://url-to-build-process.example.com',
source: 'https://url-to-sources.example.com',
})
await verifyCommand({
file: SCEAU_FILE_NAME,
strict: true,
packageDir: 'packages/my-package',
publicKey: '...', // will default to SCEAU_PUBLIC_KEY env if unspecified
})Examples
Sceau signs itself when released.
You can verify a sceau install (using itself too):
sceau verify --strict --publicKey c30d5d28b88136c77168fb78bf117948127c4e22f987ab60cd083bbd6c7ac0c9We use semantic-release, which injects the NPM package version just
before publishing. In order to sign the final package.json file,
we run sceau sign as the prepack lifecycle hook.
The private key is passed as an environment variable to the calling step (semantic-release).
Cryptography
Cryptography is provided by libsodium.
- Hash: BLAKE2b, 64 byte output, no key, default parameters
- Signature: Ed25519ph (SHA-512 pre-hash), with manifest header.
See signature.ts for more details.
About the name
Sceau is French for seal (the ones found on letters, not in oceans).
It's pronounced like so.
License
MIT - Made with ❤️ by François Best
Using this package at work ? Sponsor me to help with support and maintenance.
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago