Problemas ao capturar extensões subject alternative names de certificados X509

Bom dia pessoal,

Estou tentando recuperar os assuntos alternativos de um certificado X509 mas estou tendo um problema.

Pelo metodo “getSubjectAlternativeNames()” consigo pegar uma coleção que por sua vez é formada de outras coleções. Essas “sub-coleções” contém dois itens o primeiro item é um Integer e o segundo uma String ou um array de bytes. Quando for uma String eu sei que se trata da extensão NomeRFC822 mas quando vem um array de bytes sei que vem codificado no padrão “ASN.1 Octet String”, é aqui que começa o problema, pq não consigo identificar seu OID.

Estou usando a DEROctetString da API da BouncyCastle, mas apartir dessa clase não consigo capturar o oid.

como posso identificar o OID de uma extenção apartir de seu valor?

Desde já agradeço a ajuda

É mais complicado que parece. Aqui vai um pedaço de código, veja se ajuda.

/**
 * Uma classe que encapsula pares de objetos.
 * Inspirado no template pair&lt&gt da STL.
 *
 * @param <T> O primeiro tipo.
 * @param <U> O segundo tipo.
 */
class Pair&lt;T, U&gt; {
	/** O primeiro objeto. */
	public T first;

	/** O segundo objeto. */
	public U second;

	/** Construtor */
	public Pair(T t, U u) {
		first = t;
		second = u;
	}
}


	/**
	 * Interpreta um dado do tipo otherName. 
	 * Obs. O JDK 5.0 não tem classes que lidem com um dado do tipo OtherName.
	 * É necessário usar o BouncyCastle.
	 * @param encoded O dado em ASN.1.
	 * @return Um par contendo o OID e o conteúdo.
	 */
	private Pair&lt;DERObjectIdentifier, String&gt; getOtherName(byte[] encoded) throws IOException {
		// O JDK 5.0 não tem classes que lidem com um dado do tipo OtherName.
		// É necessário usar o BouncyCastle.
		ASN1InputStream inps = new ASN1InputStream(encoded);
		DERSequence seq = null;
		DERObjectIdentifier oid = null;
		String conteudo = "";
		seq = (DERSequence) inps.readObject();
		inps.close();
		Enumeration en = seq.getObjects();
		oid = (DERObjectIdentifier) en.nextElement();
		DERObject obj = ((ASN1TaggedObject) ((ASN1TaggedObject) en.nextElement()).getObject()).getObject();
		if (obj instanceof DERString) { // Certificados antigos SERASA - incorretos
			conteudo = ((DERString) obj).getString();
		} else if (obj instanceof DEROctetString) { // Certificados corretos
			conteudo = new String(((DEROctetString) obj).getOctets(), "ISO-8859-1");
		}
		return new Pair&lt;DERObjectIdentifier, String&gt;(oid, conteudo);
	}


//
		for (List&lt?&gt subjectAlternativeName : cert.getSubjectAlternativeNames()) {
			String email;
			Pair&lt;DERObjectIdentifier, String&gt; otherName;
			int pos;
			// O primeiro elemento é um Integer com o valor 0 = otherName, 1 = rfc822name etc.
			// O segundo valor é um byte array ou uma String. Veja o javadoc de
			// getSubjectAlternativeNames.
			switch (((Number) subjectAlternativeName.get(0)).intValue()) {
			case 0: // OtherName - contém CPF, CNPJ etc.
				otherName = getOtherName((byte[]) subjectAlternativeName.get(1));
				// o OID fica em otherName.first 
				break;
			case 1: // rfc822Name - usado para email
				email = (String) subjectAlternativeName.get(1);
				props.put("email", email);
				break;
			default:
				break;
			}
		}

Esta api que vcs estão utilizando para fazer este decode fazem decode de arquivos BER?
Eu tive que fazer isso um tempo atraz e não achei nada em java, somente C++.

Mais ou menos. Para o uso com certificação digital é suficiente.

thingol,
essa solução que você apresentou é exatamente para o meu problema, porém usando uma biblioteca diferente da que eu uso. Você usa a BouncyCastle e estou usando a api da Sun, a WSDP…

Você conhece a mesma solução porém usando essa outra biblioteca…?

valeu

Olha, eu simplesmente nunca mexi com a parte de segurança da WSDP.
(É que sou meio folgado e acostumado com a BouncyCastle.)
Não sei se a parte de segurança da WSDP tem uma parte ASN.1 disponível para ser usada. (Eu sei que há uma porção de classes “com.sun.*” que fazem exatamente essa parte de parsing ASN.1, mas não quero fazer meus programas dependerem de uma API que talvez não possa instalar (por exemplo, digamos que eu vá usar o WebSphere em vez de usar o JBoss ou o Sun Java System Application Server).

Você pode me dar sua opnião sobre o BouncyCastle? É que eu ainda posso largar o WSDP e manipular os certificados usando o BouncyCastle, mas essa API tem q ser fácil de mexer e rápido de desenvelver.

É facil mexer com certificados X509? Assinar arquivos XML? Checar assinaturas de XMLs? Etc…

valeu

A parte de XML-Signature e XML-Encryption, se não me engano, não está implementada no BouncyCastle.

Eu se fosse você iria usar as 2 bibliotecas, a menos que você tivesse um problema com deployment. Por exemplo, o BouncyCastle é um JCE Provider, e isso pode dar problemas em alguns ambientes onde você não pode mexer no diretório jre/lib/ext (onde esse arquivo deve ser copiado), ou no arquivo jre/lib/security/java.security (onde o BouncyCastle deve ser configurado).