Criptografar RSA bloco de 128 bytes

Uma das especificações do PAF-ECF é criptografar um bloco de dados 128 bytes gerados por outros passos anteriormente…
O problema é…
Se eu criptografar com RSA, ele não aceita, me retorna que pode somente criptografar 117 bytes no máximo…

Alguém já fez essa assinatura do EAD…quais os passos que usou para assinar?

o que eu fiz foi…

Gerei um MD5 do texto contido no arquivo…
Gerei um array de 128 bytes, onde a primeira posição é o num 16 que é o tamanho do hash
depois adicionei nesse array o hash md5 nas próximas posições que chega até a posicao 16 do array…

até aí tudo bem, mas daí quando vou passar esse array de bytes para criptografar em RSA, dá o erro…

o que devo fazer…

a rotina para criptografar que eu faço é

    Signature sig = Signature.getInstance( "NONEwithRSA");
         sig.initSign(pk);//pk é private key que passo como argumento para o método
         sig.update(b,0,b.length);
        

         byte[] retorno =   sig.sign();

e o engraçado se eu passar um array de bytes menor, ele aceita e criptografa certo

Já pensou em usar o openssl para fazer a criptografia? Homologamos o PAF sem problemas dessa forma

Obrigado pela atenção… no caso do openssl, como eu faria para gerar o rsa certinho, nunca mechi nele…

Em vez do signature , usei esse código e funcionou a geração do RSA

 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        // -- A) Gerando uma chave simétrica de 128 bits
        Cipher rsacf = Cipher.getInstance("RSA", "BC");
        rsacf.init(Cipher.ENCRYPT_MODE, pk);//Chave privada
        byte[] b1 = new byte[128];
        int ret = rsacf.doFinal(b, 0, b.length, b1);
        return b1;

Porém…não está validando lá no eECFc… só mostra a msg “Assinatura inválida”

Essa é classe que utilizamos pra fazer toda a operação de assinatura que o PAF exige

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.text.MessageFormat;

/**
 * Classe para controle da assinatura digital que deve ser aplicada nos arquivos do PAF
 */
public class AssinaturaDigitalPAF {

    private String openssl=null;
    private String erro=null;
    private static StringBuffer modeloXMLConfig;
    static {
        // Arquivo Padrão Para Validação da Assinatura
        modeloXMLConfig = new StringBuffer();
        modeloXMLConfig.append("<?xml version=\"1.0\"?>\r\n");
        modeloXMLConfig.append("<empresa_desenvolvedora>\r\n");
		modeloXMLConfig.append("	<nome>Software House</nome>\r\n");
		modeloXMLConfig.append("	<chave>\r\n");
		modeloXMLConfig.append("		<modulo>{0}</modulo>\r\n");
		modeloXMLConfig.append("		<expoente_publico>10001</expoente_publico>\r\n");
		modeloXMLConfig.append("	</chave>\r\n");
		modeloXMLConfig.append("</empresa_desenvolvedora>\r\n");
    }
    
    /**
     * É definido o caminho do programa OpenSSL ao instanciar a classe conforme
     * o sistema operacional
     */
    public AssinaturaDigitalPAF(){
		openssl="openssl";
    }
    
    /**     
     * @param e Erro ocorrido
     * @return  Retorna sempre falso para facilitar a saida dos outros metodos 
     * na ocorrencia de erro
     */
    private boolean setErro(String e){
        erro=e;
        return false;
    }
    
    /**     
     * @return  Erro ocorrido
     */
    public String getErro(){
        return erro;
    }
    
    /**
     * Gera uma chave privada com o openssl
     * @param pathKey Endereco no sistema de arquivode onde a chave sera gravada
     * @return verdadeiro em caso de sucesso.
     */
    public boolean gerarChavePrivada(String pathKey){
        
        //validacoes
        if(pathKey.length()==0)
            return setErro("Endereço informado está inválido.");
        File fPriv = new File(pathKey);
        if (fPriv.exists()) 
            return setErro("Chave privada já existe, apagar para continuar");
        
        //Executa comando OpenSSL
        //exemplo:  openssl -genrsa -out saida.txt 1024
        //          openssl -genrsa -out "/teste pasta/saida.txt" 1024        
        if(!execRuntime(openssl + " genrsa -out \"" + fPriv.getAbsolutePath() + "\" 1024"))
            return false;

        return true;
    }

