我正在尝试加密并解密XOR函数。对于某些输入,大整数正在正确转换为加密文本(密码),并能够解密它。但是对于某些输入,大整数没有转换回加密文本(密码)。我想弄清楚我要去哪里。
示例(密码转换回加密文本)输入:" client1"
加密...
加密: w]密码文本中的二进制文本:11101010101011011010000010001000100110110111101000000010111111111111111111
键用于二进制的键:100010101010111
Xored密码文本二进制:1110101010101101101000100010001001001101101101000001010010001010101010
键用于二进制中的键:10001010101011
在Xoring111011101011101101000100010001001101111111111111111111111中检索二进制中的密码文本
Xoring W] h"ið²
回收的密码文本DenCrypted:Client1
解密文本:客户端1
示例(未转换为加密文本)输入:" client2"
加密... 这是我的代码。 任何帮助将不胜感激。谢谢!!!
加密: 5^é -çz!r
密码文本中的二进制文本:1101010101111111001001001010011111011101110110100010001001010010
键用于二进制的键:100010101010111
Xored密码文本二进制:1101010101111111110010010100111111101110110110100100100100100100111
键用于二进制中的键:10001010101011
在Xoring11010101010111111111111111111111011101101101000100010001010010中检索二进制中的密码文本
Xoring 5^ésçz!import java.math.BigInteger;
import java.security.*;
import javax.crypto.*;
public class MainClass {
private static String algorithm = "DESede";
public static void main(String[] args) throws Exception {
String toEncrypt = "client2";
System.out.println("Encrypting...");
BigInteger encrypted1 = encrypt(toEncrypt, "password");
String decrypted = decrypt(encrypted1, "password");
System.out.println("Decrypted text: " + decrypted);
}
public static BigInteger XOR(String s) throws Exception {
BigInteger message = convertStringToBigInteger(s);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
int seed = 10;
random.setSeed(seed);
byte[] keyStream = new byte[2];
random.nextBytes(keyStream);
BigInteger key = new BigInteger(keyStream);
BigInteger cipherText = message.xor(key);
System.out.println("cipher text in binary: " + message.toString(2));
System.out.println("Key used for XORing in binary: " + key.toString(2));
System.out.println("XORed Cipher text in binary: " + cipherText.toString(2));
return cipherText;
}
public static String InverseXOR(BigInteger s) throws Exception {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
int seed = 10;
random.setSeed(seed);
byte[] keyStream = new byte[2];
random.nextBytes(keyStream); //generate random bytes in put in keyStream
BigInteger key = new BigInteger(keyStream);
BigInteger receivedMessage = s.xor(key);
System.out.println("Key used for Inverse XORing in binary: " + key.toString(2));
System.out.println("retrieved cipher text in binary after xoring" + receivedMessage.toString(2));
String receivedMessageString = convertBigIntegerToString(receivedMessage);
System.out.println("Cipher Text retrieved back by xoring " + receivedMessageString);
return receivedMessageString;
}
private static String convertBigIntegerToString(BigInteger b) {
String s = new String();
while (b.compareTo(BigInteger.ZERO) == 1) {
BigInteger c = new BigInteger("11111111", 2);
int cb = (b.and(c)).intValue();
Character cv = new Character((char) cb);
s = (cv.toString()).concat(s);
b = b.shiftRight(8);
}
return s;
}
private static BigInteger convertStringToBigInteger(String s) {
BigInteger b = new BigInteger("0");
for (int i = 0; i < s.length(); i++) {
Integer code = new Integer((int) s.charAt(i));
BigInteger c = new BigInteger(code.toString());
b = b.shiftLeft(8);
b = b.or(c);
}
return b;
}
public static BigInteger encrypt(String toEncrypt, String key) throws Exception {
SecureRandom sr = new SecureRandom(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, sk);
byte[] encrypted = cipher.doFinal(toEncrypt.getBytes());
String encrypt = new String(encrypted);
System.out.println("Encrypted : " + encrypt);
BigInteger XoredData = XOR(encrypt);
return XoredData;
}
public static String decrypt(BigInteger encrypted1, String key) throws Exception {
String encryptedCipher = InverseXOR(encrypted1);
byte[] encryptedByte = encryptedCipher.getBytes();
SecureRandom sr = new SecureRandom(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
kg.init(sr);
SecretKey sk = kg.generateKey();
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, sk);
byte[] decrypted = cipher.doFinal(encryptedByte);
String decrypt = new String(decrypted);
System.out.println("Dencrypted : " + decrypt);
return decrypt;
}
}
问题1:(可移植性)
请注意,SecureRandom(seed)
并不总是取决于种子。
在提供相同种子时,您得到相同的钥匙几乎100%意味着您在Windows上运行。
您在XOR()
中使用的构造可能更便宜。即。
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(seed);
问题2:(也许是您所看到的)
来自Javadoc的String(byte [] bytes)
:
使用平台的默认字符集来解码指定的字节数组来构造一个新字符串。[...] 当给定字节在默认字符中无效时,该构造函数的行为未指定。
...您正在将其喂食Cipertext,其中可能包含这种无效的字节序列。
您可能需要测试Arrays.equals(new String(encrypted).getBytes(), encrypted)
是否要查看您是否在转换中失去任何内容。如果您绝对必须拥有String
,请查看" Base64编码"。它的目的是将任意字节转换为法律字符编码的目的。
另外,您可能希望将Ciphertext作为字节数组,或者使用BigInteger(byte [])
构造函数初始化BigInteger
。
一个备用措辞:请注意,BigInteger是A 签名 Bigint类,因此toByteArray
方法在必要时可能会预先零,以使差异歧义为具有其MSB集的正值。这需要一些处理,但是可以通过将BigInteger
与BigInteger.ZERO
进行比较来预测。
问题3:(可移植性)
convertStringToBigInteger
中的这一行假定为8位字符。
b.shiftLeft(8);
byte
s在Java中是8位,但是字符可以是8或16位,而且我也不会奇怪地看到更新以允许32位Unicode char
S。
在String#getBytes()
的结果上进行迭代会更安全,或者更好,请跳过转换为字符串,将InterMediates作为字节阵列或BigIntegers
(使用BigInteger#TobyTearray)
次要事物
您可以使用BigInteger.ZERO
代替new BigInteger("0")
如果您缩进您的代码,我们将能够更轻松地阅读您的代码。