c++encodingx509certificatesmartcard

How to convert a certificate from a GIDS card into a crt file?


I'm working on some low level Android software for a smart card reader. I'm trying to add support for GIDS devices and am having some trouble using the certificates that I'm able to pull from the card.

PIV cards store the certificates in such a way that converting from hex to byte array provides an array that openSSL recognizes.

The same process isn't working for the certificate files from the GIDS card which is recovered as the following hex string.

DF2482042E0100930478DA336862E93768622A6712895C5DA3A0EF71AAE4A82C0F93FC0
98EA3BC86396F0C78D938B5DA3CDABEF3323272B33218541A721B70B23187B2B0093385
061BF21A7083381C3C2CFE1999F9868206FC202E3B0F87737E4E696E5269B1A180011F4
8888B87DD35B7A028B3381526C2CCC35E925A5CA29B9C68A862A004B78593514C342935
AFB0B824312F27B5D2213D373133472F393FD7404E9CD7C8C8C0DCC8D4D0CCC0D0C0220
AC83536040A40B9068D7D94BB8D1FE85FA008370F5B6E7E52664EAAA1888110C4B1DCC9
3999A97940E7A6169510E9E0264625E4E0636465606E62E467008A7331353132321CFA3
27FE982EDE7E2004004259C61009CF833FD6631E9B78A67EA705E167C1839FBE79F8917
EDDD6F26591E56FBE9BE325FF850A9CEDA25E95D3AB377DEE1E03678B5C5EE6DE626C3
C669DD01AF5A393E05AFBAFF78EBBF67E1E99EFBCDB9EFBD9EB56661D2D450A3F72FD9
599A7DD7FDFF7425C6E75FF4B7A6E525C1A9011E5BF7C69D4BF55EA7EDBF7286F9FAFF
394E07976A261E923F78472E20727F7BE2D613EAD73C9F4D8AE7652DB89DADBF4C6D79
C84FF3D65B534FA4F054F42C90A9D9D9F875DF17855ED32FD5697B7607EFCA150ADFF7
E3C4C7731C367A37FC637FCE1714FBC89599CD52EA7132C0ED55D33A833F2CCE21DE22B
DC22C851585524AA5055782ECEE9C7EBA4EF48DCFDEFE2E0020FEF833FD6631E9B78A67
EA705E167C1839FBE79F8917EDDD6F26591E56FBE9BE325FF850A9CEDA25E95D3AB377D
EE1E03678B5C5EE6DE626C3C669DD01AF5A393E05AFBAFF78EBBF67E1E99EFBCDB9EFBD
9EB56661D2D450A3F72FD9599A7DD7FDFF7425C6E75FF4B7A6E525C1A9011E5BF7C69D4
BF55EA7EDBF7286F9FAFF394E07976A261E923F78472E20727F7BE2D613EAD73C9F4D8A
E7652DB89DADBF4C6D79C84FF3D65B534FA4F054F42C90A9D9D9F875DF17855ED32FD56
97B7607EFCA150ADFF7E3C4C7731C367A37FC637FCE1714FBC89599CD52EA7132C0ED55
D33A833F2CCE21DE22BDC22C851585524AA5055782ECEE9C7EBA4EF48DCFDEFE2E00400
4D7FBAF3833093231333230A22530E6262646863D9D674B3ECB46DD2F7FACF3F190C2BA
A8AA8D87ED2DDD8C77256FDAF7558449D2533EE727EF97D2270DF2EDAFEF8BBED45E513
B7FFAD64AF5D5BF1B7FEA245CF9F3C48EFBCBA53D1B4F2F107AA53B7DDADC734C1B18CB
4ED86DF0765DB92E82A74486834DDBF5E8849F8F79EB7F5FBA1EB5E6C9C4BC306BD5430
E97197AECAB9CCF181FBBA251B8F1FAE3C32797D92CB25BB8E3D42B83B553D6DAF557CA
38CE9CB954E778BB43E96D4E3ED9A012B9BB67BCBFFF3B34277A6569135BBD45E482A37
36CEDAFA92F33BFB769A34579DDEEF0258EF21C0ED7A758313DF53DEF792FDBA8D1D384
A35F23E3D2DDE72B19004004D70496DC8E5A6673E1EB17C36DF327C835F6D8C5BCDBB0F
E44917F6100F3866D7D5B8A1E3ED1AE293DDA3321F07C4DF814EBCDF5D3EFEF89FAFD5C
72DA2426FE1329317C2FEC3955CD2EF07F105B68B43F2CEACE46AF99A691DAB37345A71
854CDDE227DE6EAB99BACE5B593EE68D81D0E3876877FCBEA68DE987B02CA69F3852747
EA1EF6F09F782BB3E296C19113EACA4FE746B04EE05CB079CBF72B1F15B973C257DD8BA
9E9F75D39B9F4DBEA4F1D2F1FA6319EE4B4797B59F87E84F4E9BCFDA6AB7DEBBCED35A5
B7AB6D69D3DB1C1C9651E16AD6F0CAF2A59E6AD9DE59473516DA1B72331C9A9471DCAF8
9F907D35CE15711DB6BF3259A75334EE6C430EE460020FE96DC8E5A6673E1EB17C36DF3
27C835F6D8C5BCDBB0FE44917F6100F3866D7D5B8A1E3ED1AE293DDA3321F07C4DF814E
BCDF5D3EFEF89FAFD5C72DA2426FE1329317C2FEC3955CD2EF07F105B68B43F2CEACE46
AF99A691DAB37345A71854CDDE227DE6EAB99BACE5B593EE68D81D0E3876877FCBEA68D
E987B02CA69F3852747EA1EF6F09F782BB3E296C19113EACA4FE746B04EE05CB079CBF7
2B1F15B973C257DD8BA9E9F75D39B9F4DBEA4F1D2F1FA6319EE4B4797B59F87E84F4E9B
CFDA6AB7DEBBCED35A5B7AB6D69D3DB1C1C9651E16AD6F0CAF2A59E6AD9DE59473516DA
1B72331C9A9471DCAF89F907D35CE15711DB6BF3259A75334EE6C430EE460040043BBDB
87DEB9DEACD41DA728722263C3D62EC2F7A4C91D9FA61CF6D272B6679CD4DF773857C04
67C5DCDB7977F6FAEBFD0063BED744

