如何将证书从GIDS卡转换为crt文件



我正在为智能读卡器开发一些低级别的Android软件。我正在尝试添加对GIDS设备的支持,但在使用我可以从卡中提取的证书时遇到了一些问题。

PIV卡存储证书的方式是,从十六进制数组转换为字节数组可以提供openSSL可以识别的数组。

对于GIDS卡中的证书文件,相同的过程不起作用,该文件将恢复为以下十六进制字符串。

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摘要:我需要将上面的十六进制代码转换为Java中的x509证书。阅读下面我所做的一些额外研究。

我仔细研究了OpenSC的pkcs15工具.c代码,发现他们对数据进行了一些非常复杂的操作。虽然我不太精通C/C++,所以我很难理解它。

从pkcs15-cert.c解析_x509_cert

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方法:

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方法:

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方法:

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;
}

这些方法都是在使用OpenSC从卡中读取证书的过程中使用的。我需要在Android上实现这一点,所以任何复制它的Java代码都会有所帮助。

我也很乐意提供一份文档来解释这是什么/证书是如何编码或格式化的。

编辑:TLV分解

你知道结尾的额外部分是什么吗?

程序应按以下方式工作(使用GidsApplet单元测试的数据(:

获取原始DO数据:

DF2482029F0100AA0278DA3368625A66D0C4D8B7809989918949C0523340E6B55BCE0AA79E87FCDCC545BD06BC6C9C5A6D1E6DDF7919195959190CF80D790DB8D998435998855942528B4B0CE4C4790DCD0C0C0D0D80A49189619438AF113217534313A312B2A18CAC0CCC4D8CFC0C40712EA626464686750BEBDE18D606B7F19DD5FD2EF52029FA2CDBCFC58B8C3D8A0E8BB37F56D3FB663CF1A8C484377D6BCB738F569778E7C85F733EE2977A55527B5666F2ACFF539F335F7BF1A3596E41F65ECD428615FF66E8F4E6DF76505F7538EAEB65E1355F594A27F47D8C4F5917FCC659E84C6089BDC397CFDCF737689C9A2B6BB26521CFBE177B75941D6C26542B6E8FBD74F78356B14992EEB93C877F9686672FDD9E7E3759313771F7AC8575DFCF4CE03B71F241E5F9536EF2E91E1A69C50D7593AAE7D63558355C13EDAD497A9B25BD67BFF4DD8B55356A91BF8FF5DFE6EF0B5B921F1177C3ED9B7ED7BFBD6606EF756E369AAFE7FD72EA42C98BD90F6E2E70B6BC5F7D9E69DFCD495D8211AB8B7F2D8E6462666460440B766650C04C6557F81D107E38FA97CFF2E6CA2946BEAA5ED94C533CBCE748D4CD0D63B0FDCDF8FAD7F39E7BBC594F9AD294B77C8FFE54911138F9BB77C0A21FFFF6BC5891F6E193CDD4FF01B50F367B3EABBF5574B772AAA878C97A739B1D67734DB7B2DEB60F08779E707FE1DE951BBF735D68E5DDD15FC060FAD9FBDF16AEA7E7C2F93A5EED927FEEB4F1F49B99B213CE250A4F3DDDD99DDE97E3DE33C1E98984F88E3F06E5893C931DCB4F74A8738A3104ACEAB34875BDBA60E3E3052DFF97F7FD67EBFC5EBD30FCD06583A5C20C6E6FFB5F3BDD33E0F83747222CF9D9F2577DB72C56C44DE87DFB44F4973A5BE3ECF8DF2C3FD7F6F1BFE95E7550E32A9F9D4BC3FE6C56875291774772B996DEFDEFBC341C004D16293D

将其解析为BER-TLV(例如使用在线工具(:

DF24 Unknown tag
0100AA0278DA3368625A66D0C4D8B7809989918949C0523340E6B55BCE0AA79E87FCDCC545BD06BC6C9C5A6D1E6DDF7919195959190CF80D790DB8D998435998855942528B4B0CE4C4790DCD0C0C0D0D80A49189619438AF113217534313A312B2A18CAC0CCC4D8CFC0C40712EA626464686750BEBDE18D606B7F19DD5FD2EF52029FA2CDBCFC58B8C3D8A0E8BB37F56D3FB663CF1A8C484377D6BCB738F569778E7C85F733EE2977A55527B5666F2ACFF539F335F7BF1A3596E41F65ECD428615FF66E8F4E6DF76505F7538EAEB65E1355F594A27F47D8C4F5917FCC659E84C6089BDC397CFDCF737689C9A2B6BB26521CFBE177B75941D6C26542B6E8FBD74F78356B14992EEB93C877F9686672FDD9E7E3759313771F7AC8575DFCF4CE03B71F241E5F9536EF2E91E1A69C50D7593AAE7D63558355C13EDAD497A9B25BD67BFF4DD8B55356A91BF8FF5DFE6EF0B5B921F1177C3ED9B7ED7BFBD6606EF756E369AAFE7FD72EA42C98BD90F6E2E70B6BC5F7D9E69DFCD495D8211AB8B7F2D8E6462666460440B766650C04C6557F81D107E38FA97CFF2E6CA2946BEAA5ED94C533CBCE748D4CD0D63B0FDCDF8FAD7F39E7BBC594F9AD294B77C8FFE54911138F9BB77C0A21FFFF6BC5891F6E193CDD4FF01B50F367B3EABBF5574B772AAA878C97A739B1D67734DB7B2DEB60F08779E707FE1DE951BBF735D68E5DDD15FC060FAD9FBDF16AEA7E7C2F93A5EED927FEEB4F1F49B99B213CE250A4F3DDDD99DDE97E3DE33C1E98984F88E3F06E5893C931DCB4F74A8738A3104ACEAB34875BDBA60E3E3052DFF97F7FD67EBFC5EBD30FCD06583A5C20C6E6FFB5F3BDD33E0F83747222CF9D9F2577DB72C56C44DE87DFB44F4973A5BE3ECF8DF2C3FD7F6F1BFE95E7550E32A9F9D4BC3FE6C56875291774772B996DEFDEFBC341C004D16293D

给定OpenSC源代码,标签中的数据应该如下所示:

  • 0x0100。。指示zlib压缩

  • 0xLLLL(此处为0xAA02(。。指示未压缩数据长度(此处为682字节(

  • 剩下的是一个zlib压缩的数据流(这里是667字节的78DA33..16293D(

然后您可以解压缩zlib数据以获得:

308202a63082018ea00302010202103929501ceb466ca8428ce10f0b73728d300d06092a864886f70d0101050500300f310d300b0603550403130454657374301e170d3136303131303136303234315a170d3236303131303136303234315a300f310d300b060355040313045465737430820122300d06092a864886f70d01010105000382010f003082010a0282010100aea17eec317d53860ecd2df71ae0625bcd06f9a3a2334872c31707f3262ef63391c51890ec8ead776dc57b744b6c1fd643c44e65d5192b9a69639aff95e703d6e8f8831ea06bbd297100a8fe982c8d6fdb4027aac35af5d313acf50475908ef15f64ae53ec4312cc51743f40f4f30bdfb028ca9d1d34b4a10cbee8bd2c23403c907b21b75dd2ddf02a7334622dce6e40fe3931cdd2db97dd63216d61bb9aa17ef7cc900ec8c9e079cfca461f6748286673807e927b9d7e803a80d6158d7c62ed6a1bbcbf1bddd17a7c2659fbc68fdb0f8e56a46f585ed846f62f8afebd3630ef2cd98137af0df4cad074e89be0d9a04339df7bcf02bed9928a1158ab73faa3590203010001300d06092a864886f70d01010505000382010100950720fb5057c35bfa4ca7837994324d254a6b0294484b9c187e9d56003dfb01ebfae78cde0d6ae4826623b4f75bf278685193f74b50a2f8febce8a866f0f23c95ff507de0b349e67fda72dd7995151774af373cb8cd6d35b505db3f50574390dfa1bda9b1f70ad0850db88f700035f34bfeb40ae5ce570e88eaba1fe742b1cbec991d90ce611395cb898b678e6c478c9042e41817b8fc3077610c934177c8882709160050aa8e386545d5a0b1e3a084ffa78eff0689f77ba157c2d330a5130046ed8feb42de3008fe9c185663e6a7ea8eda38a85e908dede415fa2706819b5ffb04f9ad8e0fec8baac128d50e3e4480bf6b05407514eec46d0aa5ddff43a557

这是一个DER编码的X.509证书:

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-----

不幸的是,这个过程不适用于您的数据(这就是为什么我要求您确认它——AFAIK zlib流应该以0x78开头(。

祝你的项目好运!

编辑>

关于GIBS规范的质量(引用OpenSC评论(:

有些功能没有文档,比如用于存储证书的格式。它们经过了逆向工程。

最新更新