密码学中的XOR

414 阅读4分钟

密码学中的XOR

  • 异或运算
  • 加密实现原理
  • 运用场景
  • java代码实现

异或运算

在计算机里有几种位运算,像或| 与& ,异或 ^
异或^例子:
0 ^ 1 = 1;  
1 ^ 1 = 0;  
0 ^ 0 = 0; 
1 ^ 0 = 1;
或|例子:
0 | 1 = 1;
1 | 1 = 1;
0 | 0 = 0;
1 | 0 = 1;
与&例子:
0 & 1 = 0;
1 & 1 = 1;
0 & 0 = 0;
1 & 0 = 0;

加密解密实现原理

A ^ B = C; ==> 1111 0001 ^ 1010 1001 = 0101 1000
B ^ C = A; ==> 1010 1001 ^ 0101 1000 = 1111 0001
此时我们可以将B当为密钥,A为需要加密的明文,C为加密后的密文

运用场景

XOR的加密的安全性是非常高的,但是在实际运用中却不会选择XOR进行加解密,因为当一个明文使用XOR进行加密后再发送给使用方时同时也需要把加密用的key发送给使用方,但key是明文,所以还不如直接发送明文给使用方。 但是在一些应用场景也会选择使用XOR进行加密,比如不需要传递key给第三方,在程序内部使用,比如配置文件中将数据库的密码使用XOR进行加密,然后再代码中使用特定的key进行解密,从而达到再配置文件中看不到明文的目的。

JAVA实现

package org.dewice.encrypt;

/**
 * 利用异或来进行加解密
 */
public class XOREncrypt {
    //既是加密的key,也是解密的key
    private final static byte[] xorkey = "todayisaniceday".getBytes();

    //用作将byte转成16进制
    private final static String hexString = "0123456789ABCDEF";

    private static XOREncrypt xorEncrypt;

    private XOREncrypt() {

    }

    public static XOREncrypt getInstance() {
        if (xorEncrypt == null) {
            xorEncrypt = new XOREncrypt();
        }
        return xorEncrypt;
    }

    public String encrypt(String encryptStr) {
        if (encryptStr != null && encryptStr.length() > 0) {
            return encrypt(encryptStr.getBytes());
        } else {
            throw new IllegalArgumentException("encryptStr is null");
        }
    }

    public String decrypt(String decrypthexString) {
        if (hexString != null && hexString.length() > 0) {
            byte[] byteArray = hexStringToByteArray(decrypthexString);
            return decrypt(byteArray);
        } else {
            throw new IllegalArgumentException("hexString is null");
        }
    }

    private String decrypt(byte[] bytes) {
        byte[] decryptXor = xor(bytes);
        return new String(decryptXor);
    }

    /**
     *  将1C0A080D161E1C130A字符串转成byte[]
     *
     * @param byteHexString
     * @return
     */
    private byte[] hexStringToByteArray(String byteHexString) {
        byte[] byteArray = null;
        if (byteHexString != null) {
            if (byteHexString.length() % 2 != 0) {
                throw new IllegalArgumentException();
            }
            byteArray = new byte[byteHexString.length() / 2];

            int hexStringPosition = 0;
            for (int byteArrayPosition = 0; hexStringPosition < byteHexString.length(); byteArrayPosition++) {
                //1C 转成byte highOrder = 1 lowOrder = C
                //0000 0000 0000 0000 0000 0000 0000 0001 ==> 1
                //0000 0000 0000 0000 0000 0000 0000 ‭1100‬ ==> C
                // 1 << 4 ==> 0000 0000 0000 0000 0000 0000 0001 0000
                int highOrder = XOREncrypt.hexString.indexOf(byteHexString.charAt(hexStringPosition)) << 4;
                int lowOrder = XOREncrypt.hexString.indexOf(byteHexString.charAt(hexStringPosition + 1));
                // 0000 0000 0000 0000 0000 0000 0001 0000 | 0000 0000 0000 0000 0000 0000 0000 ‭1100
                // 0000 0000 0000 0000 0000 0000 0001 ‭1100
                int finalByte = lowOrder | highOrder;

                byteArray[byteArrayPosition] = new Integer(finalByte).byteValue();
                hexStringPosition += 2;
            }
        } else {
            byteArray = new byte[0];
        }
        return byteArray;
    }

    private byte[] xor(byte[] bytes) {
        int keyindex = 0;
        byte[] xorbytes = new byte[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            xorbytes[i] = (byte) (bytes[i] ^ xorkey[keyindex]);
            //当 keyindex 与bytes的长度相同时,将从key的第一位开始
            if (++keyindex == bytes.length) {
                keyindex = 0;
            }
        }
        return xorbytes;
    }

    private String encrypt(byte[] bytes) {
        byte[] xorbytes = xor(bytes);
        // 将异或后的bytes结果进行Hex
        return bytesArrayToHexString(xorbytes);
    }


    private String bytesArrayToHexString(byte[] toStringBytes) {
        return bytesArrayToHexString(toStringBytes, 0, toStringBytes.length);
    }


    //二进制输出
    private String bytesArrayToHexString(byte[] b, int offset, int len) {
        if (b == null) {
            return null;
        }
        StringBuffer buff = new StringBuffer();
        int maxLen = b.length - offset;
        if (len > maxLen) {
            len = b.length - offset;
        }
        for (int i = offset; i < len; i++) {
            //byte只有8位,转int时位32位的,将byte转成int,此时需要补齐前面的24位为1
            //例如一个byte为1111 0111的需要转成int,此时需要将前24位转成0
            //就有了& 0xFF
            // 1111 1111 1111 1111 1111 1111 1111 0111 & 0000 0000 0000 0000 0000 0000 1111 1111
            // 0000 0000 0000 0000 0000 0000 1111 0111
            int j = b[i] & 0xFF;
            // 取1111的字符
            char first = XOREncrypt.hexString.charAt(j / 16);
            // 取0111的字符
            char second = XOREncrypt.hexString.charAt(j % 16);
            buff.append(first);
            buff.append(second);
        }
        return buff.toString();
    }

}