大整数未在Java中预期转换为字符串



我正在尝试加密并解密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集的正值。这需要一些处理,但是可以通过将BigIntegerBigInteger.ZERO进行比较来预测。

问题3:(可移植性)

convertStringToBigInteger中的这一行假定为8位字符

b.shiftLeft(8);

byte s在Java中是8位,但是字符可以是8或16位,而且我也不会奇怪地看到更新以允许32位Unicode charS。

String#getBytes()的结果上进行迭代会更安全,或者更好,请跳过转换为字符串,将InterMediates作为字节阵列或BigIntegers(使用BigInteger#TobyTearray)

次要事物

您可以使用BigInteger.ZERO代替new BigInteger("0")

如果您缩进您的代码,我们将能够更轻松地阅读您的代码。

最新更新