只是分享我的代码:
抱歉差错处理。
我花了一些时间来到这里。令人惊讶的是,在 Receita Federal do Brasil 然后是ITI本身更容易找到证书布局文档。 较旧的证书具有不同的布局。我会花一点时间寻找更多文档。
如果有人有官方文档,请分享。
public static List<Certificado> ListarSignatariosArquivo(byte[] arquivo)
{
/* http://www.receita.fazenda.gov.br/acsrf/LeiautedeCertificadosdaSRF.pdf
* 2.2.5. Subject Alternative Name
* Campos Obrigatórios
* OID = 2.16.76.1.3.1 com o seguinte conteúdo:
* Nas primeiras 8 (oito) posições, a data de nascimento da pessoa física titular do certificado, no formato ddmmaaaa;
* nas 11 (onze) posições subseqüentes, o número de inscrição no Cadastro de Pessoa Física (CPF) da pessoa física titular do certificado;
* nas 11 (onze) posições subseqüentes, o número de Identificação Social da pessoa física titular do certificado - NIS (PIS, PASEP ou CI);
* nas 15 (quinze) posições subseqüentes, o número do Registro Geral - RG da pessoa física titular do certificado;
* nas 6 (seis) posições subseqüentes, as siglas do órgão expedidor do RG e respectiva UF.
*
* OID = 2.16.76.1.3.5 com o seguinte conteúdo:
* Nas primeiras 12 (onze) posições, o número de inscrição do Título de Eleitor da pessoa física titular do certificado;
* nas 3 (três) posições subseqüentes, o número correspondente a Zona Eleitoral;
* nas 4 (quatro) posições seguintes, o número correspondente a Seção;
* nas 22 (vinte e duas) posições subseqüentes, o nome do município e a UF do Título de Eleitor.
*
* OID = 2.16.76.1.3.6 com o seguinte conteúdo:
* Nas 12 (doze) posições, o número do Cadastro Especifico do INSS (CEI) da pessoa física titular do certificado.
*
* Campos Opcionais
* OID = 2.16.76.1.4.x.y.z com o seguinte conteúdo:
* Tamanho variável correspondente ao número de habilitação ou identificação profissional emitido por conselho de classe ou órgão competente.
* A AC Raiz, por meio do documento ATRIBUIÇÃO DE OID DA ICP-BRASIL (DOC ICP-04-01) regulamentará a correspondência de cada conselho de classe
* ou órgão competente ao conjunto de OID acima definido.
*
* OID = 1.3.6.1.4.1.311.20.2.3 com o seguinte conteúdo:
* Este campo Principal Name contém a Identificação do endereço de login do titular do certificado no diretório Active Direct (AD) Microsoft.
* O conjunto de informações definido em cada campo OtherName deve ser armazenado como uma cadeia de caracteres do tipo ASN.1 OCTET STRING,
* com exceção do campo Principal Name cuja cadeia de caracteres é do tipo UTF-8 String.
*
* Os seguintes campos são de preenchimento obrigatório:
* - Nome;
* - CPF;
* - Data de nascimento; e
* - Email.
*/
CmsSignedData signedData = null;
List<Certificado> listaCpf = new List<Certificado>();
try
{
signedData = new CmsSignedData(arquivo);
}
catch (CmsException)
{
return listaCpf;
}
catch (Exception e)
{
throw new IntegridadeArquivoException("Arquivo corrompido.", e);
}
if (signedData != null)
{
IX509Store store = signedData.GetCertificates("Collection/Certificate");
SignerInformationStore signers = signedData.GetSignerInfos();
foreach (var it in signers.GetSigners())
{
SignerInformation signer = (SignerInformation)it;
foreach (var certificado in store.GetMatches(signer.SignerID))
{
X509Certificate x509cert = (X509Certificate)certificado;
IList tmp;
tmp = x509cert.SubjectDN.GetValueList(X509Name.CN);
string nome = tmp.Count > 0 ? tmp[0].ToString() : "";
tmp = x509cert.IssuerDN.GetValueList(X509Name.CN);
string autoridadeCertificadora = tmp.Count > 0 ? tmp[0].ToString() : "";
DateTime dtValidadeCertificado = x509cert.NotAfter;
Nullable<DateTime> dtNascimento = null;
string cpf = null;
string rg = null;
string orgaoExpedidorRg = null;
string pessoaFisicaOid = "2.16.76.1.3.1";
foreach (ArrayList a in x509cert.GetSubjectAlternativeNames())
{
string conteudo = a.ToArray()[1].ToString();
Match moid = Regex.Match(conteudo, @"\[[0-9\.]*");
string oid = moid.Success ? moid.Value.Replace("[", string.Empty) : "";
if (pessoaFisicaOid.Equals(oid))
{
Match mvalor = Regex.Match(conteudo, "#[0-9a-fA-F]+");
string valor = mvalor.Success ? mvalor.Value.Replace("#", string.Empty) : "";
//converter string hexadecimal em string decimal.
valor = FromHexToString(valor);
int i = 0;
dtNascimento = DateTime.ParseExact(valor.Substring(i, 8),"ddMMyyyy", CultureInfo.InvariantCulture);
i += 8;
cpf = valor.Substring(i, 11);
i += 22;
rg = valor.Substring(i, 15);
i += 15;
orgaoExpedidorRg = valor.Substring(i, 6);
}
}
listaCpf.Add(new Certificado {
Nome = nome,
DtNascimento = dtNascimento,
AutoridadeCertificadora = autoridadeCertificadora,
DtValidadeCertificado = dtValidadeCertificado,
Cpf = cpf,
Rg = rg,
OrgaoExpedidorRg = orgaoExpedidorRg
});
}
}
}
return listaCpf;
}
public static string FromHexToString(string hex)
{
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return Encoding.ASCII.GetString(raw);
}