Faithful, zero-dependency PHP implementation of the OpenSSH SSHSIG signature format — the
signatures produced by ssh-keygen -Y sign and used for Git commit/tag signing and file
signing. It verifies signatures (parsing the armor and SSH wire format, then authorizing the
signer against an allowed_signers file, mirroring ssh-keygen -Y verify) and signs
messages with byte-output compatible with ssh-keygen -Y verify.
Fail-closed by design: anything malformed, unsupported, cryptographically invalid, or unauthorized throws — nothing is ever silently treated as verified.
composer require k2gl/sshsigRequires PHP 8.1+ with ext-sodium (Ed25519) and ext-openssl (RSA and ECDSA) — both are
bundled with most PHP builds.
This is the equivalent of ssh-keygen -Y verify -f allowed_signers -I <identity> -n <namespace>.
use K2gl\Sshsig\AllowedSigners;
use K2gl\Sshsig\Exception\SshsigException;
use K2gl\Sshsig\SshsigVerifier;
$verifier = new SshsigVerifier;
try {
$result = $verifier->verify(
message: file_get_contents('release.tar.gz'),
armoredSignature: file_get_contents('release.tar.gz.sig'),
allowedSigners: AllowedSigners::fromFile('allowed_signers'),
identity: 'alice@example.com',
namespace: 'file',
);
echo "Verified: {$result->publicKey->fingerprint()}\n";
} catch (SshsigException $e) {
// not verified — malformed, unsupported, bad signature, or unauthorized signer
echo "Rejected: {$e->getMessage()}\n";
}The equivalent of ssh-keygen -Y check-novalidate -n <namespace>: confirm the signature is
structurally sound and cryptographically valid under its own embedded key, then inspect it.
$signature = $verifier->checkNoValidate($message, $armoredSignature, namespace: 'git');
echo $signature->signatureAlgorithm; // e.g. "ssh-ed25519"
echo $signature->publicKey->fingerprint(); // "SHA256:…"Produce an SSHSIG signature (the ssh-keygen -Y sign operation). Provide the signing key —
Ed25519 (a 64-byte libsodium secret key) or an OpenSSL RSA/ECDSA private key:
use K2gl\Sshsig\Ed25519SigningKey;
use K2gl\Sshsig\OpensslSigningKey;
use K2gl\Sshsig\SshsigSigner;
// Ed25519
$keypair = sodium_crypto_sign_keypair();
$signer = new SshsigSigner(new Ed25519SigningKey(sodium_crypto_sign_secretkey($keypair)));
// …or RSA / ECDSA from an OpenSSL private key (PEM)
$signer = new SshsigSigner(OpensslSigningKey::fromPem(file_get_contents('id_rsa')));
$armored = $signer->sign($message, namespace: 'file'); // sha512 by default
file_put_contents('message.sig', $armored);
// the resulting signature verifies with `ssh-keygen -Y verify` and with this library$signer->publicKey() returns the matching SshPublicKey (e.g. to build an allowed_signers
line). The default hash is sha512; pass hashAlgorithm: 'sha256' to switch.
$allowed = AllowedSigners::fromString(<<<TXT
# comments and blank lines are ignored
alice@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA…
*@example.com namespaces="git,file" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA…
TXT);- Fail-closed. Every failure path throws a
K2gl\Sshsig\Exception\SshsigException(InvalidSignatureException,UnsupportedAlgorithmException,SignatureVerificationFailed,SignerNotAllowedException). A returned value always means verified. - Spec-faithful. Implements OpenSSH
PROTOCOL.sshsig: theSSHSIGmagic preamble, version 1, theto-be-signedblob (namespace + reserved + hash algorithm + message hash), and the armor. - Algorithms.
ssh-ed25519,rsa-sha2-256,rsa-sha2-512,ecdsa-sha2-nistp256/384/521;sha256andsha512message hashing. The legacy SHA-1ssh-rsasignature algorithm is refused. allowed_signers. Principals pattern-lists,namespaces=,valid-after/valid-beforevalidity windows, andcert-authorityentries (parsed and recorded; certificate-chain verification is not yet performed).- Signing.
SshsigSignerover a pluggableSigningKey(Ed25519 via ext-sodium; RSA and ECDSA via ext-openssl), producing armor byte-compatible withssh-keygen -Y verify. - Zero dependencies. Pure PHP over
ext-sodiumandext-openssl; nophpseclib. - Verified against OpenSSH. The test suite verifies real
ssh-keygen -Y signoutput for every supported algorithm, plus tampered, wrong-namespace, unauthorized, and malformed cases.
MIT. See LICENSE.