    /**
     * Gera o XML de configuracoes da empresa desenvolvedora comforme a chave privada
     * o XML é utilizado para validacao das assinaturas utilizando o programa do governo
     * cECFc
     * @param pathKey Endereço da chave privada
     * @param pathHouse Endereço onde será gravada o XML de configurações
     * @return verdadeiro em caso de sucesso
     */
    public boolean gerarConfiguracoes(String pathKey,String pathHouse) {
        
        // validacoes
        if(pathHouse.length()==0)
            return setErro("Endereço informado está inválido.");
        File fPriv=new File(pathKey);
        if(!fPriv.exists())
            return setErro("Chave privada não encontrada");

        // Se encontrou o modulo deleta
        File fMod = new File("modulo.txt");
        if (fMod.exists())
            fMod.delete();
        
        // Se encontrou configuracao deleta
        File fXml = new File(pathHouse);
        if (fXml.exists())
            fXml.delete();
        
        // Cria o arquivo de modulo da chave privada
        if(!execRuntime(openssl + " rsa -in \"" + fPriv.getAbsolutePath() + "\" -modulus -out "+fMod.getName()))
            return false;

        // Lendo o arquivo com o módulo
        // Primeira linha do arquivo do módulo, contem o módulo
        // Modulus=B4FCFDB3E...F1B85675F42646EDC5
        try{
            BufferedReader modIn = new BufferedReader(new FileReader(fMod));
            String modulo = modIn.readLine();
            modIn.close();

            // Leitura do módulo após o sinal de igual
            modulo = modulo.substring(modulo.indexOf('=') + 1);

            // Inserindo módulo no Parâmetro
            String xml = MessageFormat.format(modeloXMLConfig.toString(),new Object[]{modulo});

            // Criando arquivo de configuracoes
            FileOutputStream modOut = new FileOutputStream(fXml);
            modOut.write(xml.getBytes());
            modOut.flush();
            modOut.close();
        }
        catch(IOException e){
            return setErro("Erro ao gravar arquivo de configurações");
        }

        return true;
    }
    
    /**
     * Assina um arquivo
     * @param pathKey Endereço da chave privada
     * @param pathFile Endereço do arquivo a ser assiado
     * @return Verdadeiro em caso de sucesso    
     */
    public boolean assinaArquivo(String pathKey,String pathFile){
        
        // validações
        File fPriv = new File(pathKey);		
        if (!fPriv.exists())
            return setErro("Chave privada nao encontrada");
        File fArquivo = new File(pathFile);		
        if (!fArquivo.exists())
            return setErro("Arquivo a ser assinado não encontrado");
		
        // Verifica se é um arquivo ou diretório
        if (fArquivo.isDirectory()) 
            return setErro("Impossivel assinar um diretorio ["+fArquivo.getAbsolutePath()+"]");
			
        // Verifica se tem permissao de escriuta
        if (!fArquivo.canWrite()) 
            return setErro("Sem permissao de escrita no arquivo ["+fArquivo.getAbsolutePath()+"]");
	
        //arquivo temporario para receber a assinatura
        File fSign = new File("sign.tmp");

        //executa o comando openssl
        String cmd=openssl + " dgst -md5 -sign \""
				+ fPriv.getAbsolutePath() + "\" -out "
                + fSign.getName() + " -hex \""
				+ fArquivo.getAbsolutePath()+"\"";
        if(!execRuntime(cmd)) return false;
        
        // Verifica se o arquivo foi gerado
        if(!fSign.exists())
            return setErro("Comando OpenSSL executado, porem arquivo temporario com a assinatura ["+fSign.getAbsolutePath()+"] não foi gerado");

		// Leitura do conteúdo da assintatura
		StringBuilder sbSign = new StringBuilder();
        try{
            FileInputStream inSign = new FileInputStream(fSign);
            byte[] b = new byte[inSign.available()];
            inSign.read(b);
            sbSign.append(new String(b));
        }
        catch(IOException e){
            return setErro("Erro ao abrir arquivo temporário.");
        }

        // Aplica a assinatura no arquivo
		String assinatura = "EAD"+sbSign.substring(sbSign.indexOf("=")+1).trim()+"\r\n";
        try{            
            FileOutputStream outArquivo = new FileOutputStream(fArquivo,true);
            outArquivo.write(assinatura.getBytes());
            outArquivo.flush();
            outArquivo.close();
        }
        catch(IOException e){
            return setErro("Erro ao gravar assinatura do arquivo.");
        }
        
        return true;
    }
    
    /**
     * Executa um comando no sistema operacional
     * @param cmd Comando a ser executado
     * @return Verdadeiro em caso de sucesso
     */
    private boolean execRuntime(String cmd){
        try{
            Process pr = Runtime.getRuntime().exec(cmd);            
            int status = pr.waitFor();
            if (status != 0) 
                return setErro("Falha ao executar comando ["+cmd+"]");
        }
        catch(IOException e){
            return setErro("Erro ao executar comando ["+cmd+"] (IOException)");
        }
        catch(InterruptedException e){
            return setErro("Erro ao executar OpenSSL ["+cmd+"] (InterruptedException)");
        }
        return true;
    }
}

Você vai precisar do executável do openssl para executar no Windows

Obrigado…vou estudar a sua classe e ver no que eu estou errando … vou baixar esse openssl …para ver aqui…
Muito obrigado…

o que não entendo é que criptografo usando chave publica e descriptografo e ele funciona, mas nao valida o eECFc…
Vou tentar implementar dessa forma aí que vc postou para ver se utilizando o ssl ele aceita

Gerei uma nova classe utilizando a sua idéia,de usar o openssl para gerar as assinaturas e funcionou…
Através desta classe que me passou, pude entender o funcionamento do openssl para gerar a assinatura… e como interagir com ele…
Muito obrigado…!!!

Só mais uma coisa… Seria confiável deixar um arquivo com a chave privada no sistema? Tipo, gerar um .PEM e deixar lá no meio dos arquivos de instalação? seria seguro?