自創簡易加密算法

前幾日和同事聊天,說到經常忘記密碼,但記在一些地方,又不放心。我們就想,要是實現一個加密算法,每次記錄加密結果,需要時再解密,那問題不就迎刃而解了嘛。

後來根據需求,設計了一個基於異或的對稱加密算法。算法非常簡單:

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)));
    }

}
本人並不是專業研究安全領域的人,只是有個想法,然後順便實現了一下。所以我也不清楚這個算法的安全性有多高,但至少用着方便,我也能安心記密碼了。(表示連銀行卡的密碼都經常忘,好在現在支付寶都支持指紋了。)

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