密码学中的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](https://my.oschina.net/u/2303379) byteHexString
* [@return](https://my.oschina.net/u/556800)
*/
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();
}
}