Ignore:
Timestamp:
09/13/10 15:01:56 (14 years ago)
Author:
rafaelraymundo
Message:

Ticket #1237 - Atualizados componentes de suporte ao uso do Certificado Digital.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2/security/ExpressoCert/src/br/gov/serpro/cert/DigitalCertificate.java

    r1174 r3232  
    5656import br.gov.serpro.util.Base64Utils; 
    5757import com.sun.mail.util.BASE64DecoderStream; 
     58import java.io.InputStreamReader; 
     59import java.io.OutputStream; 
     60import java.io.OutputStreamWriter; 
     61import java.io.PipedInputStream; 
     62import java.io.PipedOutputStream; 
    5863import java.security.AlgorithmParameters; 
     64import javax.activation.CommandMap; 
     65import javax.activation.MailcapCommandMap; 
    5966import javax.mail.BodyPart; 
     67import javax.mail.internet.ContentType; 
     68import javax.mail.internet.MimeUtility; 
     69import javax.mail.internet.PreencodedMimeBodyPart; 
    6070import org.bouncycastle.asn1.ASN1InputStream; 
    6171import org.bouncycastle.asn1.DERObject; 
     
    7181 * @author Mário César Kolling - mario.kolling@serpro.gov.br 
    7282 */ 
    73  
    7483//TODO: Criar exceções para serem lançadas, entre elas DigitalCertificateNotLoaded 
    7584//TODO: Adicionar setup 
    76  
    7785public class DigitalCertificate { 
    7886 
    7987    private TokenCollection tokens; 
    80         private Certificate cert; // Certificado extraído da KeyStore. Pode ser nulo. 
    81         private KeyStore keyStore; // KeyStore que guarda o certificado do usuário. Pode ser nulo. 
    82  
    83         private Frame parentFrame; 
     88    private Certificate cert; // Certificado extraído da KeyStore. Pode ser nulo. 
     89    private KeyStore keyStore; // KeyStore que guarda o certificado do usuário. Pode ser nulo. 
     90    private Frame parentFrame; 
    8491    private Setup setup; 
    85  
    86         // TODO: Transformar pkcs12Input em uma string ou URL com o caminho para a KeyStore pkcs12 
    87         private FileInputStream pkcs12Input; // stream da KeyStore pkcs12. Pode ser nulo. 
    88         private String providerName; // Nome do SecurityProvider pkcs11 carregado. Pode ser nulo. 
    89         private String hostAddress; // Endereço do host, onde a página principal do 
    90  
    91         private static final String HOME_SUBDIR; // Subdiretório dentro do diretório home do usuário. Dependente de SO. 
    92         private static final String EPASS_2000; // Caminho da biblioteca do token ePass2000. Dependente de SO. 
    93  
    94         private static final String CRLF = "\r\n"; // Separa campos na resposta do serviço de verificação de certificados 
    95         private static final String SUBJECT_ALTERNATIVE_NAME = "2.5.29.17"; // Não é mais utilizado. 
    96         private static final URL[] TRUST_STORES_URLS = new URL[3]; // URLs (file:/) das TrustStores, cacerts (jre), 
    97                                                                                                                            // trusted.certs e trusted.jssecerts (home do usuário) 
    98                                                                // Utilizadas para validação do certificado do servidor. 
    99         private static final String[] TRUST_STORES_PASSWORDS = null; // Senhas para cada uma das TrustStores, 
    100                                                                                                                                  // caso seja necessário. 
    101         private int keystoreStatus; 
    102         public static final int KEYSTORE_DETECTED = 0; 
    103         public static final int KEYSTORE_NOT_DETECTED = 1; 
    104         public static final int KEYSTORE_ALREADY_LOADED = 2; 
    105  
    106         /* 
    107          * Bloco estático que define os caminhos padrões da instalação da jre, 
    108          * do diretório home do usuário, e da biblioteca de sistema do token ePass2000, 
    109          * de acordo com o sistema operacional. 
     92    // TODO: Transformar pkcs12Input em uma string ou URL com o caminho para a KeyStore pkcs12 
     93    private FileInputStream pkcs12Input; // stream da KeyStore pkcs12. Pode ser nulo. 
     94    private String providerName; // Nome do SecurityProvider pkcs11 carregado. Pode ser nulo. 
     95    private String hostAddress; // Endereço do host, onde a página principal do 
     96    private static final String HOME_SUBDIR; // Subdiretório dentro do diretório home do usuário. Dependente de SO. 
     97    private static final String EPASS_2000; // Caminho da biblioteca do token ePass2000. Dependente de SO. 
     98    private static final String CRLF = "\r\n"; // Separa campos na resposta do serviço de verificação de certificados 
     99    private static final String SUBJECT_ALTERNATIVE_NAME = "2.5.29.17"; // Não é mais utilizado. 
     100    private static final URL[] TRUST_STORES_URLS = new URL[3]; // URLs (file:/) das TrustStores, cacerts (jre), 
     101    // trusted.certs e trusted.jssecerts (home do usuário) 
     102    // Utilizadas para validação do certificado do servidor. 
     103    private static final String[] TRUST_STORES_PASSWORDS = null; // Senhas para cada uma das TrustStores, 
     104    // caso seja necessário. 
     105    private int keystoreStatus; 
     106    public static final int KEYSTORE_DETECTED = 0; 
     107    public static final int KEYSTORE_NOT_DETECTED = 1; 
     108    public static final int KEYSTORE_ALREADY_LOADED = 2; 
     109 
     110    /* 
     111     * Bloco estático que define os caminhos padrões da instalação da jre, 
     112     * do diretório home do usuário, e da biblioteca de sistema do token ePass2000, 
     113     * de acordo com o sistema operacional. 
     114     */ 
     115    static { 
     116 
     117        Properties systemProperties = System.getProperties(); 
     118        Map<String, String> env = System.getenv(); 
     119 
     120        /* TODO: Testar a existência de vários drivers de dispositivos. Determinar qual deve ser utilizado 
     121         * e guardar em uma property no subdiretório home do usuário. 
    110122         */ 
    111         static { 
    112  
    113                 Properties systemProperties = System.getProperties(); 
    114         Map<String, String> env = System.getenv(); 
    115  
    116                 /* TODO: Testar a existência de vários drivers de dispositivos. Determinar qual deve ser utilizado 
    117                  * e guardar em uma property no subdiretório home do usuário. 
    118                  */ 
    119  
    120                 if (systemProperties.getProperty("os.name").equalsIgnoreCase("linux")){ 
    121                         HOME_SUBDIR = "/.java/deployment/security"; 
    122                         EPASS_2000 = "/usr/lib/libepsng_p11.so"; 
    123                 } 
    124                 else { 
    125                         HOME_SUBDIR = "\\dados de aplicativos\\sun\\java\\deployment\\security"; 
    126                         EPASS_2000 = System.getenv("SystemRoot")+"\\system32\\ngp11v211.dll"; 
    127             //EPASS_2000 = System.getenv("ProgramFiles")+"\\Gemplus\\GemSafe Libraries\\BIN\\gclib.dll"; 
    128                 } 
    129  
    130                 try { 
    131                         if (systemProperties.getProperty("os.name").equalsIgnoreCase("linux")){ 
    132                                 TRUST_STORES_URLS[0] = new File(systemProperties.getProperty("java.home") 
    133                                         + "/lib/security/cacerts").toURI().toURL(); 
    134                                 TRUST_STORES_URLS[1] = new File(systemProperties.getProperty("user.home") 
    135                                         + HOME_SUBDIR + "/trusted.certs").toURI().toURL(); 
    136                                 TRUST_STORES_URLS[2] = new File(systemProperties.getProperty("user.home") 
    137                                         + HOME_SUBDIR + "/trusted.jssecerts").toURI().toURL(); 
    138                         } else { 
    139  
    140                                 TRUST_STORES_URLS[0] = new File(systemProperties.getProperty("java.home") + 
    141                                                 "\\lib\\security\\cacerts").toURI().toURL(); 
    142                                 TRUST_STORES_URLS[1] = new File(systemProperties.getProperty("user.home") + 
    143                                                 HOME_SUBDIR + "\\trusted.certs").toURI().toURL(); 
    144                                 TRUST_STORES_URLS[2] = new File(systemProperties.getProperty("user.home") + 
    145                                                 HOME_SUBDIR + "\\trusted.jssecerts").toURI().toURL(); 
    146                         } 
    147  
    148  
    149                 } catch (MalformedURLException e) { 
    150                         e.printStackTrace(); 
    151                 } 
    152         } 
    153  
    154         /** 
    155          * 
    156          */ 
    157         public DigitalCertificate() { 
    158                 this.hostAddress = null; 
    159                 this.parentFrame = null; 
    160         } 
    161  
    162         /** 
    163          * Construtor da classe. Recebe a {@link URL} da página em que a Applet está incluída. 
    164          * @param pageAddress URL da página em que a Applet está incluída 
    165          */ 
    166         private DigitalCertificate(URL pageAddress){ 
    167                 this.hostAddress = pageAddress.getHost(); 
    168                 this.parentFrame = null; 
    169         } 
    170  
    171         private DigitalCertificate(Frame parent){ 
    172                 this.hostAddress = null; 
    173                 this.parentFrame = parent; 
    174         } 
    175  
    176  
    177     public DigitalCertificate(Frame parent, Setup setup){ 
    178                 this(parent); 
    179         this.setup = setup; 
    180         } 
    181  
    182     public DigitalCertificate(URL pageAddress, Setup setup){ 
    183                 this(pageAddress); 
    184         this.setup = setup; 
    185         } 
    186  
    187         /** 
    188          * Destrói a Applet, removendo o security provider inicializado se o atributo providerName 
    189          * for diferente de nulo. 
    190          */ 
    191         public void destroy(){ 
    192  
    193                 AuthProvider ap = null; 
    194  
    195         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    196             System.out.println("logout no provider"); 
    197         } 
    198                 if (keyStore != null){ 
    199                         ap = (AuthProvider) this.keyStore.getProvider(); 
    200                 } 
    201  
    202                 if (ap != null){ 
    203                         try { 
    204                                 ap.logout(); 
    205                         } catch (LoginException e) { 
    206                 if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    207                     e.printStackTrace(); 
    208                 } 
    209                         } 
    210                 } 
    211  
    212                 if (providerName != null){ 
    213                         Security.removeProvider(providerName); 
    214                 } 
    215  
    216                 this.cert = null; 
    217                 this.keyStore = null; 
    218                 this.hostAddress = null; 
    219                 this.pkcs12Input = null; 
    220                 this.providerName = null; 
    221  
    222         } 
    223  
    224         /** 
    225           * Procura pelo token nos locais padrões (Por enquanto só suporta o token ePass200), 
    226           * senão procura por um certificado A1 em System.getProperties().getProperty("user.home") + 
    227           * HOME_SUBDIR  + "/trusted.clientcerts" e retorna um inteiro de acordo com resultado desta procura. 
    228           * 
    229           * @author     Mário César Kolling 
    230           * @return     Retorna um destes valores inteiros DigitalCertificate.KEYSTORE_DETECTED, 
    231           *             DigitalCertificate.KEYSTORE_ALREADY_LOADED ou DigitalCertificate.KEYSTORE_NOT_DETECTED 
    232           * @see        DigitalCertificate 
    233           */ 
    234         public int init(){ 
    235  
    236                 // TODO: Usar dentro de um "loop" para testar outros modelos de tokens. 
    237         this.tokens = new TokenCollection(setup); 
    238                 int interfaceType = DigitalCertificate.KEYSTORE_DETECTED; 
    239  
    240                 try 
    241                 { 
    242                         // Tenta abrir o Token padrï¿œo (ePass2000). 
    243                         loadKeyStore(); 
    244  
    245                 } 
    246                 catch (Exception e1){ 
    247  
    248                         Provider[] providers = Security.getProviders(); 
    249             if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    250                 for (Provider provider: providers){ 
    251                     System.out.println(provider.getInfo()); 
    252                 } 
    253  
    254                 // Não conseguiu abrir o token (ePass2000). 
    255                 System.out.println("Erro ao ler o token: " + e1.getMessage()); 
    256             } 
    257  
    258                         try 
    259                         { 
    260                                 // Tenta abrir a keyStore padrão 
    261                                 // USER_HOME/deployment/security/trusted.clientcerts 
    262  
    263                                 Properties props = System.getProperties(); 
    264                                 pkcs12Input = new FileInputStream(props.getProperty("user.home") +  HOME_SUBDIR  + "/trusted.clientcerts"); 
    265  
    266                                 // Se chegar aqui significa que arquivo de KeyStore existe. 
    267                                 keyStore = KeyStore.getInstance("JKS"); 
    268  
    269                         } 
    270                         catch (Exception ioe){ 
    271                                 // Não conseguiu abrir a KeyStore pkcs12 
    272                 if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    273                     System.out.println(ioe.getMessage()); 
    274                 } 
    275                         } 
    276                 } 
    277  
    278  
    279                 if (keyStore == null){ 
    280                         // Não conseguiu inicializar a KeyStore. Mostra tela de login com usuário e senha. 
    281                         this.keystoreStatus = DigitalCertificate.KEYSTORE_NOT_DETECTED; 
    282                 //} else if (keyStore.getType().equalsIgnoreCase("pkcs11")){ 
     123 
     124        if (systemProperties.getProperty("os.name").equalsIgnoreCase("linux")) { 
     125            HOME_SUBDIR = "/.java/deployment/security"; 
     126            EPASS_2000 = "/usr/lib/libepsng_p11.so"; 
     127        } else { 
     128            HOME_SUBDIR = "\\dados de aplicativos\\sun\\java\\deployment\\security"; 
     129            EPASS_2000 = System.getenv("SystemRoot") + "\\system32\\ngp11v211.dll"; 
     130            //EPASS_2000 = System.getenv("ProgramFiles")+"\\Gemplus\\GemSafe Libraries\\BIN\\gclib.dll"; 
     131        } 
     132 
     133        try { 
     134            if (systemProperties.getProperty("os.name").equalsIgnoreCase("linux")) { 
     135                TRUST_STORES_URLS[0] = new File(systemProperties.getProperty("java.home") + "/lib/security/cacerts").toURI().toURL(); 
     136                TRUST_STORES_URLS[1] = new File(systemProperties.getProperty("user.home") + HOME_SUBDIR + "/trusted.certs").toURI().toURL(); 
     137                TRUST_STORES_URLS[2] = new File(systemProperties.getProperty("user.home") + HOME_SUBDIR + "/trusted.jssecerts").toURI().toURL(); 
     138            } else { 
     139 
     140                TRUST_STORES_URLS[0] = new File(systemProperties.getProperty("java.home") + 
     141                        "\\lib\\security\\cacerts").toURI().toURL(); 
     142                TRUST_STORES_URLS[1] = new File(systemProperties.getProperty("user.home") + 
     143                        HOME_SUBDIR + "\\trusted.certs").toURI().toURL(); 
     144                TRUST_STORES_URLS[2] = new File(systemProperties.getProperty("user.home") + 
     145                        HOME_SUBDIR + "\\trusted.jssecerts").toURI().toURL(); 
     146            } 
     147 
     148            // Define os tipos smime no mailcap 
     149            MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); 
     150 
     151            mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature"); 
     152            mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime"); 
     153            mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature"); 
     154            mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime"); 
     155            mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed"); 
     156 
     157            CommandMap.setDefaultCommandMap(mailcap); 
     158 
     159 
     160 
     161        } catch (MalformedURLException e) { 
     162            e.printStackTrace(); 
     163        } 
     164    } 
     165 
     166    /** 
     167     * 
     168     */ 
     169    public DigitalCertificate() { 
     170        this.hostAddress = null; 
     171        this.parentFrame = null; 
     172    } 
     173 
     174    /** 
     175     * Construtor da classe. Recebe a {@link URL} da página em que a Applet está incluída. 
     176     * @param pageAddress URL da página em que a Applet está incluída 
     177     */ 
     178    private DigitalCertificate(URL pageAddress) { 
     179        this.hostAddress = pageAddress.getHost(); 
     180        this.parentFrame = null; 
     181    } 
     182 
     183    private DigitalCertificate(Frame parent) { 
     184        this.hostAddress = null; 
     185        this.parentFrame = parent; 
     186    } 
     187 
     188    public DigitalCertificate(Frame parent, Setup setup) { 
     189        this(parent); 
     190        this.setup = setup; 
     191    } 
     192 
     193    public DigitalCertificate(URL pageAddress, Setup setup) { 
     194        this(pageAddress); 
     195        this.setup = setup; 
     196    } 
     197 
     198    public KeyStore getKeyStore() { 
     199        return keyStore; 
     200    } 
     201 
     202    public int getKeystoreStatus() { 
     203        return keystoreStatus; 
     204    } 
     205 
     206    public String getProviderName() { 
     207        return providerName; 
     208    } 
     209 
     210    /** 
     211     * Destrói a Applet, removendo o security provider inicializado se o atributo providerName 
     212     * for diferente de nulo. 
     213     */ 
     214    public void destroy() { 
     215 
     216        AuthProvider ap = null; 
     217 
     218        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     219            System.out.println("logout no provider"); 
     220        } 
     221        if (keyStore != null) { 
     222            ap = (AuthProvider) this.keyStore.getProvider(); 
     223        } 
     224 
     225        if (ap != null) { 
     226            try { 
     227                ap.logout(); 
     228            } catch (LoginException e) { 
     229                if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     230                    e.printStackTrace(); 
     231                } 
     232            } 
     233        } 
     234 
     235        if (providerName != null) { 
     236            Security.removeProvider(providerName); 
     237        } 
     238 
     239        this.cert = null; 
     240        this.keyStore = null; 
     241        this.hostAddress = null; 
     242        this.pkcs12Input = null; 
     243        this.providerName = null; 
     244 
     245    } 
     246 
     247    /** 
     248     * Procura pelo token nos locais padrões (Por enquanto só suporta o token ePass200), 
     249     * senão procura por um certificado A1 em System.getProperties().getProperty("user.home") + 
     250     * HOME_SUBDIR  + "/trusted.clientcerts" e retorna um inteiro de acordo com resultado desta procura. 
     251     * 
     252     * @author  Mário César Kolling 
     253     * @return  Retorna um destes valores inteiros DigitalCertificate.KEYSTORE_DETECTED, 
     254     *          DigitalCertificate.KEYSTORE_ALREADY_LOADED ou DigitalCertificate.KEYSTORE_NOT_DETECTED 
     255     * @see     DigitalCertificate 
     256     */ 
     257    public int init() { 
     258 
     259        // TODO: Usar dentro de um "loop" para testar outros modelos de tokens. 
     260        this.tokens = new TokenCollection(setup); 
     261        int interfaceType = DigitalCertificate.KEYSTORE_DETECTED; 
     262 
     263        try { 
     264            // Tenta abrir o Token padrï¿œo (ePass2000). 
     265            loadKeyStore(); 
     266 
     267        } catch (Exception e1) { 
     268 
     269            Provider[] providers = Security.getProviders(); 
     270            if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     271                for (Provider provider : providers) { 
     272                    System.out.println(provider.getInfo()); 
     273                } 
     274 
     275                // Não conseguiu abrir o token (ePass2000). 
     276                System.out.println("Erro ao ler o token: " + e1.getMessage()); 
     277            } 
     278 
     279            try { 
     280                // Tenta abrir a keyStore padrão 
     281                // USER_HOME/deployment/security/trusted.clientcerts 
     282 
     283                Properties props = System.getProperties(); 
     284                pkcs12Input = new FileInputStream(props.getProperty("user.home") + HOME_SUBDIR + "/trusted.clientcerts"); 
     285 
     286                // Se chegar aqui significa que arquivo de KeyStore existe. 
     287                keyStore = KeyStore.getInstance("JKS"); 
     288 
     289            } catch (Exception ioe) { 
     290                // Não conseguiu abrir a KeyStore pkcs12 
     291                if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     292                    System.out.println(ioe.getMessage()); 
     293                } 
     294            } 
     295        } 
     296 
     297 
     298        if (keyStore == null) { 
     299            // Não conseguiu inicializar a KeyStore. Mostra tela de login com usuário e senha. 
     300            this.keystoreStatus = DigitalCertificate.KEYSTORE_NOT_DETECTED; 
     301            //} else if (keyStore.getType().equalsIgnoreCase("pkcs11")){ 
     302        } else { 
     303            // Usa certificado digital. 
     304            try { 
     305                // Testa se uma keystore já foi carregada previamente 
     306                if (keyStore.getType().equalsIgnoreCase("pkcs11")) { 
     307                    keyStore.load(null, null); 
    283308                } else { 
    284                         // Usa certificado digital. 
    285                         try { 
    286                                 // Testa se uma keystore já foi carregada previamente 
    287                                 if (keyStore.getType().equalsIgnoreCase("pkcs11")){ 
    288                                         keyStore.load(null, null); 
    289                                 } else { 
    290                                         keyStore.load(pkcs12Input, null); 
    291                                 } 
    292  
    293                                 // Se chegou aqui KeyStore está liberada, mostrar tela de login sem pedir o pin. 
    294                                 this.keystoreStatus = DigitalCertificate.KEYSTORE_ALREADY_LOADED; 
    295  
    296                         } catch (ProviderException e) { 
    297                                 // Algum erro ocorreu, mostra  tela de login com usuário e senha. 
    298                                 this.keystoreStatus = DigitalCertificate.KEYSTORE_NOT_DETECTED; 
    299                                 if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    300                     e.printStackTrace(); 
    301                 } 
    302                         } catch (IOException e){ 
    303                                 // KeyStore não está liberada, mostra tela de login com o pin. 
    304                 if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    305                     System.out.println(e.getMessage()); 
    306                 } 
    307                                 this.keystoreStatus = DigitalCertificate.KEYSTORE_DETECTED; 
    308                         } catch (GeneralSecurityException e){ 
    309                 if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    310                     e.printStackTrace(); 
    311                 } 
    312                         } 
    313                 } 
    314  
    315                 return keystoreStatus; 
    316  
    317         } 
    318  
    319         /** 
    320          * Usado para assinar digitalmente um e-mail. 
    321          * @param mime 
    322          * @return String vazia 
    323          */ 
    324         public String signMail (Map<String, String> data) throws IOException, GeneralSecurityException, SMIMEException, MessagingException{ 
    325  
    326                 Key privateKey = null; 
    327                 if (this.keystoreStatus == DigitalCertificate.KEYSTORE_DETECTED){ 
    328                         String pin = DialogBuilder.showPinDialog(this.parentFrame, this.setup); 
    329                         if (pin != null){ 
    330                                 openKeyStore(pin.toCharArray()); 
    331                                 privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), pin.toCharArray()); 
    332                         } 
    333                         else { 
    334                                 return null; 
    335                         } 
    336                 } 
    337         /* 
    338                 else if (this.keystoreStatus == DigitalCertificate.KEYSTORE_ALREADY_LOADED){ 
    339                                 if (DialogBuilder.showPinNotNeededDialog(this.parentFrame)){ 
    340                                         openKeyStore(null); 
    341                                         privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), null); 
    342                                 } 
    343                                 else { 
    344                                         return null; 
    345                                 } 
    346                 } 
    347          */ 
    348                 else { 
    349  
    350             //DialogBuilder.showMessageDialog(this.parentFrame, "Nenhum token/smartcard foi detectado.\nOperação não pôde ser realizada!"); 
    351             DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate001"), this.setup); 
    352                         return null; 
    353                 } 
    354  
    355                 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    356  
    357                 Certificate certificate = getCert(); 
    358  
    359                 KeyPair keypair = new KeyPair(certificate.getPublicKey(), (PrivateKey) privateKey); 
    360  
    361                 // Cria a cadeia de certificados que a gente vai enviar 
    362         List certList = new ArrayList(); 
    363  
    364         certList.add(certificate); 
    365  
    366         // 
    367         // create the base for our message 
    368                 // 
    369         String fullMsg = data.get("body"); 
    370  
    371         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    372             System.out.println("Corpo do e-mail:\n"+fullMsg+"\n"); 
    373         } 
    374          
    375         // 
    376         // Get a Session object and create the mail message 
    377         // 
    378         Properties props = System.getProperties(); 
    379         Session session = Session.getDefaultInstance(props, null); 
    380  
    381         InputStream is = new ByteArrayInputStream(fullMsg.getBytes("iso-8859-1")); 
    382                 MimeMessage unsignedMessage = new MimeMessage(session, is); 
    383  
    384         // 
    385         // create a CertStore containing the certificates we want carried 
    386         // in the signature 
    387         // 
    388         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    389             System.out.println("Provider: " + providerName); 
    390         } 
    391         CertStore certsAndcrls = CertStore.getInstance( 
    392                                 "Collection", 
    393                                 new CollectionCertStoreParameters(certList), "BC"); 
    394  
    395         // 
    396         // create some smime capabilities in case someone wants to respond 
    397         // 
    398         ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); 
    399  
    400         SMIMECapabilityVector       caps = new SMIMECapabilityVector(); 
    401  
    402         caps.addCapability(SMIMECapability.dES_EDE3_CBC); 
    403         caps.addCapability(SMIMECapability.rC2_CBC, 128); 
    404         caps.addCapability(SMIMECapability.dES_CBC); 
    405  
    406                 SMIMESignedGenerator gen = new SMIMESignedGenerator(unsignedMessage.getEncoding()); 
    407  
    408                 gen.addSigner(keypair.getPrivate(), (X509Certificate) certificate, SMIMESignedGenerator.DIGEST_SHA1, new AttributeTable(signedAttrs), null); 
    409  
    410                 gen.addCertificatesAndCRLs(certsAndcrls); 
    411  
    412         //TODO: Extrair todos os headers de unsignedMessage 
    413  
    414                 // Gera a assinatura 
    415                 Object content = unsignedMessage.getContent(); 
    416  
    417                 //TODO: igualar unsignedMessage a null 
    418                 //TODO: Pegar os headers do objeto que guardarï¿œ esses headers quando necessï¿œrio. 
    419  
    420                 MimeMultipart mimeMultipartContent = null; 
    421                 MimeBodyPart mimeBodyPartContent = new MimeBodyPart(); 
    422  
    423                 if (content.getClass().getName().contains("MimeMultipart")){ 
    424                         mimeMultipartContent = (MimeMultipart) content; 
    425                 } 
    426                 else { 
    427                         is = new ByteArrayInputStream(content.toString().getBytes("iso-8859-1")); 
    428                         mimeBodyPartContent = new MimeBodyPart(is); 
    429                         mimeBodyPartContent.setHeader("Content-Type", unsignedMessage.getHeader("Content-Type", null)); //TODO: testar se valor existe 
    430                         is = null; 
    431                 } 
    432                 content = null; 
    433  
    434                 MimeBodyPart msg = null; 
    435                 if (mimeMultipartContent == null){ 
    436                         msg = mimeBodyPartContent; 
    437                         mimeBodyPartContent = null; 
    438                 } 
    439                 else { 
    440                         msg = new MimeBodyPart(); 
    441                         msg.setContent(mimeMultipartContent); 
    442                         mimeMultipartContent = null; 
    443                 } 
    444  
    445         // 
    446         // extract the multipart object from the SMIMESigned object. 
    447         // 
    448         MimeMultipart mm = gen.generate(msg, providerName); 
    449         gen = null; 
    450         msg = null; 
    451  
    452         MimeMessage body = new MimeMessage(session); 
    453         body.setFrom(unsignedMessage.getFrom()[0]); 
    454         body.setRecipients(Message.RecipientType.TO, unsignedMessage.getRecipients(Message.RecipientType.TO)); 
    455         body.setRecipients(Message.RecipientType.CC, unsignedMessage.getRecipients(Message.RecipientType.CC)); 
    456         body.setRecipients(Message.RecipientType.BCC, unsignedMessage.getRecipients(Message.RecipientType.BCC)); 
    457         body.setSubject(unsignedMessage.getSubject(), "iso-8859-1"); 
    458  
    459         // Atrafuia o resto dos headers         
    460         body.setHeader("Return-Path", unsignedMessage.getHeader("Return-Path", null)); 
    461         body.setHeader("Message-ID", unsignedMessage.getHeader("Message-ID", null)); 
    462         body.setHeader("X-Priority", unsignedMessage.getHeader("X-Priority", null)); 
    463         body.setHeader("X-Mailer", unsignedMessage.getHeader("X-Mailer", null)); 
    464         body.setHeader("Disposition-Notification-To", unsignedMessage.getHeader("Disposition-Notification-To", null)); 
    465         body.setHeader("Date", unsignedMessage.getHeader("Date", null)); 
    466         body.setContent(mm, mm.getContentType()); 
    467         mm = null; 
    468  
    469         if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
    470             System.out.println("\nHeaders do e-mail original:\n"); 
    471         } 
    472  
    473         body.saveChanges(); 
    474  
    475         ByteArrayOutputStream oStream = new ByteArrayOutputStream(); 
    476          
    477         oStream = new ByteArrayOutputStream(); 
    478         body.writeTo(oStream); 
    479        
    480         body = null; 
    481         return oStream.toString("iso-8859-1"); 
    482  
    483         } 
    484      
    485         /** 
    486          * Método utilizado para criptografar um e-mail 
    487          * @param source 
    488          * @return 
    489          */ 
    490     public String cipherMail(Map<String, String> data) throws IOException, GeneralSecurityException, MessagingException, CMSException, SMIMEException{ 
    491          
    492         //Pega certificado do usuário. 
    493          
    494         Key privateKey = null; 
    495                 if (this.keystoreStatus == DigitalCertificate.KEYSTORE_DETECTED){ 
    496                         String pin = DialogBuilder.showPinDialog(this.parentFrame, this.setup); 
    497                         if (pin != null){ 
    498                                 openKeyStore(pin.toCharArray()); 
    499                                 privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), pin.toCharArray()); 
    500                         } 
    501                         else { 
    502                                 return null; 
    503                         } 
    504                 } 
    505         /* 
    506                 else if (this.keystoreStatus == DigitalCertificate.KEYSTORE_ALREADY_LOADED){ 
    507                                 if (DialogBuilder.showPinNotNeededDialog(this.parentFrame)){ 
    508                                         openKeyStore(null); 
    509                                         privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), null); 
    510                                 } 
    511                                 else { 
    512                                         return null; 
    513                                 } 
    514                 } 
    515          */ 
    516                 else { 
    517  
    518             //DialogBuilder.showMessageDialog(this.parentFrame, "Nenhum token/smartcard foi detectado.\nOperação não pôde ser realizada!"); 
    519             DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate001"), this.setup); 
    520                         return null; 
    521                 } 
    522  
    523                 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    524  
    525                 X509Certificate cert = (X509Certificate)getCert(); 
    526          
    527         RecipientId recId = new RecipientId(); 
    528         recId.setSerialNumber(cert.getSerialNumber()); 
    529         recId.setIssuer(cert.getIssuerX500Principal()); 
    530          
    531         Properties props = System.getProperties(); 
    532         Session session = Session.getDefaultInstance(props, null); 
    533          
    534         String fullMsg = data.get("body"); 
    535         InputStream is = new ByteArrayInputStream(fullMsg.getBytes("iso-8859-1")); 
    536         MimeMessage encriptedMsg = new MimeMessage(session, is); 
    537  
    538         Provider prov = Security.getProvider(providerName); 
    539         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    540             System.out.println("Serviços do provider "+providerName+ ":\n"+ prov.getInfo()); 
    541             for (Provider.Service service: prov.getServices()) 
    542                 System.out.println(service.toString() + ": " + service.getAlgorithm()); 
    543         } 
    544  
    545         if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
    546             System.out.println("Email criptografado:\n" + fullMsg); 
    547         } 
    548  
    549         SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(encriptedMsg); 
    550         if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
    551             System.out.println("Algoritmo de encriptação: " + m.getEncryptionAlgOID()); 
    552         } 
    553  
    554         AlgorithmParameters algParams = m.getEncryptionAlgorithmParameters("BC"); 
    555         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    556             System.out.println("Parâmetros do algoritmo: " + algParams.toString()); 
    557         } 
    558  
    559         RecipientInformationStore recipients = m.getRecipientInfos(); 
    560         RecipientInformation recipient = recipients.get(recId); 
    561  
    562         if (recipient != null){ 
    563             MimeBodyPart decriptedBodyPart = SMIMEUtil.toMimeBodyPart(recipient.getContentStream(privateKey, this.providerName)); 
    564             encriptedMsg.setContent(decriptedBodyPart.getContent(), decriptedBodyPart.getContentType()); 
    565             encriptedMsg.saveChanges(); 
    566  
    567             ByteArrayOutputStream oStream = new ByteArrayOutputStream(); 
    568             encriptedMsg.writeTo(oStream); 
    569             encriptedMsg = null; 
    570  
    571             return oStream.toString("iso-8859-1"); 
    572         } 
    573         else { 
    574             //DialogBuilder.showMessageDialog(this.parentFrame, "Não é possível ler este e-mail com o Certificado Digital apresentado!\n" + 
    575             //        "Motivo: Este e-mail não foi cifrado com a chave pública deste Certificado Digital."); 
    576             DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate002"), this.setup); 
    577             return null; 
    578         } 
    579     } 
    580  
    581         /** 
    582          * Pega as credenciais de login do dono do certificado do serviço de verificação de certificados 
    583          * @param       pin                     pin para acessar o token 
    584          * @return      resposta        Array de Strings em que: 
    585          *                                              Indice 0: código de retorno; 
    586          *                                              Indice 1: username se código de retorno for 0, senão mensagem de erro; 
    587          *                                              Indice 2: senha decriptada se código de retorno for 0, senão não existe; 
    588          * @throws SSLHandshakeException 
    589          * @throws HttpException 
    590          * @throws IOException 
    591          * @throws GeneralSecurityException 
    592          */ 
    593         public String[] getCredentials(String pin) throws SSLHandshakeException, HttpException, IOException, GeneralSecurityException{ 
    594  
    595                 String[] resposta = null; 
    596  
    597         if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    598             System.out.println("Proxy Configurado no browser: " + System.getProperty("http.proxyHost") 
    599                     + ":" + System.getProperty("http.proxyPort")); 
    600         } 
    601  
    602                 // Registra novo protocolo https, utilizando nova implementação de AuthSSLProtocolSocketFactory 
    603                 Protocol.registerProtocol("https", new Protocol("https", 
    604                                 (ProtocolSocketFactory) new AuthSSLProtocolSocketFactory(TRUST_STORES_URLS, TRUST_STORES_PASSWORDS, this.setup), 
    605                                 443)); 
    606  
    607                 HttpClient httpclient = new HttpClient(); 
    608                 // Define um método post para o link do serviço de verificação de certificados 
    609         if (System.getProperty("http.proxyHost") != null && System.getProperty("http.proxyPort") != null){ 
    610             httpclient.getHostConfiguration().setProxy(System.getProperty("http.proxyHost"), 
    611                     Integer.parseInt(System.getProperty("http.proxyPort"))); 
    612         } 
    613                 PostMethod httppost = new PostMethod("https://"+ hostAddress + "/security/vercert.php"); 
    614  
    615                 try { 
    616                         // Adiciona parâmetro certificado no método post, executa o método, pega a resposta do servidor 
    617                         // como uma string com CRLF de separador entre os campos e gera um array de Strings 
    618                         httppost.addParameter("certificado", Base64Utils.der2pem(cert.getEncoded())); 
    619                         httpclient.executeMethod(httppost); 
    620                         resposta = httppost.getResponseBodyAsString().split(CRLF); 
    621  
    622                         if (resposta.length > 2){ 
    623                                 if (Integer.parseInt(resposta[0].trim()) == 0){ 
    624                                         // Se código da resposta for zero, decripta a senha criptografada do usuário 
    625                                         resposta[2] = decriptPassword(resposta[2].trim(), pin); 
    626                                 } 
    627                         } 
    628  
    629                 } catch (IOException e){ 
    630                         // Se for instância de SSLHandshakeException faz um cast para este tipo e lança a exceção novamente 
    631                         // Isto é usado para diferenciar o tipo de falha, para que a mensagem para o usuário seja mostrada de 
    632                         // acordo. 
    633                         if (e instanceof SSLHandshakeException){ 
    634                                 throw (SSLHandshakeException) e; 
    635                         } 
    636                         // senão lança novamente a exceção do tipo IOException 
    637                         throw e; 
    638                 } finally { 
    639                         // fecha a conexão 
    640                         httppost.releaseConnection(); 
    641                 } 
    642  
    643                 return resposta; 
    644         } 
    645  
    646         /** 
    647          * Decripta a senha criptografada 
    648          * @param encodedPassword senha criptografada e codificada em base64 para ser decriptada 
    649          * @param pin pin para acessar a KeyStore 
    650          * @return decodedPassword 
    651          * @throws GeneralSecurityException se algum problema ocorrer na decriptação da senha. 
    652          */ 
    653         public String decriptPassword(String encodedPassword, String pin) throws GeneralSecurityException{ 
    654  
    655                 String decodedPassword = new String(); 
    656  
    657                 // Pega a chave privada do primeiro certificado armazenado na KeyStore 
    658                 Enumeration<String> en = this.keyStore.aliases(); 
    659                 String certAlias = en.nextElement(); 
    660                 Key privateKey = this.keyStore.getKey(certAlias, pin.toCharArray()); 
    661  
    662                 // Inicializa os cipher com os parâmetros corretos para realizar a decriptação 
    663                 Cipher dcipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
    664                 dcipher.init(Cipher.DECRYPT_MODE, privateKey); 
    665  
    666                 // Decodifica a senha em base64 e a decripta 
    667                 decodedPassword = new String(dcipher.doFinal(Base64Utils.base64Decode(encodedPassword))); 
    668  
    669                 return decodedPassword.trim(); 
    670  
    671         } 
    672  
    673         /** 
    674          * Carrega um novo SecurityProvider 
    675          * @param pkcs11Config Linha de configuração do SmartCard ou Token 
    676          * @throws KeyStoreException Quando não conseguir iniciar a KeyStore, ou a lib do Token 
    677          *                                                       ou Smartcard não foi encontrada, ou o usuário não inseriu o Token. 
    678          */ 
    679         private void loadKeyStore() throws KeyStoreException{ 
    680  
    681                 //Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(new ByteArrayInputStream(pkcs11Config.getBytes())); 
    682                 //Security.addProvider(pkcs11Provider); 
    683                 this.keyStore = KeyStore.getInstance("PKCS11"); 
    684                 this.providerName = keyStore.getProvider().getName(); 
    685  
    686         } 
    687  
    688         /** 
    689          *  Abre a keystore passando o pin 
    690          *  @param pin pin para acessar o Token 
    691          */ 
    692         public void openKeyStore(char[] pin) throws IOException{ 
    693  
    694                 try { 
    695  
    696                         if (this.keyStore.getType().equals("PKCS11")){ 
    697                                 this.keyStore.load(null, pin); 
    698                         } 
    699                         else { 
    700                                 this.keyStore.load(this.pkcs12Input, pin); 
    701                         } 
    702  
    703                         this.cert = this.keyStore.getCertificate(this.keyStore.aliases().nextElement()); 
    704  
    705                 } catch (GeneralSecurityException e) { 
    706             if (this.setup.getParameter("debug").equalsIgnoreCase("true")){ 
    707                 e.printStackTrace(); 
    708             } 
    709                 } 
    710  
    711         } 
    712  
    713         /** 
    714          * @return the cert 
    715          */ 
    716         Certificate getCert() { 
    717                 return this.cert; 
    718         } 
    719  
    720         /** 
    721          * @param cert the cert to set 
    722          */ 
    723         void setCert(Certificate cert) { 
    724                 this.cert = cert; 
    725         } 
    726  
     309                    keyStore.load(pkcs12Input, null); 
     310                } 
     311 
     312                // Se chegou aqui KeyStore está liberada, mostrar tela de login sem pedir o pin. 
     313                this.keystoreStatus = DigitalCertificate.KEYSTORE_ALREADY_LOADED; 
     314 
     315            } catch (ProviderException e) { 
     316                // Algum erro ocorreu, mostra  tela de login com usuário e senha. 
     317                this.keystoreStatus = DigitalCertificate.KEYSTORE_NOT_DETECTED; 
     318                if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     319                    e.printStackTrace(); 
     320                } 
     321            } catch (IOException e) { 
     322                // KeyStore não está liberada, mostra tela de login com o pin. 
     323                if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     324                    System.out.println(e.getMessage()); 
     325                } 
     326                this.keystoreStatus = DigitalCertificate.KEYSTORE_DETECTED; 
     327            } catch (GeneralSecurityException e) { 
     328                if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     329                    e.printStackTrace(); 
     330                } 
     331            } 
     332        } 
     333 
     334        return keystoreStatus; 
     335 
     336    } 
     337 
     338    /** 
     339     * Usado para assinar digitalmente um e-mail. 
     340     * @param mime 
     341     * @return String vazia 
     342     */ 
     343    public String signMail(Map<String, String> data) throws IOException, GeneralSecurityException, SMIMEException, MessagingException { 
     344 
     345        Key privateKey = null; 
     346        if (this.keystoreStatus == DigitalCertificate.KEYSTORE_DETECTED) { 
     347            String pin = DialogBuilder.showPinDialog(this.parentFrame, this.setup); 
     348            if (pin != null) { 
     349                openKeyStore(pin.toCharArray()); 
     350                privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), pin.toCharArray()); 
     351            } else { 
     352                return null; 
     353            } 
     354        } /* 
     355        else if (this.keystoreStatus == DigitalCertificate.KEYSTORE_ALREADY_LOADED){ 
     356        if (DialogBuilder.showPinNotNeededDialog(this.parentFrame)){ 
     357        openKeyStore(null); 
     358        privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), null); 
     359        } 
     360        else { 
     361        return null; 
     362        } 
     363        } 
     364         */ else { 
     365 
     366            //DialogBuilder.showMessageDialog(this.parentFrame, "Nenhum token/smartcard foi detectado.\nOperação não pôde ser realizada!"); 
     367            DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate001"), this.setup); 
     368            return null; 
     369        } 
     370 
     371        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
     372 
     373        Certificate certificate = getCert(); 
     374 
     375        KeyPair keypair = new KeyPair(certificate.getPublicKey(), (PrivateKey) privateKey); 
     376 
     377        // Cria a cadeia de certificados que a gente vai enviar 
     378        List certList = new ArrayList(); 
     379 
     380        certList.add(certificate); 
     381 
     382        // 
     383        // create the base for our message 
     384        // 
     385        String fullMsg = data.get("body"); 
     386 
     387        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     388            System.out.println("Corpo do e-mail:\n" + fullMsg + "\n"); 
     389        } 
     390 
     391        // 
     392        // Get a Session object and create the mail message 
     393        // 
     394        Properties props = System.getProperties(); 
     395        Session session = Session.getDefaultInstance(props, null); 
     396 
     397        InputStream is = new ByteArrayInputStream(fullMsg.getBytes("iso-8859-1")); 
     398        MimeMessage unsignedMessage = new MimeMessage(session, is); 
     399 
     400        // 
     401        // create a CertStore containing the certificates we want carried 
     402        // in the signature 
     403        // 
     404        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     405            System.out.println("Provider: " + providerName); 
     406        } 
     407        CertStore certsAndcrls = CertStore.getInstance( 
     408                "Collection", 
     409                new CollectionCertStoreParameters(certList), "BC"); 
     410 
     411        // 
     412        // create some smime capabilities in case someone wants to respond 
     413        // 
     414        ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); 
     415 
     416        SMIMECapabilityVector caps = new SMIMECapabilityVector(); 
     417 
     418        caps.addCapability(SMIMECapability.dES_EDE3_CBC); 
     419        caps.addCapability(SMIMECapability.rC2_CBC, 128); 
     420        caps.addCapability(SMIMECapability.dES_CBC); 
     421 
     422        SMIMESignedGenerator gen = new SMIMESignedGenerator(unsignedMessage.getEncoding()); 
     423 
     424        //SMIMESignedGenerator gen = new SMIMESignedGenerator(); 
     425 
     426        gen.addSigner(keypair.getPrivate(), (X509Certificate) certificate, SMIMESignedGenerator.DIGEST_SHA1, new AttributeTable(signedAttrs), null); 
     427 
     428        gen.addCertificatesAndCRLs(certsAndcrls); 
     429 
     430        //TODO: Extrair todos os headers de unsignedMessage 
     431 
     432        // Gera a assinatura 
     433        Object content = unsignedMessage.getContent(); 
     434 
     435        //TODO: igualar unsignedMessage a null 
     436        //TODO: Pegar os headers do objeto que guardarï¿œ esses headers quando necessï¿œrio. 
     437 
     438        MimeMultipart mimeMultipartContent = null; 
     439        PreencodedMimeBodyPart mimeBodyPartContent = null; 
     440 
     441        if (content.getClass().getName().contains("MimeMultipart")) { 
     442            mimeMultipartContent = (MimeMultipart) content; 
     443        } else { 
     444            String encoding = MimeUtility.getEncoding(unsignedMessage.getDataHandler()); 
     445            mimeBodyPartContent = new PreencodedMimeBodyPart(encoding); 
     446            if (encoding.equalsIgnoreCase("quoted-printable")) { 
     447                ByteArrayOutputStream os = new ByteArrayOutputStream(); 
     448                OutputStream encode = MimeUtility.encode(os, encoding); 
     449                OutputStreamWriter writer = new OutputStreamWriter(encode, "iso-8859-1"); 
     450                writer.write(content.toString()); 
     451                writer.flush(); 
     452                mimeBodyPartContent.setText(os.toString(), "iso-8859-1"); 
     453                os = null; 
     454                encode = null; 
     455                writer = null; 
     456            } else { 
     457                mimeBodyPartContent.setText(content.toString(), "iso-8859-1"); 
     458            } 
     459            mimeBodyPartContent.setHeader("Content-Type", unsignedMessage.getHeader("Content-Type", null)); 
     460        } 
     461        content = null; 
     462 
     463        // 
     464        // extract the multipart object from the SMIMESigned object. 
     465        // 
     466        MimeMultipart mm = null; 
     467        if (mimeMultipartContent == null) { 
     468            mm = gen.generate(mimeBodyPartContent, providerName); 
     469            mimeBodyPartContent = null; 
     470        } else { 
     471            MimeBodyPart multipartMsg = new MimeBodyPart(); 
     472            multipartMsg.setContent(mimeMultipartContent); 
     473            mm = gen.generate(multipartMsg, providerName); 
     474            multipartMsg = null; 
     475            mimeMultipartContent = null; 
     476        } 
     477 
     478        gen = null; 
     479 
     480        MimeMessage body = new MimeMessage(session); 
     481        body.setFrom(unsignedMessage.getFrom()[0]); 
     482        body.setRecipients(Message.RecipientType.TO, unsignedMessage.getRecipients(Message.RecipientType.TO)); 
     483        body.setRecipients(Message.RecipientType.CC, unsignedMessage.getRecipients(Message.RecipientType.CC)); 
     484        body.setRecipients(Message.RecipientType.BCC, unsignedMessage.getRecipients(Message.RecipientType.BCC)); 
     485        body.setSubject(unsignedMessage.getSubject(), "iso-8859-1"); 
     486 
     487        // Atrafuia o resto dos headers 
     488        body.setHeader("Return-Path", unsignedMessage.getHeader("Return-Path", null)); 
     489        body.setHeader("Message-ID", unsignedMessage.getHeader("Message-ID", null)); 
     490        body.setHeader("X-Priority", unsignedMessage.getHeader("X-Priority", null)); 
     491        body.setHeader("X-Mailer", unsignedMessage.getHeader("X-Mailer", null)); 
     492        body.setHeader("Disposition-Notification-To", unsignedMessage.getHeader("Disposition-Notification-To", null)); 
     493        body.setHeader("Date", unsignedMessage.getHeader("Date", null)); 
     494        body.setContent(mm, mm.getContentType()); 
     495        mm = null; 
     496 
     497        if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
     498            System.out.println("\nHeaders do e-mail original:\n"); 
     499        } 
     500 
     501        body.saveChanges(); 
     502 
     503        ByteArrayOutputStream oStream = new ByteArrayOutputStream(); 
     504 
     505        oStream = new ByteArrayOutputStream(); 
     506        body.writeTo(oStream); 
     507 
     508        body = null; 
     509        return oStream.toString("iso-8859-1"); 
     510 
     511    } 
     512 
     513    /** 
     514     * Método utilizado para criptografar um e-mail 
     515     * @param source 
     516     * @return 
     517     */ 
     518    public String cipherMail(Map<String, String> data) throws IOException, GeneralSecurityException, MessagingException, CMSException, SMIMEException { 
     519 
     520        //Pega certificado do usuário. 
     521 
     522        Key privateKey = null; 
     523        if (this.keystoreStatus == DigitalCertificate.KEYSTORE_DETECTED) { 
     524            String pin = DialogBuilder.showPinDialog(this.parentFrame, this.setup); 
     525            if (pin != null) { 
     526                openKeyStore(pin.toCharArray()); 
     527                privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), pin.toCharArray()); 
     528            } else { 
     529                return null; 
     530            } 
     531        } /* 
     532        else if (this.keystoreStatus == DigitalCertificate.KEYSTORE_ALREADY_LOADED){ 
     533        if (DialogBuilder.showPinNotNeededDialog(this.parentFrame)){ 
     534        openKeyStore(null); 
     535        privateKey = this.keyStore.getKey(keyStore.aliases().nextElement(), null); 
     536        } 
     537        else { 
     538        return null; 
     539        } 
     540        } 
     541         */ else { 
     542 
     543            //DialogBuilder.showMessageDialog(this.parentFrame, "Nenhum token/smartcard foi detectado.\nOperação não pôde ser realizada!"); 
     544            DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate001"), this.setup); 
     545            return null; 
     546        } 
     547 
     548        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
     549 
     550        X509Certificate cert = (X509Certificate) getCert(); 
     551 
     552        RecipientId recId = new RecipientId(); 
     553        recId.setSerialNumber(cert.getSerialNumber()); 
     554        recId.setIssuer(cert.getIssuerX500Principal()); 
     555 
     556        Properties props = System.getProperties(); 
     557        Session session = Session.getDefaultInstance(props, null); 
     558 
     559        String fullMsg = data.get("body"); 
     560        InputStream is = new ByteArrayInputStream(fullMsg.getBytes("iso-8859-1")); 
     561        MimeMessage encriptedMsg = new MimeMessage(session, is); 
     562 
     563        Provider prov = Security.getProvider(providerName); 
     564        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     565            System.out.println("Serviços do provider " + providerName + ":\n" + prov.getInfo()); 
     566            for (Provider.Service service : prov.getServices()) { 
     567                System.out.println(service.toString() + ": " + service.getAlgorithm()); 
     568            } 
     569        } 
     570 
     571        if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
     572            System.out.println("Email criptografado:\n" + fullMsg); 
     573        } 
     574 
     575        SMIMEEnvelopedParser m = new SMIMEEnvelopedParser(encriptedMsg); 
     576        if (setup.getParameter("debug").equalsIgnoreCase("true")) { 
     577            System.out.println("Algoritmo de encriptação: " + m.getEncryptionAlgOID()); 
     578        } 
     579 
     580        AlgorithmParameters algParams = m.getEncryptionAlgorithmParameters("BC"); 
     581        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     582            System.out.println("Parâmetros do algoritmo: " + algParams.toString()); 
     583        } 
     584 
     585        RecipientInformationStore recipients = m.getRecipientInfos(); 
     586        RecipientInformation recipient = recipients.get(recId); 
     587 
     588        if (recipient != null) { 
     589            String retorno; 
     590 
     591            MimeBodyPart decriptedBodyPart = SMIMEUtil.toMimeBodyPart(recipient.getContent(privateKey, getProviderName())); 
     592 
     593            if ((new ContentType(decriptedBodyPart.getContentType())).getSubType().equalsIgnoreCase("x-pkcs7-mime")) { 
     594                StringBuffer sb = new StringBuffer(encriptedMsg.getSize()); 
     595 
     596                for (Enumeration e = encriptedMsg.getAllHeaderLines(); e.hasMoreElements();) { 
     597                    String header = (String) e.nextElement(); 
     598                    if (!header.contains("Content-Type") && 
     599                            !header.contains("Content-Transfer-Encoding") && 
     600                            !header.contains("Content-Disposition")) { 
     601                        sb.append(header); 
     602                        sb.append("\r\n"); 
     603                    } 
     604                } 
     605                ByteArrayOutputStream oStream = new ByteArrayOutputStream(); 
     606                decriptedBodyPart.writeTo(oStream); 
     607                decriptedBodyPart = null; 
     608                encriptedMsg = null; 
     609 
     610                sb.append(oStream.toString("iso-8859-1")); 
     611 
     612                retorno = sb.toString(); 
     613 
     614            } else { 
     615                encriptedMsg.setContent(decriptedBodyPart.getContent(), decriptedBodyPart.getContentType()); 
     616                encriptedMsg.saveChanges(); 
     617 
     618                ByteArrayOutputStream oStream = new ByteArrayOutputStream(); 
     619                encriptedMsg.writeTo(oStream); 
     620                encriptedMsg = null; 
     621 
     622                retorno = oStream.toString("iso-8859-1"); 
     623            } 
     624 
     625            return retorno; 
     626        } else { 
     627            //DialogBuilder.showMessageDialog(this.parentFrame, "Não é possível ler este e-mail com o Certificado Digital apresentado!\n" + 
     628            //        "Motivo: Este e-mail não foi cifrado com a chave pública deste Certificado Digital."); 
     629            DialogBuilder.showMessageDialog(this.parentFrame, setup.getLang("ExpressoCertMessages", "DigitalCertificate002"), this.setup); 
     630            return null; 
     631        } 
     632    } 
     633 
     634    /** 
     635     * Pega as credenciais de login do dono do certificado do serviço de verificação de certificados 
     636     * @param   pin                     pin para acessar o token 
     637     * @return  resposta        Array de Strings em que: 
     638     *                                          Indice 0: código de retorno; 
     639     *                                          Indice 1: username se código de retorno for 0, senão mensagem de erro; 
     640     *                                          Indice 2: senha decriptada se código de retorno for 0, senão não existe; 
     641     * @throws SSLHandshakeException 
     642     * @throws HttpException 
     643     * @throws IOException 
     644     * @throws GeneralSecurityException 
     645     */ 
     646    public String[] getCredentials(String pin) throws SSLHandshakeException, HttpException, IOException, GeneralSecurityException { 
     647 
     648        String[] resposta = null; 
     649 
     650        if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     651            System.out.println("Proxy Configurado no browser: " + System.getProperty("http.proxyHost") + ":" + System.getProperty("http.proxyPort")); 
     652        } 
     653 
     654        // Registra novo protocolo https, utilizando nova implementação de AuthSSLProtocolSocketFactory 
     655        Protocol.registerProtocol("https", new Protocol("https", 
     656                (ProtocolSocketFactory) new AuthSSLProtocolSocketFactory(TRUST_STORES_URLS, TRUST_STORES_PASSWORDS, this.setup), 
     657                443)); 
     658 
     659        HttpClient httpclient = new HttpClient(); 
     660        // Define um método post para o link do serviço de verificação de certificados 
     661        if (System.getProperty("http.proxyHost") != null && System.getProperty("http.proxyPort") != null) { 
     662            httpclient.getHostConfiguration().setProxy(System.getProperty("http.proxyHost"), 
     663                    Integer.parseInt(System.getProperty("http.proxyPort"))); 
     664        } 
     665        PostMethod httppost = new PostMethod("https://" + hostAddress + "/security/vercert.php"); 
     666 
     667        try { 
     668            // Adiciona parâmetro certificado no método post, executa o método, pega a resposta do servidor 
     669            // como uma string com CRLF de separador entre os campos e gera um array de Strings 
     670            httppost.addParameter("certificado", Base64Utils.der2pem(cert.getEncoded())); 
     671            httpclient.executeMethod(httppost); 
     672            resposta = httppost.getResponseBodyAsString().split(CRLF); 
     673 
     674            if (resposta.length > 2) { 
     675                if (Integer.parseInt(resposta[0].trim()) == 0) { 
     676                    // Se código da resposta for zero, decripta a senha criptografada do usuário 
     677                    resposta[2] = decriptPassword(resposta[2].trim(), pin); 
     678                } 
     679            } 
     680 
     681        } catch (IOException e) { 
     682            // Se for instância de SSLHandshakeException faz um cast para este tipo e lança a exceção novamente 
     683            // Isto é usado para diferenciar o tipo de falha, para que a mensagem para o usuário seja mostrada de 
     684            // acordo. 
     685            if (e instanceof SSLHandshakeException) { 
     686                throw (SSLHandshakeException) e; 
     687            } 
     688            // senão lança novamente a exceção do tipo IOException 
     689            throw e; 
     690        } finally { 
     691            // fecha a conexão 
     692            httppost.releaseConnection(); 
     693        } 
     694 
     695        return resposta; 
     696    } 
     697 
     698    /** 
     699     * Decripta a senha criptografada 
     700     * @param encodedPassword senha criptografada e codificada em base64 para ser decriptada 
     701     * @param pin pin para acessar a KeyStore 
     702     * @return decodedPassword 
     703     * @throws GeneralSecurityException se algum problema ocorrer na decriptação da senha. 
     704     */ 
     705    public String decriptPassword(String encodedPassword, String pin) throws GeneralSecurityException { 
     706 
     707        String decodedPassword = new String(); 
     708 
     709        // Pega a chave privada do primeiro certificado armazenado na KeyStore 
     710        Enumeration<String> en = this.keyStore.aliases(); 
     711        String certAlias = en.nextElement(); 
     712        Key privateKey = this.keyStore.getKey(certAlias, pin.toCharArray()); 
     713 
     714        // Inicializa os cipher com os parâmetros corretos para realizar a decriptação 
     715        Cipher dcipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 
     716        dcipher.init(Cipher.DECRYPT_MODE, privateKey); 
     717 
     718        // Decodifica a senha em base64 e a decripta 
     719        decodedPassword = new String(dcipher.doFinal(Base64Utils.base64Decode(encodedPassword))); 
     720 
     721        return decodedPassword.trim(); 
     722 
     723    } 
     724 
     725    /** 
     726     * Carrega um novo SecurityProvider 
     727     * @param pkcs11Config Linha de configuração do SmartCard ou Token 
     728     * @throws KeyStoreException Quando não conseguir iniciar a KeyStore, ou a lib do Token 
     729     *                                                   ou Smartcard não foi encontrada, ou o usuário não inseriu o Token. 
     730     */ 
     731    private void loadKeyStore() throws KeyStoreException { 
     732 
     733        //Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(new ByteArrayInputStream(pkcs11Config.getBytes())); 
     734        //Security.addProvider(pkcs11Provider); 
     735        this.keyStore = KeyStore.getInstance("PKCS11"); 
     736        this.providerName = keyStore.getProvider().getName(); 
     737 
     738    } 
     739 
     740    /** 
     741     *  Abre a keystore passando o pin 
     742     *  @param pin pin para acessar o Token 
     743     */ 
     744    public void openKeyStore(char[] pin) throws IOException { 
     745 
     746        try { 
     747 
     748            if (this.keyStore.getType().equals("PKCS11")) { 
     749                this.keyStore.load(null, pin); 
     750            } else { 
     751                this.keyStore.load(this.pkcs12Input, pin); 
     752            } 
     753 
     754            this.cert = this.keyStore.getCertificate(this.keyStore.aliases().nextElement()); 
     755 
     756            System.out.println("Aliases (" + this.keyStore.size() + "): "); 
     757            if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     758                for (Enumeration alias = this.keyStore.aliases(); alias.hasMoreElements();) { 
     759                    System.out.println(alias.nextElement()); 
     760                } 
     761            } 
     762 
     763        } catch (GeneralSecurityException e) { 
     764            if (this.setup.getParameter("debug").equalsIgnoreCase("true")) { 
     765                e.printStackTrace(); 
     766            } 
     767        } 
     768 
     769    } 
     770 
     771    /** 
     772     * @return the cert 
     773     */ 
     774    Certificate getCert() { 
     775        return this.cert; 
     776    } 
     777 
     778    /** 
     779     * @param cert the cert to set 
     780     */ 
     781    void setCert(Certificate cert) { 
     782        this.cert = cert; 
     783    } 
    727784} 
Note: See TracChangeset for help on using the changeset viewer.