Skip to main content
Version: 4.0

SPKAC

SPKAC is an acronym for Signed Public Key and Challenge, a lesser used CSR format without distinguished names or extensions.

Reading SPKACs

use phpseclib4\File\SPKAC;

$spkac = SPKAC::load(file_get_contents('spkac.txt'));

print_r($spkac);
(download spkac.txt)

$spkac, in this case, is a SPKAC object which, in turn, is basically a thin wrapper around an instance of \phpseclib4\File\ASN1\Constructed. Passing $spkac through print_r() or var_dump() triggers the __debugInfo() magic method which, in turn, produces the following output:

publicKeyAndChallenge
spki
phpseclib4\Crypt\RSA\PublicKey
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM00BBEr4iRFui8QRALkTZ/yJj
TbVsemyekfIYlIsmqolpgkhXNkXv2RNSkM8yWGS7+45YEo2Vb3X98/2z+8j4b24c
eB5g0Z6B/RXc6EpvHnX1GYMYofsfjP2U3is8qYWvuzPvmc7xD+QOb6wF5p9FXSOG
jXmnuljjPaeLwAF3AwIDAQAB
-----END PUBLIC KEY-----
challenge
phpseclib4\File\ASN1\Types\IA5String
123456789
signatureAlgorithm
algorithm
phpseclib4\File\ASN1\Types\OID
md5WithRSAEncryption
signature
phpseclib4\File\ASN1\Types\BitString
0087c883aa51d5b4ab0bb1592122cc7999efbe0ef13ce3a208f44069aaf1b3e87dacfcdeb2bb494fc843848ecc74ea5679fa15dad0fc252027fad40045e72a6f9e79e81f6fd2c21d5182c9499dd822de9edec249bcd9534af9cf810d2cb7802180ecfb0dc59382145b150528f2e4da998764f0d3b0ef0f3c4934a65a9e29262df4

All elements and subelements of the above SPKAC object can be accessed as array elements vis-a-vis ArrayAccess. As a consequence of this there are two ways to get (for example) the public key. You could do $spkac['publicKeyAndChallenge']['spki'] or you could do $spkac->getPublicKey(). It's these helper functions that set the SPKAC class apart from \phpseclib4\File\ASN1\Constructed.

To learn more about the capabilities afforded to the SPKAC class by virtue of it being a thin wrapper around \phpseclib4\File\ASN1\Constructed please refer to Deep Dive: ASN1\Constructed Objects.

getPublicKey()

echo $spkac->getPublicKey();

Returns a \phpseclib4\Crypt\Common\PublicKey object that, by default, gets cast to a PKCS8-encoded public key:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM00BBEr4iRFui8QRALkTZ/yJj
TbVsemyekfIYlIsmqolpgkhXNkXv2RNSkM8yWGS7+45YEo2Vb3X98/2z+8j4b24c
eB5g0Z6B/RXc6EpvHnX1GYMYofsfjP2U3is8qYWvuzPvmc7xD+QOb6wF5p9FXSOG
jXmnuljjPaeLwAF3AwIDAQAB
-----END PUBLIC KEY-----

Note that if the key is in an unsupported format then $spkac->getPublicKey() will throw a UnexpectedValueException. If you want to see what the public key is, regardless of whether or not it's in a supported format, then you can do $spkac['publicKeyAndChallenge']['spki'].

Very rarely, SPKACs may not have a public key at all. You can test for this by doing $spkac->hasPublicKey(), which returns a boolean based on whether or not the SPKAC in question has a public key or not.

getChallenge()

$spkac->getChallenge() is a shorthand way of getting $spkac['publicKeyAndChallenge']['challenge'].

Creating SPKACs

Minimalistic SPKAC

Consider the following:

use phpseclib4\File\SPKAC;

$spkac = new SPKAC();
echo $spkac;

The SPKAC that that would produce would look something like this:

SPKAC=MBYwDDAIMAMGAQADAQAWADADBgEAAwEA

This SPKAC has no public key, no challenge and no signature.

If you did print_r($spkac) on that SPKAC you'd get this:

publicKeyAndChallenge
spki
algorithm
algorithm
phpseclib4\File\ASN1\Types\OID
0.0
subjectPublicKey
phpseclib4\File\ASN1\Types\BitString
00
challenge
phpseclib4\File\ASN1\Types\IA5String
signatureAlgorithm
algorithm
phpseclib4\File\ASN1\Types\OID
0.0
signature
phpseclib4\File\ASN1\Types\BitString
00

Setting the Public Key

Let's say you created your public key thusly:

use phpseclib4\Crypt\EC;

$private = EC::createKey('nistp256');
$public = $private->getPublicKey();

At this point you could set the public key for the SPKAC using one of two techniques:

$spkac = new SPKAC($public);
echo $spkac;
$spkac = new SPKAC();
$spkac->setPublicKey($public);
echo $spkac;

You can also remove a public key be calling $spkac->removePublicKey().

Setting the Challenge

The challenge can be set by calling $spkac->setChallenge() and passing a string to that function. It can also be set by setting $spkac['publicKeyAndChallenge']['challenge'] to a string.

Note that the challenge field is an IA5String (7-bit ASCII), so setChallenge() silently ANDs each byte of the input with 0x7F to clamp it into the 7-bit range. If you pass a UTF-8 challenge with multi-byte characters, you'll get back a clamped 7-bit version rather than an error. For interoperability, pass plain ASCII.

Signing

Let's say you created your public key thusly:

use phpseclib4\Crypt\EC;

$private = EC::createKey('nistp256');
$public = $private->getPublicKey();

At that point you can sign your SPKAC like so:

$spkac = new SPKAC($public);
// do stuff
$private->sign($spkac);
echo $spkac;

Note that $pfx->sign($spkac) works syntactically but is unusual: an SPKAC is signed by the requester (proving they control the private key corresponding to the embedded public key), whereas a PFX represents a CA's signing identity. In normal flows you'd use a bare PrivateKey to sign an SPKAC.

Validating Signatures

SPKAC's are always self-signed and can be validated thusly:

$spkac = SPKAC::load('...');
echo $spkac->validateSignature() ? 'valid' : 'invalid';