您的位置:首页 > 移动开发 > Android开发

Android 安全——Java环境动态加载Jar之Jar包的加密和解密

2015-06-25 16:03 567 查看

编写测试Jar包

1.类结构



2.类代码

Parent.class

package com.wind.test;

abstract class Parent {
public String name() {
return "Piter";
}
}


Jim.class

package com.wind.test;

class Jim extends Parent {

public String name() {
return "My father is " + super.name() + " and my name is Jim";
}
}


Tom.class

package com.wind.test;

class Tom extends Parent{

public String name() {
return "My father is " + super.name() + " and my name is Tom";
}
}


Test.class

package com.wind.test;

public class Test {
public void print() {
Jim son1 = new Jim();
System.out.println(son1.name());
Tom son2 = new Tom();
System.out.println(son2.name());
}
}


Main.class

package com.wind.main;

import com.wind.test.Test;

public class Main {

public static void main(String[] args) {
new Test().print();
}
}


3.运行结果



4.打包

打包过程在上一篇文章有,这里就不赘述了。

Jar包的加密类

package com.wind.load.enjar;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import com.wind.load.Base64;

public class JarEncoder {
private JarInputStream jis;

public JarEncoder(String src) throws FileNotFoundException, IOException {
this(new FileInputStream(src));
}

public JarEncoder(File file) throws FileNotFoundException, IOException {
this(new FileInputStream(file));
}

public JarEncoder(InputStream is) throws IOException {
jis = new JarInputStream(is);
}

/**
* 通过指定的路径输出加密后的jar
* @param target
* @throws FileNotFoundException
* @throws IOException
*/
public void write(String target) throws FileNotFoundException, IOException {
write(new FileOutputStream(target));
}

/**
* 通过指定的文件输出加密后的jar
* @param file
* @throws FileNotFoundException
* @throws IOException
*/
public void write(File file) throws FileNotFoundException, IOException {
write(new FileOutputStream(file));
}

/**
* 通过指定的输出流输出加密后的jar
* @param os
* @throws FileNotFoundException
* @throws IOException
*/
public void write(OutputStream os) throws FileNotFoundException, IOException {
Manifest menifest = jis.getManifest(); //获取jar的Manifest信息
JarOutputStream jos = null;
if(menifest == null) {
jos = new JarOutputStream(os);
} else {
//JarInputStream的getNextJarEntry()方法无法获取Manifest信息,所以只能通过这种方式写入Manifest信息
jos = new JarOutputStream(os, menifest);
}

JarEntry entry = null;
while((entry = jis.getNextJarEntry()) != null) {
jos.putNextEntry(entry);
if(entry.getName().endsWith(".class")) { //只加密class文件

4000
byte[] bytes = getBytes(jis); //读取class文件内容
byte[] enbytes = Base64.encode(bytes); //加密后的信息
jos.write(enbytes, 0, enbytes.length); //把加密后的信息写入流
} else { //其他类型的文件直接写入流
byte[] bytes = getBytes(jis);
jos.write(bytes, 0, bytes.length);
}
jos.flush();
}
jos.close();
jis.close();
}

/**
* 从jar输入流中读取信息
* @param jis
* @return
* @throws IOException
*/
private byte[] getBytes(JarInputStream jis) throws IOException {
int len = 0;
byte[] bytes = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
while((len = jis.read(bytes, 0, bytes.length)) != -1) {
baos.write(bytes, 0, len);
}
return baos.toByteArray();
}
}


Jar包的解密类

package com.wind.load.dejar;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import com.wind.load.Base64;

public class JarDecoder extends ClassLoader {
private JarInputStream jis;
private Map<String, ByteBuffer> entryMap;

public JarDecoder(String src) throws FileNotFoundException, IOException {
this(new FileInputStream(src));
}

public JarDecoder(File file) throws FileNotFoundException, IOException {
this(new FileInputStream(file));
}

public JarDecoder(InputStream is) throws IOException {
jis = new JarInputStream(is);
entryMap = new HashMap<String, ByteBuffer>();
JarEntry entry = null;
while((entry = jis.getNextJarEntry()) != null) {
String name = entry.getName();
if(name.endsWith(".class")) { //class文件解密后再缓存
byte[] bytes = getBytes(jis); //读取class文件内容
byte[] debytes = Base64.decode(bytes); //解密class文件内容
ByteBuffer buffer = ByteBuffer.wrap(debytes); //把数据复制到ByteBuffer对象中
entryMap.put(name, buffer); //缓存数据
} else { //其他文件直接缓存
byte[] bytes = getBytes(jis);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
entryMap.put(name, buffer);
}
}
jis.close();
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
ByteBuffer buffer = entryMap.get(path);
if(buffer == null) {
return super.findClass(name);
} else {
byte[] bytes = buffer.array();
return defineClass(name, bytes, 0, bytes.length);
}
}

/**
* 从jar输入流中读取信息
* @param jis
* @return
* @throws IOException
*/
private byte[] getBytes(JarInputStream jis) throws IOException {
int len = 0;
byte[] bytes = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
while((len = jis.read(bytes, 0, bytes.length)) != -1) {
baos.write(bytes, 0, len);
}
return baos.toByteArray();
}

/**
* 关闭Decoder
* @throws IOException
*/
public void close() throws IOException {
Iterator<ByteBuffer> iterator = entryMap.values().iterator();
while(iterator.hasNext()) {
ByteBuffer buffer = iterator.next();
buffer.clear(); //清空ByteBuffer对象缓存
}
entryMap.clear(); //清空HashMap
}
}


测试类

package com.wind.load;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.wind.load.dejar.JarDecoder;
import com.wind.load.enjar.JarEncoder;

public class Main {

public static void main(String[] args) {
encode();
decode();
}

private static void encode() {
try {
JarEncoder encoder = new JarEncoder("E:/test.jar");
encoder.write("E:/test_encode.jar");
System.out.println("encode success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void decode() {
try {
JarDecoder decoder = new JarDecoder("E:/test_encode.jar");
Class<?> cls = decoder.loadClass("com.wind.test.Test");
Method method = cls.getMethod("print", null);
method.invoke(cls.newInstance(), null);
decoder.close();
System.out.println("decode success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}


运行结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 安全