• 150608

    文章

  • 1145

    评论

  • 13

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

开发宝藏收集之(字符串混淆代码)


本周接到了一个任务,要求做个通讯加密.这本是个非常easy的事.使用现成的AES加密就行了,这当然不是今天的重点.重点是我们需要把双方都使用的秘钥加密~其实就是一个key
比如:

final static String keyword = "这是一千万的老干妈";

但是有个不爽的事.java代码是可以反编译的.
别人一眼就能看到你的秘钥明文.
这是非常low的.
所以我又想了一下.
干脆写的复杂点?
比如这样?




 final static String keyword = new String(new byte[]{
       1,2,3>>3,2<<3,16%4,55/3,16/2/4,34|22&43     
    });

关键是这样写出来我也不认识.而且别人拿出来随便放哪跑一下就行了.达不到混淆的目的.
后天终于找到一款非常好用的工具类.

ObfuscatedString

属于 trueLicense的一个包下的工具类
里面有一些引用会报错,我处理了一下,把代码粘上来


import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 *
 * This class is designed to be thread safe.
 *
 * @author jie.huang
 * @date 2020/7/3
 **/
public class ObfuscatStringUtil {

    private static final String UTF8
            = new String(new char[] { '\u0055', '\u0054', '\u0046', '\u0038' }); // => "UTF8"

	public static void main(String[] args) {
       String key = "这是一瓶老干妈";
        String obfuscateKey = obfuscate(key);
        System.out.println(obfuscateKey);
        ObfuscatStringUtil obfuscatedString = new ObfuscatStringUtil(new long[]{0xA811885BF815CA4FL, 0x3D5A0E8D21857F32L, 0x8710FB7F6FEF0209L, 0x44CE22BFA09D7BF9L});
        System.out.println(obfuscatedString.toString());
    }
    public static String obfuscate(final String s) {
        // Any string literal used in this method is represented as an
        // ObfuscatedString unless it's no longer than two characters.
        // This should help to prevent location of this class in the obfuscated
        // code generated by ProGuard.

        if (-1 != s.indexOf(0)) {
            throw new IllegalArgumentException(new ObfuscatStringUtil(new long[] {
                    0x241005931110FC70L, 0xDCD925A88EAD9F37L, 0x19ADA1C861E2A85DL,
                    0x9A5948E700FCAD8AL, 0x2E11C83A72441DE2L
            }).toString()); // => "Null characters are not allowed!";
        }

        // Obtain the string as a sequence of UTF-8 encoded bytes.
        final byte[] encoded;
        try {
            encoded = s.getBytes(UTF8);
        } catch (UnsupportedEncodingException ex) {
            throw new AssertionError(ex); // UTF8 is always supported
        }

        // Create and seed a Pseudo Random Number Generator (PRNG) with a
        // random long number.
        final Random prng = new Random(); // randomly seeded
        final long seed = prng.nextLong(); // seed strength is effectively 48 bits
        prng.setSeed(seed);

        // Construct a StringBuffer to hold the generated code and append the
        // seed as the first element of the encoded array of longs.
        // The value is represented in hexadecimal in order to keep the string
        // representation as short as possible.
        final StringBuffer code = new StringBuffer(new ObfuscatStringUtil(new long[] {
                0xA28E32BB0D3E394EL, 0xF842D1C94E549EECL, 0x7D07DFF01F907E4L,
                0x4E0BDE791ECD467CL, 0xDFF389B58DA3E44FL, 0x2477FAED0CE62C79L
        }).toString()); // => "new ObfuscatedString(new long[] {";
        appendHexLiteral(code, seed);

        final int length = encoded.length;
        for (int i = 0; i < length; i += 8) {
            final long key = prng.nextLong();
            // Compute the value of the next array element as an obfuscated
            // version of the next eight bytes of the UTF8 encoded string.
            final long obfuscated = toLong(encoded, i) ^ key;

            code.append(", ");
            appendHexLiteral(code, obfuscated);
        }

        code.append(new ObfuscatStringUtil(new long[] {
                0x4200B7AD6FFFF546L, 0x9B822E95FE73769DL, 0x23C2800C6CACFCE3L,
                0x21C30B492D9AEF99L
        }).toString()); // => "}).toString() /* => \"";

        // Append the original string to the generated code comment,
        // properly escaping quotation marks and backslashes.
        code.append(
                s.replaceAll("\\\\", new ObfuscatStringUtil(new long[] {
                        0x6D2C680D49523A01L, 0xB932F1DBD19E82CEL}).toString() /* => "\\\\\\\\" */)
                        .replaceAll("\"", new ObfuscatStringUtil(new long[] {
                                0x85E9D53EF7A9324BL, 0xB05BD65C9F19DE07L}).toString() /* => "\\\\\"" */));

        code.append(new ObfuscatStringUtil(new long[] {
                0xC54FFF0621E7D107L, 0x194EAD468C6FCF93L
        }).toString()); // => "\" */"

        return code.toString();
    }

