自创简易加密算法

前几日和同事聊天,说到经常忘记密码,但记在一些地方,又不放心。我们就想,要是实现一个加密算法,每次记录加密结果,需要时再解密,那问题不就迎刃而解了嘛。

后来根据需求,设计了一个基于异或的对称加密算法。算法非常简单:

1.先定义一个由一系列不规则字符组成的盐值(SALT),然后生成一个密钥,密钥是一个整数数组,里面的值随机生成,对应盐值字符串的下标。

2.加密时,根据密钥与盐值生成一个用来加密的字节数组。

3.通过这个字节数组,与被加密数据的字节数组进行异或操作

4.返回加密结果,由于异或的特性,解密过程同加密过程。


后来经过一些修改,将加密的字节数组转换为对应的16进制字符串(4位二进制表示一位16进制,根据这个规律生成)。这样就能将任何数据加密为一串字符串,解密时,先将这串字符串转换为对应的字节数组,再进行解密还原。


老规矩,上王者(呸,代码 最近有些沉迷游戏):

package com.myself.tryit;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * Created with IntelliJ IDEA
 * Date: 2017/12/8
 * Time: 上午11:04
 *
 * @author 陈樟杰
 */
public class EncryptDecrypt {
    /**
     * 盐值
     */
    private static final String SALT = "dfsad@#%$@TDGDF%$#%@#%WFRGFDHJKcvxznmfdsgdfgs2432534fgdf46t";
    /**
     * 内部密钥
     */
    private static final int[] KEY = {
            23, 22, 24, 4, 51, 26, 37, 27, 24, 6, 26, 38, 29, 35, 18, 21, 14, 3, 12, 4, 41, 39, 18, 44, 54, 21, 33, 35, 31, 22, 34, 53, 51, 44, 8, 12, 3, 0, 28, 1, 48, 9, 51, 57, 20, 44, 27, 3, 16, 48
    };

    /**
     * 16进制映射表
     */
    private static final Map MMP = new HashMap(12);

    static {
        short i = 10;
        for (; i < 16; i++) {
            MMP.put(i, (char) ('A' + i - 10));
            MMP.put((char) ('A' + i - 10), i);
        }
    }

    /**
     * 生成密钥
     *
     * @param len 密钥长度
     * @return
     */
    public static int[] generateKey(int len) {
        int ceiling = SALT.length();
        int[] key = new int[len];
        for (int i = 0; i < len; i++) {
            key[i] = (int) (Math.random() * ceiling);
        }
        return key;
    }

    /**
     * 加密
     *
     * @param original
     * @return
     */
    public static byte[] encrypt(byte[] original) {
        byte[] keyByte = new byte[KEY.length];
        /**
         * 获取加密字节数组
         */
        for (int i = 0; i < KEY.length; i++) {
            keyByte[i] = (byte) SALT.charAt(KEY[i]);
        }
        /**
         * 加密
         */
        int k = 0;
        byte[] encryptByte = new byte[original.length];
        for (int i = 0; i < original.length; i++) {
            encryptByte[i] = (byte) (original[i] ^ keyByte[k++ % keyByte.length]);
        }

        return encryptByte;
    }

    /**
     * 解密
     *
     * @param original
     * @return
     */
    public static byte[] decrypt(byte[] original) {
        return encrypt(original);
    }

    /**
     * 对字符串加密
     * 由于解码时 byte数组不一定符合规范 所以解码算法可能会改变字节数组的值 所以只能返回字节数组 而不能返回字符串
     *
     * @param original
     * @return
     */
    public static byte[] encryptString(String original) {
        return encrypt(original.getBytes());
    }

    /**
     * 对字符串解密
     *
     * @param original
     * @return
     */
    public static String decryptToString(byte[] original) {
        return new String(encrypt(original));
    }

    /**
     * 加密成16进制字符串
     *
     * @param original
     * @return
     */
    public static String encryptToHex(byte[] original) {
        //先加密
        byte[] bytes = encrypt(original);
        /**
         * 将加密的字节数组转换成16进制字符串
         */
        StringBuffer stringBuffer = new StringBuffer("");
        for (int i = 0; i < bytes.length; i++) {
            short a = (short) (bytes[i] & 15);
            short b = (short) ((bytes[i] & (15 << 4)) >>> 4);
            if (b < 10) {
                stringBuffer.append(b);
            } else {
                stringBuffer.append(MMP.get(b));
            }

            if (a < 10) {
                stringBuffer.append(a);
            } else {
                stringBuffer.append(MMP.get(a));
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 从16进制字符串解密
     *
     * @param original
     * @return
     */
    public static byte[] decryptFromHex(String original) {
        /**
         * 将16进制字符串转换成字节数组
         */
        byte[] bytes = new byte[original.length() / 2];
        int len = 0;
        for (int i = 0; i < original.length(); i += 2) {
            short a, b;
            if (original.charAt(i) >= '0' && original.charAt(i) <= '9') {
                a = (short) (original.charAt(i) - '0');
                a <<= 4;
            } else {
                a = (short) MMP.get(original.charAt(i));
                a <<= 4;
            }

            if (original.charAt(i + 1) >= '0' && original.charAt(i + 1) <= '9') {
                b = (short) (original.charAt(i + 1) - '0');
            } else {
                b = (short) MMP.get(original.charAt(i + 1));
            }
            bytes[len++] = (byte) (a + b);
        }
        //解密字节数组
        return decrypt(bytes);
    }

    /**
     * 将字符串加密成16进制字符串
     *
     * @param original
     * @return
     */
    public static String encryptStringToHex(String original) {
        return encryptToHex(original.getBytes());
    }

    /**
     * 从16进制字符串解密成原字符串
     *
     * @param original
     * @return
     */
    public static String decryptStringFromHex(String original) {
        return new String(decryptFromHex(original));
    }


    /**
     * 加密
     */
    private void doEncrypt() {
        System.err.println("-------------加密-------------");
        Scanner scanner = new Scanner(System.in);
        String original = scanner.next();

        System.out.println(encryptStringToHex(original));
    }

    /**
     * 解密
     */
    private void doDecrypt() {
        System.err.println("-------------解密-------------");
        Scanner scanner = new Scanner(System.in);
        String original = scanner.next();

        System.out.println(decryptStringFromHex(original));
    }

    public static void main(String[] args) {
        //加密
        new EncryptDecrypt().doEncrypt();
        //解密
//        new EncryptDecrypt().doDecrypt();
    }

    @Test
    public void test() {
        int[] keys = generateKey(SALT.length());
        for (int k : keys) {
            System.out.print(k+", ");
        }
        System.out.println();

        String original = "穷且益坚,不坠青云之志。";

        String encrypt = encryptStringToHex(original);
        System.out.println(encrypt);
        System.out.println(decryptStringFromHex(encrypt));

        encrypt = encryptToHex(original.getBytes());
        System.out.println(encrypt);
        System.out.println(new String(decryptFromHex(encrypt)));


        original = "人生得意须尽欢,莫使金樽空对月。";

        byte[] bytes = encryptString(original);
        System.out.println(new String(bytes));
        System.out.println(decryptToString(bytes));


        bytes = encrypt(original.getBytes());
        System.out.println(new String(bytes));
        System.out.println(new String(decrypt(bytes)));
    }

}
本人并不是专业研究安全领域的人,只是有个想法,然后顺便实现了一下。所以我也不清楚这个算法的安全性有多高,但至少用着方便,我也能安心记密码了。(表示连银行卡的密码都经常忘,好在现在支付宝都支持指纹了。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章