Criptografia usando Bouncy Castle

15 respostas
T

Alguem ja se deparou com esse erro ou sabe o q pode ser?
Estou tentando criptografar um arquivo usando Bouncy Castle. Já coloquei o jar do provider dentro de jre/lib/ext… ja fiz download e sobrescrevi os policy files sem restriçoes, já adicionei, dinamicamente, o provider dentro de meu código. Mas quando tento instanciar o Cipher da seguinte forma:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
Dá o seguinte erro:xception in thread "main" java.lang.ExceptionInInitializerError at javax.crypto.Cipher.getInstance(DashoA12275) at javax.crypto.Cipher.getInstance(DashoA12275) at br.com.maxxdata.csframework.concreteutils.UtilCriptografaArquivo.criptografarArquivo(UtilCriptografaArquivo.java:81) at br.com.maxxdata.csframework.concreteutils.UtilCriptografaArquivo.main(UtilCriptografaArquivo.java:213) Caused by: java.lang.SecurityException: Cannot set up certs for trusted CAs at javax.crypto.SunJCE_b.<clinit>(DashoA12275) ... 4 more

Alguém?

Desde já agradeço à atenção,

Saudações

15 Respostas

T

a) Que versão do JDK você está usando
b) Quais os arquivos .jar que você acrescentou
c) Se quiser simplesmente “AES/CBC/PKCS5Padding” use o próprio algoritmo da Sun se você estiver usando JDK 1.4.2_08 ou posterior.

T

a) Estou usando jdk1.5.0_06.
b) “bcprov-jdk15-132.jar”, “local_policy.jar” e “US_export_policy.jar”.
c) como assim usar o proprio algoritmo da sun? nao entendi. com ficaria meu getInstance do cipher?

T

a) Como eu mencionei em outro post, PKCS#7 não é um algoritmo e sim um padrão.
b) Baixe estes exemplos do livro Beginning Cryptography with Java (escrito por um dos autores do BouncyCastle) :
http://media.wiley.com/product_ancillary/30/07645963/DOWNLOAD/beg_crypto_examples.zip
c) Além do bcprov, ponha também o bcmail-jdk15-* e os outros (exceto o bctest).
d) Já que está com a mão na massa, use a versão mais nova (1.33)

T

Por coincidencia ja baixei esses exemplos e até criei um projeto no eclipse pra testa-los… peguei muita idéia deles. A questao eh q acho q to fazendo tudo certo, porem ta rolando alguma coisa sinistra do tipo jce q nao ta assinada sei la. . esse erro de “Cannot set up certs for trusted CAs” ta me cheirando a algo errado fora do meu código. Já gastei dias tentando resolver, por isso tô aki desesperado… meu projeto ja ta com o prazo enforcando-me!!!

T

Eclipse? Hum… Pode ser que você esteja com algum problema de classpath. O que ocorre se você roda seus programas “na mão” - em uma linha de comando?
Além disso, é melhor instalar o provider naquele arquivo java.security também.

T

Num pode ser de classpath pq executei os testes desses exemplos aíi e rodaram… tipo akele de ver se o provider ta instalado… entao descarto essa hipótese… mas acho q to quase descobrindo o problema… ja ja volto aki pra postar se consegui ou nao heheh… e se eu tiver mais dúvida tbm… ^^

T
Opa! tô conseguindo criptografar já ! Olha como ficou o método de criptografar:
public void criptografarArquivo(File arquivo, PublicKey chavePublica) 
	throws CSFException, NoSuchProviderException, InvalidAlgorithmParameterException {
		//
		try {		
			
			Mac mac = Mac.getInstance("HMACSHA1","BC");
			
			
			chavePublica.hashCode();
			
			SecureRandom    sec_rand = new SecureRandom();
			byte[]  mac_key_bytes = new byte[20]; // Set to correct length for HMACSHA1
			sec_rand.nextBytes(mac_key_bytes); // Fill with random data,
			
			
			
			Key mac_key = new SecretKeySpec(mac_key_bytes, "HMACSHA1"); // Convert to key object.
			mac.init(mac_key); // Initialize.
			
			
			KeyGenerator key_gen = KeyGenerator.getInstance("AES", "BC"); // Using appropriate key generator.
			key_gen.init(128, sec_rand); // Set up with key size and a SecureRandom.
			Key aes_key = key_gen.generateKey(); // Generate the Key Object.
			
			byte[]		    ivBytes = new byte[] { 
					0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
					0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
			
			//byte[]		    keyBytes = chavePublica.getEncoded();
			
			//SecretKeySpec   key = new SecretKeySpec(keyBytes, "AES");
			
			IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);			 
			
			Cipher          cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			
			cipher.init(Cipher.ENCRYPT_MODE, aes_key, ivSpec);
			
			byte [] arquivoEmBytes = UtilArquivos.abrirArquivoEmArrayDeBytes(arquivo);			
			
			byte [] arquivoCriptografado = null;
			
			arquivoCriptografado = cipher.doFinal(arquivoEmBytes);			
			
			File arqCripto = new File(arquivo.getAbsolutePath()+".p7b");
			
			FileOutputStream fos = new FileOutputStream(arqCripto);
			
			fos.write(arquivoCriptografado);
			
			fos.close();
			
		} catch (NoSuchAlgorithmException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} catch (NoSuchPaddingException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} catch (InvalidKeyException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} catch (IOException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} catch (IllegalBlockSizeException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} catch (BadPaddingException e) {
			
			throw new CSFExceptionCritica(e.getMessage(),e.getStackTrace());
			
		} 
	}