    private static void appendHexLiteral(final StringBuffer sb, final long l) {
        sb.append('0'); // obfuscation futile - too short
        sb.append('x'); // dito
        sb.append(Long.toHexString(l).toUpperCase());
        sb.append('L'); // dito
    }

    /**
     * @param bytes The array containing the bytes to decode in little endian
     *        order.
     * @param off The offset of the bytes in the array.
     *
     * @return The decoded long value.
     */
    private static long toLong(final byte[] bytes, int off) {
        final int end = Math.min(bytes.length, off + 8);
        long l = 0;
        for (int i = end; --i >= off; ) {
            l <<= 8;
            l |= bytes[i] & 0xFF;
        }
        return l;
    }

    /**
     * @param l The long value to encode.
     * @param bytes The array which holds the encoded bytes upon return.
     * @param off The offset of the bytes in the array.
     */
    private static void toBytes(long l, byte[] bytes, int off) {
        final int end = Math.min(bytes.length, off + 8);
        for (int i = off; i < end; i++) {
            bytes[i] = (byte) l;
            l >>= 8;
        }
    }

    /** The obfuscated string. */
    private final long[] obfuscated;

    /**
     * Constructs an obfuscated string.
     *
     * @param obfuscated The obfuscated string.
     * @throws NullPointerException If {@code obfuscated} is
     *         {@code null}.
     * @throws ArrayIndexOutOfBoundsException If the provided array does not
     *         contain at least one element.
     */
    public ObfuscatStringUtil(final long[] obfuscated) {
        this.obfuscated = (long[]) obfuscated.clone();
        this.obfuscated[0] = obfuscated[0];
    }

    /** Returns the original string. */
    @Override
    public String toString() {
        final int length = obfuscated.length;

        // The original UTF8 encoded string was probably not a multiple
        // of eight bytes long and is thus actually shorter than this array.
        final byte[] encoded = new byte[8 * (length - 1)];

        // Obtain the seed and initialize a new PRNG with it.
        final long seed = obfuscated[0];
        final Random prng = new Random(seed);

        // De-obfuscate.
        for (int i = 1; i < length; i++) {
            final long key = prng.nextLong();
            toBytes(obfuscated[i] ^ key, encoded, 8 * (i - 1));
        }

        final String decoded;
        try {
            decoded = new String(encoded, UTF8);
        } catch (UnsupportedEncodingException ex) {
            throw new AssertionError(ex); // UTF-8 is always supported
        }
        final int i = decoded.indexOf(0);
        return -1 == i ? decoded : decoded.substring(0, i);
    }
}

来.看一下运行结果.

new ObfuscatedString(new long[] {0xE790EF86B04039E7L, 0xE7AB8031CA252A78L, 0x1C8A0DFAD2C1626BL, 0x20DADE37CB46F303L}).toString() /* => "这是一瓶老干妈" */
这是一瓶老干妈

如果你仔细看就回发现

new ObfuscatedString(new long[] {0xE790EF86B04039E7L, 0xE7AB8031CA252A78L, 0x1C8A0DFAD2C1626BL, 0x20DADE37CB46F303L});
new ObfuscatStringUtil(new long[]{0xA811885BF815CA4FL, 0x3D5A0E8D21857F32L, 0x8710FB7F6FEF0209L, 0x44CE22BFA09D7BF9L});

这两行代码都表示

这是一瓶老干妈

实际上你每次运行混淆代码得出来的结果都不一样.

这样别人在反编译你代码的时候只能调试才能知道这个字符串是什么,是不是很happy?

需要完整代码的可以留言~


695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

1条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤 主体内容背景
打开支付宝扫码付款购买视频教程
遇到问题联系客服QQ:419400980
注册梁钟霖个人博客