The certificate that comes back to the gateway url is one long string; for example,
MIICoDCCAgmgAwIBAQIFA6LWuW0wDQYJKoZIhvcNAQEEBQAwgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhOZXcgWW9yazEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTEcMBoGA1UEChMTQ29sdW1iaWEgVW5pdmVyc2l0eTENMAsGA1UECxMEQWNJUzEjMCEGA1UEAxMaQ29sdW1iaWEgVW5pdmVyc2l0eSBDT0QgQ0ExJTAjBgkqhkiG9w0BCQEWFmNlcnQtYXV0aEBjb2x1bWJpYS5lZHUwHhcNMDAxMjA1MjIwOTQ4WhcNMDAxMjA1MjIxNDQ4WjB2MQ8wDQYDVQQDEwZhcmllbDAxDTALBgNVBAsTBEFjSVMxHDAaBgNVBAoTE0NvbHVtYmlhIFVuaXZlcnNpdHkxFjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuX72G1Ck%2f01n8djOuLjI6Q10JvWhVcDj9jz6ezdOlhMXbzxtgd8rkaGFr7ZPilOgbLbFfabJZx2HVymlM6%2fUrTWCpQG2THjKWD%2bB5pAc0%2bEgOyNwDHQfbSFB7XhGjox1Qfvl%2f29euHclE6Zl0T%2bdqVrvE%2fPF9cwgLtcgPIMZJOkCAwEAATANBgkqhkiG9w0BAQQFAAOBgQA4ht3AHWyuxKEXf%2fRB8vrsCG0%2f31%2f42YYjrgH%2fUiCt2PpRMJ%2fYH6sd7Wu%2bC5f%2fU8lww1JXYNKIBloZ2FWj6C3aPvdJr19WOZDeMyrKyTX4JGSnEuz9KRYzDYbSwHtM5uq%2frG1l1gUbxeI4AzbjsWsRcbZWjaLmjrozf3tpdwsDig%3d%3d
Notice also that it is url-encoded, as all variables received by a cgi script are.
In order to convert this to PEM format, you will need to url-decode it, add line feeds every 64th character, and add the BEGIN and END headers that PEM requires.
So your certificate would look something like this:
-----BEGIN CERTIFICATE----- MIICoDCCAgmgAwIBAQIFA6LWuW0wDQYJKoZIhvcNAQEEBQAwgbExCzAJBgNVBAYT AlVTMREwDwYDVQQIEwhOZXcgWW9yazEWMBQGA1UEBxMNTmV3IFlvcmsgQ2l0eTEc MBoGA1UEChMTQ29sdW1iaWEgVW5pdmVyc2l0eTENMAsGA1UECxMEQWNJUzEjMCEG A1UEAxMaQ29sdW1iaWEgVW5pdmVyc2l0eSBDT0QgQ0ExJTAjBgkqhkiG9w0BCQEW FmNlcnQtYXV0aEBjb2x1bWJpYS5lZHUwHhcNMDAxMjA1MjIwOTQ4WhcNMDAxMjA1 MjIxNDQ4WjB2MQ8wDQYDVQQDEwZhcmllbDAxDTALBgNVBAsTBEFjSVMxHDAaBgNV BAoTE0NvbHVtYmlhIFVuaXZlcnNpdHkxFjAUBgNVBAcTDU5ldyBZb3JrIENpdHkx ETAPBgNVBAgTCE5ldyBZb3JrMQswCQYDVQQGEwJVUzCBnzANBgkqhkiG9w0BAQEF AAOBjQAwgYkCgYEAuX72G1Ck/01n8djOuLjI6Q10JvWhVcDj9jz6ezdOlhMXbzxt gd8rkaGFr7ZPilOgbLbFfabJZx2HVymlM6/UrTWCpQG2THjKWD+B5pAc0+EgOyNw DHQfbSFB7XhGjox1Qfvl/29euHclE6Zl0T+dqVrvE/PF9cwgLtcgPIMZJOkCAwEA ATANBgkqhkiG9w0BAQQFAAOBgQA4ht3AHWyuxKEXf/RB8vrsCG0/31/42YYjrgH/ UiCt2PpRMJ/YH6sd7Wu+C5f/U8lww1JXYNKIBloZ2FWj6C3aPvdJr19WOZDeMyrK yTX4JGSnEuz9KRYzDYbSwHtM5uq/rG1l1gUbxeI4AzbjsWsRcbZWjaLmjrozf3tp dwsDig== -----END CERTIFICATE-----
This PEM-format certificate is just base-64 encoding of the der-encoded raw certificate if you get rid of the line breaks and the headers again. Some (i.e. most) libraries will read PEM-formatted certificates directly, so putting it back into this form may be helpful; a sample (lousy) perl routine to do this is below.
sub convertcert2pem {
my($cert) = @_;
local $pemcertheader="-----BEGIN CERTIFICATE-----\n";
local $pemcertfooter="-----END CERTIFICATE-----\n";
local $pemcertbody=addlinebreaks($cert);
local $pemcert = $pemcertheader.$pemcertbody.$pemcertfooter;
return($pemcert);
}
sub addlinebreaks {
my($cert)=@_;
local $ll=64;
local $certbody="";
local $temp="";
while (length($cert)>$ll) {
$temp=substr($cert,0,$ll);
$certbody = $certbody.$temp."\n";
$cert=substr($cert,$ll);
}
$certbody = $certbody.$cert."\n";
return($certbody);
}
I said that PEM encoding is base 64 encoding of a der-encoded object. DER stands for Distinguished Encoding Rules, and it describes a method of uniquely representing any given digital object as a binary string once the object can be described in the so-called ASN.1 (Abstract Syntax Notation).
The raw certificate is not readable; a cat -v which shows all of the control characters and so on as literal would display something like
0M-^B^B10M-^B^AM-^Z^B^E^BM-&^@^@^A0^M^F *M-^FHM-^FM-w^M^A^A^B^E^@0_1^K0 ^F^CU^D^F^S^BUS1^W0^U^F^CU^D
^S^NVeriSign, Inc.1705^F^CU^D^K^S.Class 4 Public Primary Certification Authority0^^^W^M960129000000Z^W^M991231235959Z0_1^K0 ^F^CU^D^F^S^BUS1^W0^U^F^CU^D
^S^NVeriSign, Inc.1705^F^CU^D^K^S.Class 4 Public Primary Certification Authority0M-^AM-^_0^M^F *M-^FHM-^FM-w^M^A^A^A^E^@^CM-^AM-^M^@0M-^AM- ^BM-^AM-^A^@M-PM-2uM-vxM-PM-.ZPM-tM-iPM-)M-^_M-
M-WM-oM-^QM-^TpM-hM-R$M-^PvM- M-^EM-VM-_M-,M-f^A^W2M-^@M-pM-^]M-^SGM-^CM-jM-RM-^J$M-Q
which admittedly is not very enlightening.
In order to parse this thing you need to understand the structure of the certificate. The X.509 v3 spec says that the syntax for a certificate is as follows:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING }
TBSCertificate ::= SEQUENCE {
version [0] Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version shall be v2 or v3
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
-- If present, version shall be v2 or v3
extensions [3] Extensions OPTIONAL
-- If present, version shall be v3 -- }
You'll want to pay particular attention to the subject and extensions fields. The rest of the fields are useful for validation (for example) but most libraries have some routine that will do basic certificate validation for you.
Here is the definition for the subject field:
Name ::= CHOICE { -- only one possibility for now --
rdnSequence RDNSequence }
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
DistinguishedName ::= RDNSequence
RelativeDistinguishedName ::=
SET SIZE (1 .. MAX) OF AttributeTypeAndValue
AttributeTypeAndValue ::= SEQUENCE {
type AttributeType,
value AttributeValue }
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY
which is not all that helpful either. But generally this boils down to a sequence
of things that usually has in it oid and value pairs for the fields CommonName,
OrganizationalUnit, Organization, Locality, StateOrProvince, and Country. You'll
want to extract the CommonName field and look at the value.
And here is the definition for the extensions field:
extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING }
This is what we use to pack all the things into a certificate that didn't make it into the forst x.509 spec. The oid tells you what sort of thing it is, and the octet string contains.... the der-encoded value. That means, that for example, if you have an octet string which you want to put as a value into an extension, you der-encode the octet string *again* as an octet string (that's right, it would be double-encoded) and then stuff it in a sequence after its oid.
For more details about these oids, octet strings, and der-encoding and so on you had probably better look at the ASN.1 introduction and overview which is part fo some old SSLeay docs I have lying around. There is a pointer to the Layman's Guide to ASN.1 off of that page, which you will also want to read if you have to dig seriously into the guts of the certificate (for example, if your library doesn't have a mechanism for retrieving an arbitrary extension from the certificate getting its oid).