To understand phpseclib's X.509 API it first helps to consider what an X.509 certificate aims to do. So let's start off by decoding one.
Here's google.com's X.509 cert:
-----BEGIN CERTIFICATE----- MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0 ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q== -----END CERTIFICATE-----
Let's use phpseclib to decode that:
<?php include('File/X509.php'); $x509 = new File_X509(); $cert = $x509->loadX509('...'); print_r($cert); ?>
Specific values can be retrieved by accessing the appropriate array indices in $cert
or with the following (self-explanatory) functions:
getDNProp()
: See Distinguished Names for more information.getDN()
getIssuerDN()
getPublicKey()
: Returns a Crypt_RSA objectThe contents of $cert
are as follows:
$cert
:
-----BEGIN PUBLIC KEY----- MIGJAoGBAN63JkOmmYXNOKcVCbnPD8nDVYyI7oyNKCckSypeoNgW+mEYS89tYIDTNUAycsCPEtjl To+5svbZFV5ahjGjuoaqa8jZcYzMzScTHp1CXTj2p6zv+mLzGIHUJEZ/AXd8xiqJFJm7mDkdqBn7 OQBEfRuUangtaa3Aeiz60NogEpjTAgMBAAE= -----END PUBLIC KEY-----
When you connect to an HTTPS website you're given that website's public key via an X.509 certificate. The question is... how do you know that that public key hasn't, itself, been tampered with? SSH asks you if the certificate is valid upon your first connection attempt and alerts you when the certificate changes on subsequent connection attempts. HTTPS uses certificate authorities to verify the legitimacy of a public key. Certificate authorities have public keys as well, that are distributed via X.509 certificates. A website's X.509 certificate is signed by a certificate authorities private key and then verified by the certificate authorities public key.
$cert['tbsCertificate']['issuer']
:$cert['tbsCertificate']['subject']
:$cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
:$cert['signature']
:$rsa->sign($cert['tbsCertificate'])
with the certificate authorities private key.
Let's try to save that X.509 cert as is:
<?php include('File/X509.php'); $x509 = new File_X509(); $cert = $x509->loadX509('...'); echo $x509->saveX509($cert); ?>
Here's the result:
-----BEGIN CERTIFICATE----- MIIDITCCAoqgAwIBAgIQT52W2WawmStUwpV8tBV9TTANBgkqhkiG9w0BAQUFADBM MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0xMTEwMjYwMDAwMDBaFw0x MzA5MzAyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC gYEA3rcmQ6aZhc04pxUJuc8PycNVjIjujI0oJyRLKl6g2Bb6YRhLz21ggNM1QDJy wI8S2OVOj7my9tkVXlqGMaO6hqpryNlxjMzNJxMenUJdOPanrO/6YvMYgdQkRn8B d3zGKokUmbuYOR2oGfs5AER9G5RqeC1prcB6LPrQ2iASmNMCAwEAAaOB5zCB5DAM BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0 ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF AAOBgQAhrNWuyjSJWsKrUtKyNGadeqvu5nzVfsJcKLt0AMkQH0IT/GmKHiSgAgDp ulvKGQSy068Bsn5fFNum21K5mvMSf3yinDtvmX3qUA12IxL/92ZzKbeVCq3Yi7Le IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q== -----END CERTIFICATE-----
Great! So we have a valid X.509 cert, right? Not quite. Although it'll decode as one it's not going to properly validate. Even though nothing in the certificate has been changed (which one could do by editing the associative array) X.509 certificates have certain optional fields that when not present default to certain values. Some encoders may save these values explicitly, which would change the DER encoding of the tbsCertificate portion of the certificate which is what the signature is based off of.
To validate a cert that certs signing cert needs to be loaded. This can be done by calling $x509->loadCA('...')
. After that one need simply call $x509->validateSignature()
. Here's an example:
<?php include('File/X509.php'); $x509 = new File_X509(); $x509->loadCA('...'); $cert = $x509->loadX509('...'); echo $x509->validateSignature() ? 'valid' : 'invalid'; ?>
The certificate used to sign google.com's certificate is as follows:
-----BEGIN CERTIFICATE----- MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g 5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo 3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv -----END CERTIFICATE-----
Pass that cert into $x509->loadCA()
and then pass Certificate 1 into $x509->loadX509()
and the above code will output "valid". Use Certificate 2 and the above code will output "invalid".
Other validation methods are as follows:
$x509->validateSignature(FILE_X509_VALIDATE_SIGNATURE_BY_CA)
does not accept self-signed certs as being valid.$x509->validateURL()
$x509->validateDate()
validates against the current date.$x509->validateDate('June 1, 1983')
validates against June 1, 1983As Creating an X.509 cert fail demonstrated, simply saving an X.509 associative array is insufficient. The array needs to be properly signed. This can be done by calling $x509->sign($issuer, $subject)
.
The following is a discussion of the various options that can be set on each of the parameters in the $x509->sign($issuer, $subject)
call. Feel free to skip ahead to the example.
$issuer
properties consist of the following:
$cert['tbsCertificate']['issuer']
$issuer->setPrivateKey()
$cert['signature']
)$issuer->setKeyIdentifier()
. It's purpose is beyond the scope of this tutorial.id-ce-authorityKeyIdentifier
extension$subject
properties consist of the following:
$cert['tbsCertificate']['subject']
$subject->setPublicKey()
$cert['tbsCertificate']['subjectPublicKeyInfo']
$subject->setDomain()
$cert['tbsCertificate']['subject']
(id-at-commonName) and potentially the id-ce-subjectAltName
extension.$issuer->setKeyIdentifier()
. It's purpose is beyond the scope of this tutorial.id-ce-subjectKeyIdentifier
extension$x509
properties (ie. those that don't belong to either the $issuer
or $subject
consist of the following:
$x509->setStartDate()
. Accepts anything strtotime()
accepts. Defaults to the current time.$cert['tbsCertificate']['validity']['notBefore']['utcTime']
$x509->setEndDate()
. Accepts anything strtotime()
accepts. Defaults to one year from now$cert['tbsCertificate']['validity']['notAfter']['utcTime']
$x509->setSerialNumber()
. Defaults to 0.$cert['tbsCertificate']['serialNumber']
$x509->makeCA()
. Needs to be set if you want to import cert into browser as CA.id-ce-keyUsage
and id-ce-basicConstraints
<?php include('File/X509.php'); include('Crypt/RSA.php'); // create private key / x.509 cert for stunnel / website $privKey = new Crypt_RSA(); extract($privKey->createKey()); $privKey->loadKey($privatekey); $pubKey = new Crypt_RSA(); $pubKey->loadKey($publickey); $pubKey->setPublicKey(); $subject = new File_X509(); $subject->setPublicKey($pubKey); $subject->setDNProp('id-at-organizationName', 'phpseclib demo cert'); $subject->setDomain('www.whatever.com'); $issuer = new File_X509(); $issuer->setPrivateKey($privKey); $issuer->setDN($subject->getDN()); $x509 = new File_X509(); //$x509->setStartDate('-1 month'); // default: now //$x509->setEndDate('+1 year'); // default: +1 year //$x509->setSerialNumber(chr(1)); // default: 0 $result = $x509->sign($issuer, $subject); echo "the stunnel.pem contents are as follows:\r\n\r\n"; echo $privKey->getPrivateKey(); echo "\r\n"; echo $x509->saveX509($result); echo "\r\n";
The output of the above is as follows:
the stunnel.pem contents are as follows: -----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQCtYr+TcpSQ043ZZi+akC1LR5Q6MJPJ6/0MQ7IFPt/SCywaxsdFsNQ40+TOSFNk G68nscyB5nEPDkNzLJ7AklNSRHItqxTwohuW4a+fBfzAi0vXS9IrM2iep13cHE9r5QW9pouRQiYf bi5FegEWbtIc5SrmAxHAH9K3KGRaXEeufwIDAQABAoGAFijgwz+JrVjccESXIPH8V/q1/xnmSZBX rxGX1wPKJ1Y2NNXi8g0/kmPCgnrL7ad8I16d/JwvJvVzuWyifYo2C7++wHjPKvqTXgg7OiCai3KV O0y3r3xhVdvKOOmD42zPuPkHXSORrWP0wgH07pPThKRLmc2I1EuRtXzLvGrCOMECQQDbD7YRotnC biL7OzoFuzUKEpSN464LhdkTcDWeRUEvQQa/hTiKIeJ5aTdvyEOKBpuYzPTh6/79nBkgS7Lg5KtV AkEAyp9X06ZMXiOIFZszARddoALM1FXJkAVsa5T+pUJAscKU5JHFrgckk+D9snnYvR7eN5OMHOkP fH9yzKS4Zif6gwJABojicoY8HruwWXQ7193syB8jxVPMZlWY0yaewtjoB+PVsrLjq+M04VBNMg10 TlLCI33BtFeY5LHaYgdAD8tifQJBAKnBGZmuR2jPJ+HCJtcRNlUqQ2TZgobwpEb1iun1ObIzrP5Z yl3kihaCdsmiH51CUTYKnWZTM7BALnOYxQyBDfUCQQCI1JOGXOveAxsr4sP6vornAU/G7ekX2n9x LAjktKBd0pX25L9fdqrZPH61bOvF9S3VjuiX5vSp8OyUxoWMPbPn -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIB4zCCAU6gAwIBAgIAMAsGCSqGSIb3DQEBBTA5MRwwGgYDVQQKDBNwaHBzZWNsaWIgZGVtbyBj ZXJ0MRkwFwYDVQQDDBB3d3cud2hhdGV2ZXIuY29tMCIYDzIwMTIwNjA0MDMxMDMxWhgPMjAxMzA2 MDQwMzEwMzFaMDkxHDAaBgNVBAoME3BocHNlY2xpYiBkZW1vIGNlcnQxGTAXBgNVBAMMEHd3dy53 aGF0ZXZlci5jb20wgZ0wCwYJKoZIhvcNAQEBA4GNADCBiQKBgQCtYr+TcpSQ043ZZi+akC1LR5Q6 MJPJ6/0MQ7IFPt/SCywaxsdFsNQ40+TOSFNkG68nscyB5nEPDkNzLJ7AklNSRHItqxTwohuW4a+f BfzAi0vXS9IrM2iep13cHE9r5QW9pouRQiYfbi5FegEWbtIc5SrmAxHAH9K3KGRaXEeufwIDAQAB MAsGCSqGSIb3DQEBBQOBgQBYEsMuWBA9ie4ulXxeLhLoQvEo6vgl5LDRFMuP+AhkKzfXUo2yEMWP /QxbSglcPT/ycb+5+FhYGWxGatM5V+sB43ZBHZD14ZWPN35ePmDIfqXdRmphhXuhdNU7DWwp97ZR c26CQXzHurRf29VloV8k5JKwsfnLRPVCrbJySMB6dg== -----END CERTIFICATE-----
Distinguished Names can be set by any of the following functions:
$subject->loadX509('...')
will set the $subject
object to use the certificate subject's distinguished name as its own$subject->setDNProp('propName', 'propValue')
accepts propName's like id-at-commonName
(used in the X.509 specs) or CN
(used by OpenSSL as short hand)$subject->setDN('...')
takes stuff like $cert['tbsCertificate']['subject']
, the $code['subject']
output of $cert = openssl_x509_parse('...')
and full-on DN strings. eg:
C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com
$subject->loadCSR('...')
gets the distinguished name from a certificate signing request$subject->removeDNProp('propName')
Here we just create a self-signed cert and its corresponding private key, as above, that'll serve as the CA, and then another cert, signed by the CA, with a second private key to correspond to this second cert.
CA certs need to have $x509->makeCA()
called on them for browsers to accept them as certificate authorities.
<?php include('File/X509.php'); include('Crypt/RSA.php'); // create private key for CA cert // (you should probably print it out if you want to reuse it) $CAPrivKey = new Crypt_RSA(); extract($CAPrivKey->createKey()); $CAPrivKey->loadKey($privatekey); $pubKey = new Crypt_RSA(); $pubKey->loadKey($publickey); $pubKey->setPublicKey(); echo "the private key for the CA cert (can be discarded):\r\n\r\n"; echo $privatekey; echo "\r\n\r\n"; // create a self-signed cert that'll serve as the CA $subject = new File_X509(); $subject->setPublicKey($pubKey); $subject->setDNProp('id-at-organizationName', 'phpseclib demo CA'); $issuer = new File_X509(); $issuer->setPrivateKey($CAPrivKey); $issuer->setDN($CASubject = $subject->getDN()); $x509 = new File_X509(); $x509->setStartDate('-1 month'); $x509->setEndDate('+1 year'); $x509->setSerialNumber(chr(1)); $x509->makeCA(); $result = $x509->sign($issuer, $subject); echo "the CA cert to be imported into the browser is as follows:\r\n\r\n"; echo $x509->saveX509($result); echo "\r\n\r\n"; // create private key / x.509 cert for stunnel / website $privKey = new Crypt_RSA(); extract($privKey->createKey()); $privKey->loadKey($privatekey); $pubKey = new Crypt_RSA(); $pubKey->loadKey($publickey); $pubKey->setPublicKey(); $subject = new File_X509(); $subject->setPublicKey($pubKey); $subject->setDNProp('id-at-organizationName', 'phpseclib demo cert'); $subject->setDomain('www.google.com'); $issuer = new File_X509(); $issuer->setPrivateKey($CAPrivKey); $issuer->setDN($CASubject); $x509 = new File_X509(); $x509->setStartDate('-1 month'); $x509->setEndDate('+1 year'); $x509->setSerialNumber(chr(1)); $result = $x509->sign($issuer, $subject); echo "the stunnel.pem contents are as follows:\r\n\r\n"; echo $privKey->getPrivateKey(); echo "\r\n"; echo $x509->saveX509($result); echo "\r\n";
The output of the above is as follows:
the private key for the CA cert (can be discarded): -----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCeSAGfM4nHdIaBwThHYGW3MABTvrSMrawnGN/Mx5ttyLQF4YcUJFSpGAJ8y2hV iak3irbLtc6nlpJFOHtMB4VsuG7S+MySYKBm5l7eApfWynHMLKVml3URXCMVMXju4SxiI+D10nNO aq+eSEIFlPOY+7LgSdIAka6/9+z2hgoITQIDAQABAoGADS1RdT+FKOW6jPLZDJgp36ZPYKlvvoZ2 3opjl1jGx8z9r7+mzzZ3Fdy52EnW1cgwHj+eGDd6jNksNDcPjLTTlqfwoKMZhf1gpYBKA5PtnqFU rxM5eW3SzLWkPOZoS/i8fxze0uvoh0zcm6u1nictcjkj0Hqql4hbTrDRENxTfgECQQC9qYFWsH8q r/ztbl6WBxW1NT9JgthvteiINpAjeN9tmuP9BgTGPk4j3MhTVsPp5ogzdn3MLch2YJ9cJuEeHon1 AkEA1aSiiZwGH9tCI8EFJrDqbCqDgeOmlkgMp5YQ8TqBg6/nkM4wWz9cXSmFPO3L9BQhvXE8RlGJ DChCksbBcjnV+QJBALXZ7w+lz2iosYUejEahqGjFE1dyw//olXr1hiLc5K39E5kpyi4i012Ddfii etqsle9yL5A0Xb9TSblb9gGhGnkCQDyj8Gay3KIqMAnJ/dZPnRp6rr0titlZNg5TcBeojZ59TXMy s1MTFvpykJkMvjlXhYQqIfurpQTIYK0csUfk1rECQBPVqVAG45VBn6yV1cDaqvg/0aQ6yZc7nQTr 7aLuUCTaf/xP4wSWiQpGiRFdTLt3pkkI3XdngV6j8RCcpgED6qU= -----END RSA PRIVATE KEY----- the CA cert to be imported into the browser is as follows: -----BEGIN CERTIFICATE----- MIIBzzCCATqgAwIBAgIBATALBgkqhkiG9w0BAQUwHDEaMBgGA1UECgwRcGhwc2VjbGliIGRlbW8g Q0EwIhgPMjAxMjA1MDQwMzQxNDhaGA8yMDEzMDYwNDAzNDE0OFowHDEaMBgGA1UECgwRcGhwc2Vj bGliIGRlbW8gQ0EwgZ0wCwYJKoZIhvcNAQEBA4GNADCBiQKBgQCeSAGfM4nHdIaBwThHYGW3MABT vrSMrawnGN/Mx5ttyLQF4YcUJFSpGAJ8y2hViak3irbLtc6nlpJFOHtMB4VsuG7S+MySYKBm5l7e ApfWynHMLKVml3URXCMVMXju4SxiI+D10nNOaq+eSEIFlPOY+7LgSdIAka6/9+z2hgoITQIDAQAB oyMwITAOBgNVHQ8BAQAEBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQUDgYEAc31s EL3tWfwFIHYK+96wzvAS7F/4FCMcZOdrW9LZ1IniXUSf601MIOVy0pAc17Xf6QjlVOhziA3cLMi3 3CWwEDgnhXU8s6YRAa6WD8eeHwmJKE3vIU0+klscIdOO+14BrC+mRUoPaZ1hmixMvrK/pVhXAkef XTSk5kq9f2Bfm+M= -----END CERTIFICATE----- the stunnel.pem contents are as follows: -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQCBsisUty8OFR2gz3sweCoIfyzFWcvaTA55noaI6LXZMebI3iB7u5dJjsbI2yRh IgDaHBDVyu6R9W/NA9QFkKGoHmnnvHsEo8Jc9Ca3nVIfjVBUj+kGMnadUtHoxZaRXLdwV9nX+LCa rfEz9VDS21BOJJ6OzUmvvkM0AUkGQlmcnwIDAQABAoGAN2+c63dbNRVAe0aEHNUX/lbBn79Am5fL zh882RNC+0nRoAUV9F1cDpRpElxdAemjXJcHeSKK87dpaMOcoh5Ogi2rXXgB++igxNdx19+z4Ku1 A1JG0O08Z/n7DQQb5g+V4Z9oIorpfufh7lIj4HgDLoznCj2lWq6SpzWobmtYnC0CQQDJDjYDRJRR ujepI6yz+9ckD6Jr2AwjSrdQKUPMzeexlTQgDqW/Jec5k3dS1zcvM+FctzNfnp9LyK/CABFYLb6r AkEApSOpwpzAsL1rDUqdV3iBEPPBmLLeTef4+pyggGGYFeu+TR3hNrHZPphXi6F/c+kmt7kDWgq1 K3QZPQkadXgJ3QJAF5Bb0jw6ae26Uk+FET8l8usGLT+QBJ7gJzv+30UOr6h+CHfPAz0tAXmAFax1 okmhUx2BnuZXYyltN/6MCdqqqwJAVqU5owTADXu1OYoWuBhgD9b1kvr2rQWzmzqm8/VA6O+CL9An pJz4EWG5PWgFCXoheHA4k/veRuhpfZ7TJSNQeQJAFVH1RQYAYOTVyyXYbUJnXEbVnEYeTVUKLJmx VSmAwFxx6s/EHVmiDH/WPgV4NkZt7gW7epkqoz3gfTDWYfx8Qg== -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- MIIBxTCCATCgAwIBAgIBATALBgkqhkiG9w0BAQUwHDEaMBgGA1UECgwRcGhwc2VjbGliIGRlbW8g Q0EwIhgPMjAxMjA1MDQwMzQxNDhaGA8yMDEzMDYwNDAzNDE0OFowNzEcMBoGA1UECgwTcGhwc2Vj bGliIGRlbW8gY2VydDEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wgZ0wCwYJKoZIhvcNAQEBA4GN ADCBiQKBgQCBsisUty8OFR2gz3sweCoIfyzFWcvaTA55noaI6LXZMebI3iB7u5dJjsbI2yRhIgDa HBDVyu6R9W/NA9QFkKGoHmnnvHsEo8Jc9Ca3nVIfjVBUj+kGMnadUtHoxZaRXLdwV9nX+LCarfEz 9VDS21BOJJ6OzUmvvkM0AUkGQlmcnwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzWpz47IfG6vWf5WlN R+iTEBwr8kKJOop38otzxwGBvYk7YBHI2DZW0tivpceN7JjkhpkBUNd+vg/qQSp0UVp38MrVR0cw ZP0iAJmLHTq/Jpymrqpz3Cn0bvKFvmYvzHgy9bjS5dy8AuFZY16qieNJovrV2c4dnCh4xo2c+MbK Ig== -----END CERTIFICATE-----