2010-02-17 5 views
1

Je veux implémenter un chargeur de classe personnalisé afin de signer numériquement mes fichiers jar. en raison de problèmes de performances, je ne veux pas crypter toutes mes classes. donc je veux implémenter un chargeur de classes personnalisé qui, lorsqu'il a été appelé , délègue la classe à son parent et si le parent n'a pas réussi à charger la classe, il le gère lui-même. ceci est mon code:problème avec classloader personnalisé

package org.dpdouran.attach; 
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.spec.AlgorithmParameterSpec;import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.spec.IvParameterSpec; 
import javax.crypto.spec.SecretKeySpec; 

public class CustomClassLoader extends ClassLoader { 
    private static final int BUFFER_SIZE = 8192; 
    @Override 
    protected Class<?> findClass(String className) throws ClassNotFoundException { 
     System.out.println("loading... "+className); 
     String clsFile = className.replace('.', '/') + ".class"; 
     InputStream in = getResourceAsStream(clsFile); 
     if(in==null) 
      return null; 
     byte[] buffer = new byte[BUFFER_SIZE]; 
     ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int n = -1; 
     try { 
      while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) { 
       out.write(buffer, 0, n); 
      } 
     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     //do decrypt 
     byte[] classBytes = out.toByteArray(); 
     byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C, 
       0x07, 0x72, 0x6F, 0x5A }; 
     AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv); 
     Cipher dcipher=null; 
     try { 
      dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     byte keyBytes[] = "abcdEFGH".getBytes(); 
     SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DES"); 
     try { 
      dcipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidAlgorithmParameterException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     byte[] dbytes = null; 
     try { 
      dbytes = dcipher.doFinal(classBytes); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return defineClass(className, dbytes, 0, dbytes.length); 
    } 
    public CustomClassLoader(ClassLoader parent){ 
     super(sun.misc.Launcher.getLauncher().getClassLoader()); 
    } 
} 

aussi j'ai changé le système par défaut classloader en changeant la propriété "java.system.class.loader". Lorsque j'exécute mon application, cela fonctionne très bien avec la classe non cryptée mais quand elle atteint la classe cryptée, elle lance ClassFormatError et ma méthode findClasses n'est jamais appelée! Comment puis-je être sûr que mon classloader personnalisé sera appelé sur des classys cryptés? grâce

Répondre

0

Essayez le réglage classloader et regardez si programatically cela fonctionne

Thread.currentThread().setContextClassLoader(myClassLoader); 

Quand j'exécutait mon classloader je mis en œuvre la méthode loadClass au lieu de FindClass. Essayez de faire quelque chose comme

try { 
    return super.loadClass(name); 
catch (Exception e) { 
    ... your code here 
} 

D'autre part, la documentation dit de ne pas surcharger loadClass mais findClass.

// Édition

Une autre idée. Il semble que vous gardiez vos classes cryptées avec des fichiers .class non cryptés. Il semble donc que le classloader parent trouve le fichier .class approprié et n'appelle jamais votre findClass. Mais le format du fichier de classe est faux, car il est crypté. La séquence est my.loadClass-> parent.loadClass-> parent.loadClass ... -> my.findClass

Vous devez donc être sûr que le classloader parent ne trouvera pas la classe. Renommez simplement les classes cryptées - donnez-leur une autre extension ou conservez-les dans un dossier séparé.

Cela devrait faire l'affaire

+0

i ont essayé, mais en le faisant je ne peux pas attraper l'exception ClassFormatError! ça jette un chemin! – arash

+0

Regardez la section // Modifier ci-dessus –

+0

La modification de l'extension des classes cryptées suffira probablement. – rsp

Questions connexes