文章来源:http://blog.csdn.net/cping1982/article/details/5786759
首先声明,小弟绝对不是标题党。事实上,这是昨天小弟看到的某条新闻后(《100%准确预测涨停股?——新型股票诈骗伎俩揭秘》,原文地址:http://bit.ly/aYC8pd),有感而发杜撰的Java版闲暇之作。
这个小程序的作用非常之简单,也就是向原文中所描述的那样,加密文本文件,而后将内容以“你所需要的方式”展示出来。
下载地址(源码在jar中):http://greenvm.googlecode.com/files/Fraud.jar
主程序如下:
- package org.text.fraud;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- * @author chenpeng
- * @email:ceponline@yahoo.com.cn
- * @version 0.1
- */
- public class Fool {
- // crc32参数表,共有256项
- final static private long[] crcTable = new long[256];
- // 静态初始化参数表
- static {
- long crc;
- int n, k;
- for (n = 0; n < 256; n++) {
- crc = (long) n;
- for (k = 0; k < 8; k++) {
- if ((crc & 1) == 1) {
- crc = 0xEDB88320L ^ (crc >> 1);
- } else {
- crc = crc >> 1;
- }
- }
- crcTable[n] = crc;
- }
- }
- private static final byte[] DIGITS = { '0', '1', '2', '3', '4', '5', '6',
- '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- private static final byte[] FILE_FLAG_ID = { 'W', 'S', 'P', 'Z' };
- private boolean checkCRC = true;
- private byte[] passBytes;
- final static private String EMPTY_CONTEXT = "我是骗子我怕谁?";
- /**
- * 解密byte[]
- *
- * @param array
- * @return
- */
- private byte[] decode(byte[] array) {
- return decode(new String(array).toCharArray());
- }
- /**
- * 解密char[]
- *
- * @param data
- * @return
- */
- private byte[] decode(char[] data) {
- if (passBytes == null) {
- throw new RuntimeException("Password is null");
- }
- // 将16进制字符串转化为原始byte[]
- int len = data.length;
- byte[] out = new byte[len >> 1];
- for (int i = 0, j = 0; j < len; i++) {
- int f = toDigit(data[j]) << 4;
- j++;
- f = f | toDigit(data[j]);
- j++;
- out[i] = (byte) (f & 0xFF);
- }
- // 为了防止向新闻中那样轻易被人试出规律,此示例以password混淆内容
- // 一个password只能解密一种信息。
- int keyindex = passBytes.length;
- int outindex = out.length;
- byte buffer[] = new byte[outindex / 2];
- for (int i = 0; i < outindex; i += 2) {
- int index = (i / 2) % keyindex;
- int k = out[i] - passBytes[index];
- if (k < 0) {
- k = k + 256;
- }
- buffer[i / 2] = (byte) k;
- }
- return buffer;
- }
- /**
- * 将字符转化为指定进制数字
- *
- * @param ch
- * @return
- */
- private static int toDigit(char ch) {
- int digit = Character.digit(ch, 16);
- if (digit == -1) {
- throw new RuntimeException("digit is -1");
- }
- return digit;
- }
- /**
- * 解密byte[]
- *
- * @param data
- * @return
- */
- private byte[] encode(byte[] data) {
- if (passBytes == null) {
- throw new RuntimeException("Password is null");
- }
- // 以password加密byte[]
- int keyindex = passBytes.length;
- int insindex = data.length;
- byte buffer[] = new byte[2 * insindex];
- for (int i = 0; i < insindex; i++) {
- int index = i % keyindex;
- int k = data[i] + passBytes[index];
- int d = (int) (255 * Math.random());
- if (k > 255) {
- k = k - 255;
- }
- buffer[2 * i] = (byte) k;
- buffer[2 * i + 1] = (byte) d;
- }
- // 将加密后信息转化为16进制字符串(想要乱码效果就不用转了……)
- int l = buffer.length;
- byte[] out = new byte[l << 1];
- for (int i = 0, j = 0; i < l; i++) {
- out[j++] = DIGITS[(0xF0 & buffer[i]) >>> 4];
- out[j++] = DIGITS[0x0F & buffer[i]];
- }
- return out;
- }
- /**
- * 加密指定字符串
- *
- * @param string
- * @return
- */
- public final String encrypt(String string) {
- return new String(encode(string.getBytes()));
- }
- /**
- * 解密指定字符串
- *
- * @param string
- * @return
- */
- public final String decrypt(String string) {
- return new String(decode(string.getBytes()));
- }
- /**
- * 以CRC32方式加密指定数据
- *
- * @param buf
- * @param startPos
- * @param endPos
- * @return
- */
- private String CRC32(final byte[] buf, final int startPos, final int endPos) {
- long c = 0xFFFFFFFFL;
- for (int i = startPos; i < endPos; i++) {
- c = (crcTable[(int) ((c ^ buf[i]) & 0xFF)] ^ (c >> 8));
- }
- return String.valueOf(Math.abs((int) (c ^ 0xFFFFFFFFL)));
- }
- public void checkCRC(boolean bool) {
- this.checkCRC = bool;
- }
- /**
- * 为防止如新闻中那样轻易被人试出规律,密码采用CRC校验方式存在。
- *
- * @param pass
- */
- public void makePassword(String pass) {
- if (checkCRC) {
- int size = pass.length();
- byte[] bytes = new byte[size];
- for (int i = 0; i < size; i++) {
- bytes[i] = (byte) pass.charAt(i);
- }
- this.passBytes = CRC32(bytes, 0, size).getBytes();
- } else {
- this.passBytes = pass.getBytes();
- }
- }
- /**
- * 从文件中读取byte[]
- *
- * @param dis
- * @param size
- * @return
- * @throws Exception
- */
- public static byte[] readByteArray(DataInputStream dis, int size)
- throws Exception {
- byte[] readBytes = new byte[size];
- for (int i = 0; i < size; i++) {
- readBytes[i] = dis.readByte();
- }
- return readBytes;
- }
- /**
- * 写入byte[]到文件中
- *
- * @param bytes
- * @param dos
- * @throws Exception
- */
- public static void writeByteArray(byte[] bytes, DataOutputStream dos)
- throws Exception {
- for (int i = 0; i < bytes.length; i++) {
- dos.writeByte(bytes[i] ^ 0x01);
- }
- }
- /**
- * 读取文件数据至byte[]
- *
- * @param dis
- * @return
- */
- private static byte[] read(DataInputStream dis) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- byte[] bytes = new byte[8192];
- try {
- int read;
- while ((read = dis.read(bytes)) >= 0) {
- bos.write(bytes, 0, read);
- }
- bytes = bos.toByteArray();
- } catch (IOException e) {
- return null;
- }
- return bytes;
- }
- /**
- * 读取一个【WSPZ】类型的加密文本文件
- *
- * @param fileName
- * @param password
- * @return
- */
- public String readFile(String fileName, String password) {
- String context = null;
- InputStream in = null;
- DataInputStream dis = null;
- try {
- File file = new File(fileName);
- in = new FileInputStream(file);
- dis = new DataInputStream(in);
- if (!verify(dis, password)) {
- throw new RuntimeException("Password error");
- }
- byte[] bytes = read(dis);
- context = new String(decode(bytes));
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (dis != null) {
- dis.close();
- dis = null;
- }
- } catch (Exception e) {
- }
- }
- return context;
- }
- /**
- * 读取一个【WSPZ】类型的加密文本信息
- *
- * @param context
- * @param password
- * @return
- */
- public String readContext(String context, String password) {
- String text = null;
- ByteArrayInputStream bis = null;
- DataInputStream dis = null;
- try {
- bis = new ByteArrayInputStream(context.getBytes());
- dis = new DataInputStream(bis);
- if (!verify(dis, password)) {
- throw new RuntimeException("Password error");
- }
- byte[] bytes = read(dis);
- text = new String(decode(bytes));
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- if (dis != null) {
- dis.close();
- dis = null;
- }
- } catch (Exception e) {
- }
- }
- return text;
- }
- /**
- * 验证指定【WSPZ】类型数据的密码是否正确
- *
- * @param context
- * @param password
- * @return
- */
- public boolean verifyContext(String context, String password) {
- ByteArrayInputStream bis = null;
- try {
- bis = new ByteArrayInputStream(context.getBytes());
- DataInputStream dis = new DataInputStream(bis);
- readByteArray(dis, 4);
- makePassword(password);
- byte[] crc = readByteArray(dis, passBytes.length);
- if (checkCRC) {
- if (new String(crc).equals(CRC32(password.getBytes(), 0,
- password.length()))) {
- return true;
- }
- } else {
- if (new String(crc).equals(password)) {
- return true;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- bis.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return false;
- }
- /**
- * 验证指定文件的密码是否正确
- *
- * @param fileName
- * @param password
- * @return
- */
- public boolean verify(DataInputStream dis, String password) {
- try {
- readByteArray(dis, 4);
- makePassword(password);
- byte[] crc = readByteArray(dis, passBytes.length);
- if (checkCRC) {
- if (new String(crc).equals(CRC32(password.getBytes(), 0,
- password.length()))) {
- return true;
- }
- } else {
- if (new String(crc).equals(password)) {
- return true;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
- /**
- * 验证指定文件的密码是否正确
- *
- * @param fileName
- * @param password
- * @return
- */
- public boolean verify(String fileName, String password) {
- try {
- File file = new File(fileName);
- FileInputStream fis = new FileInputStream(file);
- DataInputStream dis = new DataInputStream(fis);
- return verify(dis, password);
- } catch (FileNotFoundException e) {
- }
- return false;
- }
- /**
- * 构建一个【WSPZ】类型的加密文本文件
- *
- * @param fileName
- * @param password
- * @param context
- */
- public void makeFile(String fileName, String password, String context) {
- // 构建密码
- makePassword(password);
- String text = encrypt(context);
- FileOutputStream os = null;
- DataOutputStream dos = null;
- try {
- File file = new File(fileName);
- os = new FileOutputStream(file);
- dos = new DataOutputStream(os);
- dos.write(FILE_FLAG_ID);
- dos.write(passBytes);
- dos.write(text.getBytes());
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (dos != null) {
- try {
- dos.close();
- dos = null;
- } catch (IOException e) {
- }
- }
- }
- }
- /**
- * 获得CRC32化的密码信息
- *
- * @return
- */
- public String getPassCRC32() {
- return new String(passBytes);
- }
- /**
- * 构建一个(骗人)的信息文件
- *
- * @param fileName
- * @param password
- */
- public static void makeFoolFile(String fileName, String password) {
- Fool fool = new Fool();
- fool.makeFile(fileName, password, EMPTY_CONTEXT);
- }
- }
具体操作如下图所示:
1、生成一个“涨价股”信息(当然,里面写什么都无所谓)
2、生成的文本信息如下(我将其转为16进制保存)
3、这是一个“正版”的“解密锁”没有的功能,那就是在仅仅输入密码时,会将加密的文本文件真正解密出来。
4、如果输入为“需要解密的内容”(也就是密码和加密文档的混合体),则会按照输入的内容输出(嗯,也就是学骗子那样,输入什么就显示什么)。
5、说起来这个小应用比“正版”稍稍“顽强”一些,那就是当输入的密码信息,与压缩文件里包含的密码不相同时,系统不会“解密文件”(至少不会像新闻里那样,被随便拼凑的信息能混过关了……)。
下载地址(源码在jar中):http://greenvm.googlecode.com/files/Fraud.jar
严格意义上讲,小弟从来不愿意将这类低级犯罪归结到智能犯罪中,因为这种骗局实在太过肤浅。任凭文章中分析了多少,其实也就是做个加密的文件糊弄事,然后把第二天实际的涨停股“解密”到文件中的小把戏罢了。别的因素且不说,换个稍微有点计算机常识的人遇到这种事,至少也会想想,对方难道不可以用7z或rar这种现成的工具压缩文件吗?如果有20位或以上的密码,就算是CIA级别的机构也未必能在一天内破解出真实内容来,更别说普通人,根本就用不着自己写个解密器嘛(况且它那个解密器要是新出炉的木马,一双击不就杯具了……)。