AES encryption and decryption int array-Java C++ implementation

Problem Description

encryption

Input : original int array, such as [1,2,3,4]
Output : encrypted int array, such as [2323,323,333,555]

graph LR
1,2,3,4-->2323,323,333,555

Decrypt

Input : the encrypted int array, such as [2323,323,333,555]
Output : the decrypted int array, such as [1,2,3,4]

graph LR
2323,323,333,555-->1,2,3,4

Some solutions

  • RSA algorithm encrypts and decrypts each number in the array
  • AES first converts each number into a string, and then encrypts and decrypts it. This method does not work, because the encrypted string cannot be converted into a digital representation.

AES solution

    The java code is that jdk uses its own library, which automatically generates the key, and then we save it in the file; the encryption library used by C++ is crypt, a very powerful encryption library, and the array should be replaced by a vector container.

Step 1 int转byte

    An int corresponds to 4 bytes, the java conversion code is as follows:

public static byte[] int2byte(int res) {
        byte[] targets = new byte[4];
        targets[0] = (byte) (res & 0xff);
        targets[1] = (byte) ((res >> 8) & 0xff);
        targets[2] = (byte) ((res >> 16) & 0xff);
        targets[3] = (byte) (res >>> 24);
        return targets;
    }

    The C++ conversion code is as follows:

byte*  EncryptAES::int2byte(int res) {
	byte *targets = new byte[4];
	targets[0] = (byte)(res & 0xff);
	targets[1] = (byte)((res >> 8) & 0xff);
	targets[2] = (byte)((res >> 16) & 0xff);
	targets[3] = (byte)((int)((unsigned)res >> 24));
	return targets;
}

Step 2 byte转int

    4 bytes correspond to 1 Int, the conversion code is as follows:

 public static int byte2int(byte[] res) {
        int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00)
                | ((res[2] << 24) >>> 8) | (res[3] << 24);
        return targets;
    }

    The C++ conversion code is as follows:

nt EncryptAES::byte2int(vector<byte> res) {
	int targets = (res[0] & 0xff) | ((res[1] << 8) & 0xff00)
				  | (int)((unsigned)(res[2] << 24) >> 8) | (res[3] << 24);
	return targets;
}

Step 3 Conversion between byte array and int array

    Convert int array to byte array, java conversion code is as follows:

 public static byte[] ints2byte(int res[]) {
        byte[] a = new byte[res.length * 4];   //预分配4*int数组的大小
        for (int i = 0; i < res.length; i++) {
            byte temp[] = int2byte(res[i]);
            System.arraycopy(temp, 0, a, i * 4, 4);
        }
        return a;
    }

    The C++ conversion code is as follows:

void EncryptAES::ints2byte(vector<int> res, vector<byte> &a) {
	for (int i = 0; i < res.size(); i++) {
		byte* temp = EncryptAES::int2byte(res[i]);
		for (int j = 0;j < 4;j++) {
			a.push_back(temp[j]);
		}
	

    Convert byte array to int array, java conversion code is as follows:

  public static int[] byte2ints(byte[] res) {
        byte[] byte_3 = null;
        byte_3 = new byte[res.length];
        System.arraycopy(res, 0, byte_3, 0, res.length);
        int[] result = new int[byte_3.length / 4];  //预分配byte数组的大小
        for (int i = 0; i < byte_3.length; i = i + 4) {
            byte b[] = new byte[4];
            System.arraycopy(byte_3, i, b, 0, 4);
            result[i / 4] = byte2int(b);
        }
        return result;
    }

    The C++ conversion code is as follows:

void EncryptAES::byte2ints(vector<byte> res, vector<int> &results) {
	vector<byte> c;
	for (int i = 0; i < res.size(); i = i + 4) {
		c.clear();
		for (int j = 0;j < 4;j++) {
			c.push_back(res[i + j]);
		}
		results.push_back(byte2int(c));
	}
}

Step 4 The last step to encrypt and decrypt the byte array

Here we have to consider the choice of AES mode. If an int array has only one int, it is equivalent to only 4 bytes for a long time, which does not meet the 16-byte length of aes. We hope that the length of the encrypted sum is the same as the one before the encryption The length is the same, then the number of int after encryption is the same as the number of int before encryption, so we choose AES/OFB/NoPadding mode. As for all the modes of aes as shown below:

aes all modes

    The java encryption and decryption code is as follows:

public static int[] encrypt(int input[]) {
        encrypt(ints2byte(input));
        return byte2ints(result);
    }

    public static int[] decrypt(int input[], String str) {
        byte[] a = new byte[input.length * 4];
        byte[] res = ints2byte(input);
        System.arraycopy(res, 0, a, 0, res.length);
        decrypt(a, str);
        return byte2ints(result);
    }

    public static String getSecretKey() throws IOException {
        File file = new File("key");
        byte[] key = new byte[(int) file.length()];
        FileInputStream fis = new FileInputStream(file);
        fis.read(key);
        String str = new String(key, "ISO-8859-1");
        return str;
    }

    public static void encrypt(byte[] bobo) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(128);
            SecretKey secretKey = keyGenerator.generateKey();
            IvParameterSpec paramSpec = new IvParameterSpec(AES_IV);
            byte[] enCodeFormat = secretKey.getEncoded();
            SecretKeySpec aesKey = new SecretKeySpec(enCodeFormat, "AES");
            File file = new File("key");
            OutputStream outputStream = new FileOutputStream(file);
            outputStream.write(enCodeFormat);
            outputStream.flush();
            outputStream.close();
            Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, aesKey, paramSpec);
            result = cipher.doFinal(bobo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void decrypt(byte[] bobo, String str) {
        try {
            byte[] key = str.getBytes("ISO-8859-1");
            SecretKeySpec aesKey = new SecretKeySpec(key, "AES");
            IvParameterSpec paramSpec = new IvParameterSpec(AES_IV);

            Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, aesKey, paramSpec);
            result = cipher.doFinal(bobo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    The C++ encryption and decryption code is as follows:

void EncryptAES::encrypt(vector<int> input, vector<int> &res) {
	vector<byte> temp;
	ints2byte(input, temp);
	AesEncrypt(temp);
	byte2ints(result, res);
}

void EncryptAES::decrypt(vector<int> input, string str, vector<int> &res2) {
	vector<byte> a;
	vector<byte> res;
	ints2byte(input, res);
	for (int i = 0;i < res.size();i++)
		a.push_back(res[i]);
	AesDecrypt(a, str);
	byte2ints(result, res2);
}
string EncryptAES::getSecretKey(string Path) {
	ifstream infile;
	infile.open(Path.c_str(), ios::binary);
	if (!infile)
	{
		return "没有秘钥文件";
	}
	infile.seekg(0, ios::end);
	unsigned long len = infile.tellg();
	byte* buffer = new byte[len];
	infile.seekg(0, ios::beg);
	infile.read((char*)buffer, len);
	infile.close();

	string encoded;
	encoded.clear();
	StringSource(buffer, len, true,
				 new HexEncoder(
						 new StringSink(encoded)
				 ) // HexEncoder
	); // StringSource
	delete[](buffer);
	return encoded;
}
void EncryptAES::AesEncrypt(vector<byte> a) {
	try
	{
		string cipher;
		AutoSeededRandomPool prng;
		byte key[AES::DEFAULT_KEYLENGTH];
		prng.GenerateBlock(key, sizeof(key));


		ofstream outputF("aeskey", ofstream::binary);
		for (int i = 0;i<AES::DEFAULT_KEYLENGTH;i++)
			outputF << key[i];
		outputF.flush();
		outputF.close();

		OFB_Mode< AES >::Encryption e;
		e.SetKeyWithIV(key, sizeof(key), AES_IV);


		byte* plain = new byte[a.size()];
		for (int i = 0;i < a.size();i++)
			plain[i] = a[i];
		// OFB mode must not use padding. Specifying
		//  a scheme will result in an exception
		StringSource(plain, a.size(), true,
					 new StreamTransformationFilter(e,
													new StringSink(cipher)
					 ) // StreamTransformationFilter
		); // StringSource
		result.clear();
		vector<byte>(result).swap(result);
		stringToByte(cipher, result);
		delete[]plain;
	}
	catch (const CryptoPP::Exception& e)
	{
		cerr << e.what() << endl;
		exit(1);
	}

}

void EncryptAES::AesDecrypt(vector<byte> a, string str) {
	string decoded;
	StringSource ss(str, true,
					new HexDecoder(
							new StringSink(decoded)
					) // HexDecoder
	); // StringSource
	vector<byte> keyTemp;
	stringToByte(decoded, keyTemp);
	byte* key = new byte[keyTemp.size()];
	for (int i = 0;i < keyTemp.size();i++)
		key[i] = keyTemp[i];
	byte* cipher = new byte[a.size()];
	for (int i = 0;i < a.size();i++)
		cipher[i] = a[i];
	try
	{
		string recovered;
		OFB_Mode< AES >::Decryption d;
		d.SetKeyWithIV(key, keyTemp.size(), AES_IV);

		// The StreamTransformationFilter removes
		//  padding as required.
		StringSource s(cipher, a.size(), true,
					   new StreamTransformationFilter(d,
													  new StringSink(recovered)
					   ) // StreamTransformationFilter
		); // StringSource
		result.clear();
		vector<byte>(result).swap(result);
		stringToByte(recovered, result);
		delete[](key);
		delete[](cipher);
	}
	catch (const CryptoPP::Exception& e)
	{
		cerr << e.what() << endl;
		exit(1);
	}
}


Engineering code implementation

    Java is IDEA project, C++ is VS2015 project, including crypt lib. The address is as follows: AES int array encryption Java C++s implementation

Guess you like

Origin blog.csdn.net/u012397189/article/details/75090065