agora quero pegar informações sobre esse arquivo criptografado, isso é possível?? Desse jeito q eu criptografei tem como pegar informações do arquivo se eu tivesse extraído essa chave pública aí de um certificado??

T

Do jeito que você escreveu, você só gerou um monte de dados criptografados com uma chave simétrica. Pior: cada vez que você rodar esse programa, você vai ter uma chave diferente, e você nunca vai conseguir decifrar esse troço.

Você ainda não leu os exemplos direito…

T

é q isso daí eu só fiz pra ter certeza q ta tudo instalado e configurado corretamente… Quero saber o seguinte, se eu tivesse usado uma chave publica de um certificado ao inves dessas chaves doidonas aí q eu criei, eu conseguiria recuperar alguma informaçao depois do arquivo encriptado?

T

Vamos explicar como é que funciona o PKCS#7 envelopedData.

Esse formato contém, entre outras coisas:

  • Os dados criptografados com uma chave simétrica gerada aleatoriamente;
  • A chave simétrica criptografada com a chave pública do destinatário.
    Não estou com o padrão aqui para dizer se é possível também mandar mais alguma coisa, como o número de série do certificado X.509 do destinatário ou outra coisa. Só olhando o padrão.

O destinatário deve fazer o seguinte:

  • Decifrar a chave simétrica, usando a sua chave privada.
  • Decifrar os dados, usando a chave simétrica decifrada.
T
Então vc se refere a esse exemplo dakele pacote q falou no inicio né?!
/**
 * Demonstrate creation and processing a public key recipient enveloped-message
 * with matching of the RID to a certificate to make sure we have the right recipient.
 */
public class KeyTransEnvelopedDataWithCertMatchExample
{
    public static void main(String[] args)
        throws Exception
    {
        KeyStore        credentials = Utils.createCredentials();
        PrivateKey      key = (PrivateKey)credentials.getKey(Utils.END_ENTITY_ALIAS, Utils.KEY_PASSWD);
        Certificate[]   chain = credentials.getCertificateChain(Utils.END_ENTITY_ALIAS);
        X509Certificate cert = (X509Certificate)chain[0];

        // set up the generator
        CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();
        
        gen.addKeyTransRecipient(cert);
        
        // create the enveloped-data object
        CMSProcessable   data = new CMSProcessableByteArray("Hello World!".getBytes());

        CMSEnvelopedData enveloped = gen.generate(
                                data,
                                CMSEnvelopedDataGenerator.AES256_CBC, "BC");
        
        // recreate
        enveloped = new CMSEnvelopedData(enveloped.getEncoded());
        
        // set up to iterate through the recipients
        RecipientInformationStore   recipients = enveloped.getRecipientInfos();
        CertStore                   certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(Collections.singleton(cert)), "BC");
        Iterator                    it = recipients.getRecipients().iterator();
        RecipientInformation        recipient = null;
        
        while (it.hasNext())
        {
            recipient = (RecipientInformation)it.next();
            if (recipient instanceof KeyTransRecipientInformation)
            {
                // match the recipient ID
                Collection matches = certStore.getCertificates(recipient.getRID());
                
                if (!matches.isEmpty())
                {
                    // decrypt the data
                    byte[] recData = recipient.getContent(key, "BC");

                    // compare recovered data to the original data
                    if (Arrays.equals((byte[])data.getContent(), recData))
                    {
                        System.out.println("data recovery succeeded");
                        break;
                    }
                    else
                    {
                        System.out.println("data recovery failed");
                        break;
                    }
                }
            }
        }   
        
        if (recipient == null)
        {
            System.out.println("could not find a matching recipient");
        }
    }
}
T

Acho que é esse mesmo.

Recipient = Destinatário

T

Hum… Esse conceito de Recipient aí ta me confundindo pra caramba. Fiz minha versão desse exemplo aí pra carregar do token, mas até agora num deu certo… acho q esse treco de recipiente ser o destinatário q ta me confundindo… o recipiente nesse momento aki // decrypt the data byte[] recData = recipient.getContent(key, "BC"); Como pode pegar um arquivo encriptado de um recipiente entao? afinal o que ele ta fazendo nessa linha??

Desde já agradeço a atenção,

T

O tal exemplo que você está mostrando é um exemplo com “ida e volta” - ou seja, tem a parte que envelopa dados com PKCS#7, e a parte que decifra os tais dados.

T

Entao, eu separei em dois métodos esse exemplo aí… Um q criptografa e outro q descriptografa e verifica se o descriptado compara com o antigo antes da criptografada ^ ^. ôo!!
Só q na hora de descriptografar byte[] recData = recipient.getContent(key, "BC"); Ele da uma exception doidona assim: xception in thread "main" java.security.NoSuchProviderException: No such provider: org.mozilla.jss.JSSProvider at javax.crypto.Cipher.getInstance(DashoA12275) at org.bouncycastle.cms.KeyTransRecipientInformation.getContentStream(Unknown Source) at org.bouncycastle.cms.RecipientInformation.getContent(Unknown Source) at br.com.maxxdata.csframework.concreteutils.UtilCriptografaDescriptografa.descriptografa(UtilCriptografaDescriptografa.java:125)
Quer q eu poste o código pra vc ver como ficou Thingol?? Se é q vc vai ter saco heheh^ ^" eu sou muito chato…o_O

Criado 7 de julho de 2006
Ultima resposta 10 de jul. de 2006
Respostas 15
Participantes 2