在java

时间:2017-12-03 18:28:54

标签: java cryptography tostring biginteger

我正在尝试加密和解密包括XOR功能。对于某些输入集,Big Integer正在被正确转换为加密文本(密码)并且能够解密它。但是对于某些输入集,Big Integer不会转换回加密文本(密码)。我想知道我哪里出错了。

示例(密码转换回加密文本)输入:“client1”

加密...
加密: w] h“iÐÿ
二进制密文:111011101011101011010000010001001101001110100000001011111111111
用于二进制异或的密钥:100010111010101
二进制的XORed Cipher文本:111011101011101011010000010001001101001110100000101001000101010
用于二进制逆XOR的键:100010111010101
在xoring111011101011101011010000010001001101001110100000001011111111111之后检索到的二进制密文 通过xoring w] h“iÐÿ来检索密文 不加密:client1
解密文本:client1

示例(未转换为加密文本)输入:“client2”

加密...
加密: 5 ^ÉœÇZ!R
二进制密文:11010101011110110010010101001111000111010110100010000101010010
用于二进制异或的密钥:100010111010101
XORed Cipher二进制文本:11010101011110110010010101001111000111010110100110010010000111
用于二进制逆XOR的键:100010111010101
xoring11010101011110110010010101001111000111010110100010000101010010后检索到的二进制密文 xoring 5 ^ÉSÇZ!R

回收密文

这是我的代码。

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 个答案:

答案 0 :(得分:1)

问题1:(可移植性)

请注意,SecureRandom(seed)并不总是取决于种子 在提供相同的种子时,你获得相同密钥的事实几乎100%意味着你在Windows上运行它。

您在XOR()中使用的构造可能更具可移植性。即。

SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 
random.setSeed(seed);

问题2:(也许是您所看到的来源)

来自String(byte [] bytes)的Javadoc:

  

使用平台的默认字符集解码指定的字节数组,构造一个新的String。 [...]   当指定的字节在默认字符集中无效时,此构造函数的行为未指定。

...并且你正在为它提供cipertext,它可能包含这样的无效字节序列。

您可能想要测试Arrays.equals(new String(encrypted).getBytes(), encrypted)是否在转换中丢失任何内容。如果您必须将其设为String,请查看“base64编码”。它的设计完全是为了将任意字节转换为合法的字符编码。

或者,您可能希望将密文保留为字节数组,或者使用BigInteger构造函数初始化BigInteger(byte [])

一个谨慎的注意事项:请注意,BigInteger是一个签名的 bigint类,因此toByteArray方法可以在必要时添加前导零,以消除其MSb集合的正值的歧义。这需要一些处理,但可以通过将BigIntegerBigInteger.ZERO进行比较来预测。

问题3:(可移植性)

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

b.shiftLeft(8);

byte在Java中是8位,但字符可以是8位或16位,我也不会惊讶地看到更新允许32位unicode char

迭代String#getBytes()的结果会更安全......或者更好的是,跳过转换为字符串,并将中间词保留为字节数组,或BigIntegers(使用BigInteger#toByteArray )

次要事情

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

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