TL;DR summary: I need to turn the above hex code into an x509 certificate in Java. Read below for some additional research I've done.

I dug around in OpenSC's pkcs15-tool.c code and found that they are doing some pretty involved manipulation to the data. I'm not well-versed in C/C++ though, so I had a hard time following it.

parse_x509_cert from pkcs15-cert.c

static int
parse_x509_cert(sc_context_t *ctx, struct sc_pkcs15_der *der, struct sc_pkcs15_cert *cert)
{
    int r;
    struct sc_algorithm_id sig_alg;
    struct sc_pkcs15_pubkey *pubkey = NULL;
    unsigned char *serial = NULL, *issuer = NULL, *subject = NULL, *buf =  der->value;
    size_t serial_len = 0, issuer_len = 0, subject_len = 0, data_len = 0, buflen = der->len;
    struct sc_asn1_entry asn1_version[] = {
        { "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, &cert->version, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_extensions[] = {
        { "x509v3",     SC_ASN1_OCTET_STRING,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL| SC_ASN1_ALLOC, &cert->extensions, &cert->extensions_len },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_tbscert[] = {
        { "version",        SC_ASN1_STRUCT,    SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_version, NULL },
        { "serialNumber",   SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, &serial, &serial_len },
        { "signature",      SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
        { "issuer",     SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &issuer, &issuer_len },
        { "validity",       SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
        { "subject",        SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &subject, &subject_len },
        /* Use a callback to get the algorithm, parameters and pubkey into sc_pkcs15_pubkey */
        { "subjectPublicKeyInfo",SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki_fields,  &pubkey },
        { "extensions",     SC_ASN1_STRUCT,    SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_extensions, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_cert[] = {
        { "tbsCertificate", SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert, NULL },
        { "signatureAlgorithm", SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, &sig_alg, NULL },
        { "signatureValue", SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_serial_number[] = {
        { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_subject[] = {
        { "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };
    struct sc_asn1_entry asn1_issuer[] = {
        { "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
        { NULL, 0, 0, 0, NULL, NULL }
    };

    const u8 *obj;
    size_t objlen;

    LOG_FUNC_CALLED(ctx);

    memset(cert, 0, sizeof(*cert));
    obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &objlen);
    if (obj == NULL)
        LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found");

    data_len = objlen + (obj - buf);
    cert->data.value = malloc(data_len);
    if (!cert->data.value)
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
    memcpy(cert->data.value, buf, data_len);
    cert->data.len = data_len;

    r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL);
    cert->key = pubkey;
    cert->version++;

    LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 parsing of certificate failed");

    if (!pubkey)
        LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert");


    if (serial && serial_len)   {
        sc_format_asn1_entry(asn1_serial_number + 0, serial, &serial_len, 1);
        r = sc_asn1_encode(ctx, asn1_serial_number, &cert->serial, &cert->serial_len);
        LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of serial failed");
    }

    if (subject && subject_len)   {
        sc_format_asn1_entry(asn1_subject + 0, subject, &subject_len, 1);
        r = sc_asn1_encode(ctx, asn1_subject, &cert->subject, &cert->subject_len);
        LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of subject");
    }

    if (issuer && issuer_len)   {
        sc_format_asn1_entry(asn1_issuer + 0, issuer, &issuer_len, 1);
        r = sc_asn1_encode(ctx, asn1_issuer, &cert->issuer, &cert->issuer_len);
        LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of issuer");
    }

err:
    /* not used for anything */
    sc_asn1_clear_algorithm_id(&sig_alg);
    free(serial);
    free(subject);
    free(issuer);

    LOG_FUNC_RETURN(ctx, r);
}

sc_asn1_verify_tag method:

const u8 *sc_asn1_verify_tag(sc_context_t *ctx, const u8 * buf, size_t buflen,
                 unsigned int tag_in, size_t *taglen_out)
{
    return sc_asn1_skip_tag(ctx, &buf, &buflen, tag_in, taglen_out);
}

sc_asn1_skip_tag method:

const u8 *sc_asn1_skip_tag(sc_context_t *ctx, const u8 ** buf, size_t *buflen,
               unsigned int tag_in, size_t *taglen_out)
{
    const u8 *p = *buf;
    size_t len = *buflen, taglen;
    unsigned int cla = 0, tag;

    if (sc_asn1_read_tag((const u8 **) &p, len, &cla, &tag, &taglen) != SC_SUCCESS
            || p == NULL)
        return NULL;
    switch (cla & 0xC0) {
    case SC_ASN1_TAG_UNIVERSAL:
        if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_UNI)
            return NULL;
        break;
    case SC_ASN1_TAG_APPLICATION:
        if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_APP)
            return NULL;
        break;
    case SC_ASN1_TAG_CONTEXT:
        if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_CTX)
            return NULL;
        break;
    case SC_ASN1_TAG_PRIVATE:
        if ((tag_in & SC_ASN1_CLASS_MASK) != SC_ASN1_PRV)
            return NULL;
        break;
    }
    if (cla & SC_ASN1_TAG_CONSTRUCTED) {
        if ((tag_in & SC_ASN1_CONS) == 0)
            return NULL;
    } else
        if (tag_in & SC_ASN1_CONS)
            return NULL;
    if ((tag_in & SC_ASN1_TAG_MASK) != tag)
        return NULL;
    len -= (p - *buf);  /* header size */
    if (taglen > len) {
        sc_debug(ctx, SC_LOG_DEBUG_ASN1,
             "too long ASN.1 object (size %"SC_FORMAT_LEN_SIZE_T"u while only %"SC_FORMAT_LEN_SIZE_T"u available)\n",
             taglen, len);
        return NULL;
    }
    *buflen -= (p - *buf) + taglen;
    *buf = p + taglen;  /* point to next tag */
    *taglen_out = taglen;
    return p;
}

sc_asn1_read_tag method:

int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out,
             unsigned int *tag_out, size_t *taglen)
{
    const u8 *p = *buf;
    size_t left = buflen, len;
    unsigned int cla, tag, i;

    *buf = NULL;

    if (left == 0 || !p)
        return SC_ERROR_INVALID_ASN1_OBJECT;
    if (*p == 0xff || *p == 0) {
        /* end of data reached */
        *taglen = 0;
        *tag_out = SC_ASN1_TAG_EOC;
        return SC_SUCCESS;
    }

    /* parse tag byte(s)
     * Resulted tag is presented by integer that has not to be
     * confused with the 'tag number' part of ASN.1 tag.
     */
    cla = (*p & SC_ASN1_TAG_CLASS) | (*p & SC_ASN1_TAG_CONSTRUCTED);
    tag = *p & SC_ASN1_TAG_PRIMITIVE;
    p++;
    left--;
    if (tag == SC_ASN1_TAG_PRIMITIVE) {
        /* high tag number */
        size_t n = SC_ASN1_TAGNUM_SIZE - 1;
        /* search the last tag octet */
        do {
            if (left == 0 || n == 0)
                /* either an invalid tag or it doesn't fit in
                 * unsigned int */
                return SC_ERROR_INVALID_ASN1_OBJECT;
            tag <<= 8;
            tag |= *p;
            p++;
            left--;
            n--;
        } while (tag & 0x80);
    }

    /* parse length byte(s) */
    if (left == 0)
        return SC_ERROR_INVALID_ASN1_OBJECT;
    len = *p;
    p++;
    left--;
    if (len & 0x80) {
        len &= 0x7f;
        unsigned int a = 0;
        if (len > sizeof a || len > left)
            return SC_ERROR_INVALID_ASN1_OBJECT;
        for (i = 0; i < len; i++) {
            a <<= 8;
            a |= *p;
            p++;
            left--;
        }
        len = a;
    }

    *cla_out = cla;
    *tag_out = tag;
    *taglen = len;
    *buf = p;

    if (len > left)
        return SC_ERROR_ASN1_END_OF_CONTENTS;

    return SC_SUCCESS;
}

These methods are all used in the process of reading certificates from the card using OpenSC. I need to achieve this on Android so any Java code that replicates it would be helpful.

I'd also be happy with a document that explains what this is/how this certificate is encoded or formatted.

Edit: TLV Breakdown

Any ideas what the extra portions at the end might be?


Solution

  • The procedure should work as follows (using data from GidsApplet unit test):

    Take raw DO data:

    DF2482029F0100AA0278DA3368625A66D0C4D8B7809989918949C0523340E6B55BCE0AA79E87FCDCC545BD06BC6C9C5A6D1E6DDF7919195959190CF80D790DB8D998435998855942528B4B0CE4C4790DCD0C0C0D0D80A49189619438AF113217534313A312B2A18CAC0CCC4D8CFC0C40712EA626464686750BEBDE18D606B7F19DD5FD2EF52029FA2CDBCFC58B8C3D8A0E8BB37F56D3FB663CF1A8C484377D6BCB738F569778E7C85F733EE2977A55527B5666F2ACFF539F335F7BF1A3596E41F65ECD428615FF66E8F4E6DF76505F7538EAEB65E1355F594A27F47D8C4F5917FCC659E84C6089BDC397CFDCF737689C9A2B6BB26521CFBE177B75941D6C26542B6E8FBD74F78356B14992EEB93C877F9686672FDD9E7E3759313771F7AC8575DFCF4CE03B71F241E5F9536EF2E91E1A69C50D7593AAE7D63558355C13EDAD497A9B25BD67BFF4DD8B55356A91BF8FF5DFE6EF0B5B921F1177C3ED9B7ED7BFBD6606EF756E369AAFE7FD72EA42C98BD90F6E2E70B6BC5F7D9E69DFCD495D8211AB8B7F2D8E6462666460440B766650C04C6557F81D107E38FA97CFF2E6CA2946BEAA5ED94C533CBCE748D4CD0D63B0FDCDF8FAD7F39E7BBC594F9AD294B77C8FFE54911138F9BB77C0A21FFFF6BC5891F6E193CDD4FF01B50F367B3EABBF5574B772AAA878C97A739B1D67734DB7B2DEB60F08779E707FE1DE951BBF735D68E5DDD15FC060FAD9FBDF16AEA7E7C2F93A5EED927FEEB4F1F49B99B213CE250A4F3DDDD99DDE97E3DE33C1E98984F88E3F06E5893C931DCB4F74A8738A3104ACEAB34875BDBA60E3E3052DFF97F7FD67EBFC5EBD30FCD06583A5C20C6E6FFB5F3BDD33E0F83747222CF9D9F2577DB72C56C44DE87DFB44F4973A5BE3ECF8DF2C3FD7F6F1BFE95E7550E32A9F9D4BC3FE6C56875291774772B996DEFDEFBC341C004D16293D
    

    Parse it as BER-TLV (e.g. using an online tool):

    DF24 Unknown tag
        0100AA0278DA3368625A66D0C4D8B7809989918949C0523340E6B55BCE0AA79E87FCDCC545BD06BC6C9C5A6D1E6DDF7919195959190CF80D790DB8D998435998855942528B4B0CE4C4790DCD0C0C0D0D80A49189619438AF113217534313A312B2A18CAC0CCC4D8CFC0C40712EA626464686750BEBDE18D606B7F19DD5FD2EF52029FA2CDBCFC58B8C3D8A0E8BB37F56D3FB663CF1A8C484377D6BCB738F569778E7C85F733EE2977A55527B5666F2ACFF539F335F7BF1A3596E41F65ECD428615FF66E8F4E6DF76505F7538EAEB65E1355F594A27F47D8C4F5917FCC659E84C6089BDC397CFDCF737689C9A2B6BB26521CFBE177B75941D6C26542B6E8FBD74F78356B14992EEB93C877F9686672FDD9E7E3759313771F7AC8575DFCF4CE03B71F241E5F9536EF2E91E1A69C50D7593AAE7D63558355C13EDAD497A9B25BD67BFF4DD8B55356A91BF8FF5DFE6EF0B5B921F1177C3ED9B7ED7BFBD6606EF756E369AAFE7FD72EA42C98BD90F6E2E70B6BC5F7D9E69DFCD495D8211AB8B7F2D8E6462666460440B766650C04C6557F81D107E38FA97CFF2E6CA2946BEAA5ED94C533CBCE748D4CD0D63B0FDCDF8FAD7F39E7BBC594F9AD294B77C8FFE54911138F9BB77C0A21FFFF6BC5891F6E193CDD4FF01B50F367B3EABBF5574B772AAA878C97A739B1D67734DB7B2DEB60F08779E707FE1DE951BBF735D68E5DDD15FC060FAD9FBDF16AEA7E7C2F93A5EED927FEEB4F1F49B99B213CE250A4F3DDDD99DDE97E3DE33C1E98984F88E3F06E5893C931DCB4F74A8738A3104ACEAB34875BDBA60E3E3052DFF97F7FD67EBFC5EBD30FCD06583A5C20C6E6FFB5F3BDD33E0F83747222CF9D9F2577DB72C56C44DE87DFB44F4973A5BE3ECF8DF2C3FD7F6F1BFE95E7550E32A9F9D4BC3FE6C56875291774772B996DEFDEFBC341C004D16293D
    

    Given the OpenSC source code the data inside the tag should look like:

    Then you can decompress zlib data to get:

    308202a63082018ea00302010202103929501ceb466ca8428ce10f0b73728d300d06092a864886f70d0101050500300f310d300b0603550403130454657374301e170d3136303131303136303234315a170d3236303131303136303234315a300f310d300b060355040313045465737430820122300d06092a864886f70d01010105000382010f003082010a0282010100aea17eec317d53860ecd2df71ae0625bcd06f9a3a2334872c31707f3262ef63391c51890ec8ead776dc57b744b6c1fd643c44e65d5192b9a69639aff95e703d6e8f8831ea06bbd297100a8fe982c8d6fdb4027aac35af5d313acf50475908ef15f64ae53ec4312cc51743f40f4f30bdfb028ca9d1d34b4a10cbee8bd2c23403c907b21b75dd2ddf02a7334622dce6e40fe3931cdd2db97dd63216d61bb9aa17ef7cc900ec8c9e079cfca461f6748286673807e927b9d7e803a80d6158d7c62ed6a1bbcbf1bddd17a7c2659fbc68fdb0f8e56a46f585ed846f62f8afebd3630ef2cd98137af0df4cad074e89be0d9a04339df7bcf02bed9928a1158ab73faa3590203010001300d06092a864886f70d01010505000382010100950720fb5057c35bfa4ca7837994324d254a6b0294484b9c187e9d56003dfb01ebfae78cde0d6ae4826623b4f75bf278685193f74b50a2f8febce8a866f0f23c95ff507de0b349e67fda72dd7995151774af373cb8cd6d35b505db3f50574390dfa1bda9b1f70ad0850db88f700035f34bfeb40ae5ce570e88eaba1fe742b1cbec991d90ce611395cb898b678e6c478c9042e41817b8fc3077610c934177c8882709160050aa8e386545d5a0b1e3a084ffa78eff0689f77ba157c2d330a5130046ed8feb42de3008fe9c185663e6a7ea8eda38a85e908dede415fa2706819b5ffb04f9ad8e0fec8baac128d50e3e4480bf6b05407514eec46d0aa5ddff43a557
    

    That is a DER encoded X.509 certificate:

    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                39:29:50:1c:eb:46:6c:a8:42:8c:e1:0f:0b:73:72:8d
        Signature Algorithm: sha1WithRSAEncryption
            Issuer: CN = Test
            Validity
                Not Before: Jan 10 16:02:41 2016 GMT
                Not After : Jan 10 16:02:41 2026 GMT
            Subject: CN = Test
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    Public-Key: (2048 bit)
                    Modulus:
                        00:ae:a1:7e:ec:31:7d:53:86:0e:cd:2d:f7:1a:e0:
                        62:5b:cd:06:f9:a3:a2:33:48:72:c3:17:07:f3:26:
                        2e:f6:33:91:c5:18:90:ec:8e:ad:77:6d:c5:7b:74:
                        4b:6c:1f:d6:43:c4:4e:65:d5:19:2b:9a:69:63:9a:
                        ff:95:e7:03:d6:e8:f8:83:1e:a0:6b:bd:29:71:00:
                        a8:fe:98:2c:8d:6f:db:40:27:aa:c3:5a:f5:d3:13:
                        ac:f5:04:75:90:8e:f1:5f:64:ae:53:ec:43:12:cc:
                        51:74:3f:40:f4:f3:0b:df:b0:28:ca:9d:1d:34:b4:
                        a1:0c:be:e8:bd:2c:23:40:3c:90:7b:21:b7:5d:d2:
                        dd:f0:2a:73:34:62:2d:ce:6e:40:fe:39:31:cd:d2:
                        db:97:dd:63:21:6d:61:bb:9a:a1:7e:f7:cc:90:0e:
                        c8:c9:e0:79:cf:ca:46:1f:67:48:28:66:73:80:7e:
                        92:7b:9d:7e:80:3a:80:d6:15:8d:7c:62:ed:6a:1b:
                        bc:bf:1b:dd:d1:7a:7c:26:59:fb:c6:8f:db:0f:8e:
                        56:a4:6f:58:5e:d8:46:f6:2f:8a:fe:bd:36:30:ef:
                        2c:d9:81:37:af:0d:f4:ca:d0:74:e8:9b:e0:d9:a0:
                        43:39:df:7b:cf:02:be:d9:92:8a:11:58:ab:73:fa:
                        a3:59
                    Exponent: 65537 (0x10001)
        Signature Algorithm: sha1WithRSAEncryption
             95:07:20:fb:50:57:c3:5b:fa:4c:a7:83:79:94:32:4d:25:4a:
             6b:02:94:48:4b:9c:18:7e:9d:56:00:3d:fb:01:eb:fa:e7:8c:
             de:0d:6a:e4:82:66:23:b4:f7:5b:f2:78:68:51:93:f7:4b:50:
             a2:f8:fe:bc:e8:a8:66:f0:f2:3c:95:ff:50:7d:e0:b3:49:e6:
             7f:da:72:dd:79:95:15:17:74:af:37:3c:b8:cd:6d:35:b5:05:
             db:3f:50:57:43:90:df:a1:bd:a9:b1:f7:0a:d0:85:0d:b8:8f:
             70:00:35:f3:4b:fe:b4:0a:e5:ce:57:0e:88:ea:ba:1f:e7:42:
             b1:cb:ec:99:1d:90:ce:61:13:95:cb:89:8b:67:8e:6c:47:8c:
             90:42:e4:18:17:b8:fc:30:77:61:0c:93:41:77:c8:88:27:09:
             16:00:50:aa:8e:38:65:45:d5:a0:b1:e3:a0:84:ff:a7:8e:ff:
             06:89:f7:7b:a1:57:c2:d3:30:a5:13:00:46:ed:8f:eb:42:de:
             30:08:fe:9c:18:56:63:e6:a7:ea:8e:da:38:a8:5e:90:8d:ed:
             e4:15:fa:27:06:81:9b:5f:fb:04:f9:ad:8e:0f:ec:8b:aa:c1:
             28:d5:0e:3e:44:80:bf:6b:05:40:75:14:ee:c4:6d:0a:a5:dd:
             ff:43:a5:57
    -----BEGIN CERTIFICATE-----
    MIICpjCCAY6gAwIBAgIQOSlQHOtGbKhCjOEPC3NyjTANBgkqhkiG9w0BAQUFADAP
    MQ0wCwYDVQQDEwRUZXN0MB4XDTE2MDExMDE2MDI0MVoXDTI2MDExMDE2MDI0MVow
    DzENMAsGA1UEAxMEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
    AK6hfuwxfVOGDs0t9xrgYlvNBvmjojNIcsMXB/MmLvYzkcUYkOyOrXdtxXt0S2wf
    1kPETmXVGSuaaWOa/5XnA9bo+IMeoGu9KXEAqP6YLI1v20AnqsNa9dMTrPUEdZCO
    8V9krlPsQxLMUXQ/QPTzC9+wKMqdHTS0oQy+6L0sI0A8kHsht13S3fAqczRiLc5u
    QP45Mc3S25fdYyFtYbuaoX73zJAOyMngec/KRh9nSChmc4B+knudfoA6gNYVjXxi
    7WobvL8b3dF6fCZZ+8aP2w+OVqRvWF7YRvYviv69NjDvLNmBN68N9MrQdOib4Nmg
    Qznfe88CvtmSihFYq3P6o1kCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAlQcg+1BX
    w1v6TKeDeZQyTSVKawKUSEucGH6dVgA9+wHr+ueM3g1q5IJmI7T3W/J4aFGT90tQ
    ovj+vOioZvDyPJX/UH3gs0nmf9py3XmVFRd0rzc8uM1tNbUF2z9QV0OQ36G9qbH3
    CtCFDbiPcAA180v+tArlzlcOiOq6H+dCscvsmR2QzmETlcuJi2eObEeMkELkGBe4
    /DB3YQyTQXfIiCcJFgBQqo44ZUXVoLHjoIT/p47/Bon3e6FXwtMwpRMARu2P60Le
    MAj+nBhWY+an6o7aOKhekI3t5BX6JwaBm1/7BPmtjg/si6rBKNUOPkSAv2sFQHUU
    7sRtCqXd/0OlVw==
    -----END CERTIFICATE-----
    

    This procedure unfortunately does not work with your data (that is why I asked you to confirm it -- AFAIK the zlib stream should start with 0x78).

    Good luck with your project!

    EDIT>

    Regarding the quality of GIDS specification (citing OpenSC comment):

    Some features are undocumented like the format used to store certificates. They have been reverse engineered.