Cifrado y descifrado AES int array-implementación Java C ++

Descripción del problema

cifrado

Entrada : matriz int original, como [1,2,3,4]
Salida : matriz int cifrada, como [2323,323,333,555]

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

Descifrar

Entrada : la matriz int cifrada, como [2323,323,333,555]
Salida : la matriz int descifrada, como [1,2,3,4]

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

Algunas soluciones

  • El algoritmo RSA cifra y descifra cada número de la matriz
  • AES primero convierte cada número en una cadena y luego lo encripta y desencripta. Este método no funciona, porque la cadena cifrada no se puede convertir en una representación digital.

Solución AES

    El código java es que jdk usa su propia biblioteca, que generará automáticamente la clave, y luego la guardamos en el archivo; la biblioteca de cifrado utilizada por C ++ es crypt, una biblioteca de cifrado muy poderosa, y la matriz debe ser reemplazada por un contenedor de vectores.

Paso 1 int 转 byte

    Un int corresponde a 4 bytes, el código de conversión de Java es el siguiente:

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;
    }

    El código de conversión de C ++ es el siguiente:

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;
}

Paso 2 byte 转 int

    4 bytes corresponden a 1 Int, el código de conversión es el siguiente:

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

    El código de conversión de C ++ es el siguiente:

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;
}

Paso 3 Conversión entre matriz de bytes y matriz int

    Convierta una matriz int en una matriz de bytes, el código de conversión de Java es el siguiente:

 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;
    }

    El código de conversión de C ++ es el siguiente:

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]);
		}
	

    Convierta una matriz de bytes en una matriz int, el código de conversión de Java es el siguiente:

  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;
    }

    El código de conversión de C ++ es el siguiente:

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));
	}
}

Paso 4 El último paso para cifrar y descifrar la matriz de bytes

Aquí tenemos que considerar la elección del modo AES. Si una matriz int tiene solo un int, equivale a solo 4 bytes durante mucho tiempo, lo que no cumple con la longitud de 16 bytes de aes. Esperamos que la longitud de la suma cifrada sea la misma que la anterior al cifrado La longitud es la misma, entonces el número de int después del cifrado es el mismo que el número de int antes del cifrado, por lo que elegimos el modo AES / OFB / NoPadding. En cuanto a todos los modos de aes como se muestra a continuación:

aes todos los modos

    El código de cifrado y descifrado de Java es el siguiente:

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();
        }
    }

    El código de cifrado y descifrado de C ++ es el siguiente:

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);
	}
}


Implementación de código de ingeniería

    Java es el proyecto IDEA, C ++ es el proyecto VS2015, incluida la biblioteca de cifrado. La dirección es la siguiente: Encriptación de matriz AES int Implementación de Java C ++ s

Supongo que te gusta

Origin blog.csdn.net/u012397189/article/details/75090065
Recomendado
Clasificación