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:
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