nteroperabilidade @CryptoAPI C ++ com Java usando AES

Estou tentando criptografar em C ++ usando CryptoAPI e descriptografar Java usando SunJCE. Eu obtive a chave RSA para funcionar - e verifiquei em uma sequência de teste. No entanto, minha chave AES não está funcionando - eu recebojavax.crypto.BadPaddingException: Given final block not properly padded.

riptografia C ++:

// init and gen key
HCRYPTPROV provider;
CryptAcquireContext(&provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);

// Use symmetric key encryption
HCRYPTKEY sessionKey;
DWORD exportKeyLen;
CryptGenKey(provider, CALG_AES_128, CRYPT_EXPORTABLE, &sessionKey);

// Export key
BYTE exportKey[1024];
CryptExportKey(sessionKey, NULL, PLAINTEXTKEYBLOB, 0, exportKey, &exportKeyLen);

// skip PLAINTEXTKEYBLOB header
//      { uint8_t bType, uint8_t version, uint16_t reserved, uint32_t aiKey, uint32_t keySize }
DWORD keySize =  *((DWORD*)(exportKey + 8));
BYTE * rawKey = exportKey + 12;

// reverse bytes for java
for (unsigned i=0; i<keySize/2; i++) {
    BYTE temp = rawKey[i];
    rawKey[i] = rawKey[keySize-i-1];
    rawKey[keySize-i-1] = temp;
}

// Encrypt message
BYTE encryptedMessage[1024];
const char * message = "Decryption Works";
BYTE messageLen = (BYTE)strlen(message);
memcpy(encryptedMessage, message, messageLen);
DWORD encryptedMessageLen = messageLen;
CryptEncrypt(sessionKey, NULL, TRUE, 0, encryptedMessage, &encryptedMessageLen, sizeof(encryptedMessage));

// reverse bytes for java
for (unsigned i=0; i<encryptedMessageLen/2; i++) {
    BYTE temp = encryptedMessage[i];
    encryptedMessage[i] = encryptedMessage[encryptedMessageLen - i - 1];
    encryptedMessage[encryptedMessageLen - i - 1] = temp;
}

BYTE byteEncryptedMessageLen = (BYTE)encryptedMessageLen;
FILE * f = fopen("test.aes", "wb");
fwrite(rawKey, 1, keySize, f);
fwrite(&byteEncryptedMessageLen, 1, sizeof(byteEncryptedMessageLen), f);
fwrite(encryptedMessage, 1, encryptedMessageLen, f);
fclose(f);

// destroy session key
CryptDestroyKey(sessionKey);
CryptReleaseContext(provider, 0);

Java Decryption:

try
{
    FileInputStream in = new FileInputStream("test.aes");
    DataInputStream dataIn = new DataInputStream(in);

    // stream key and message
    byte[] rawKey = new byte[16];
    dataIn.read(rawKey);
    byte encryptedMessageLen = dataIn.readByte();
    byte[] encryptedMessage = new byte[encryptedMessageLen];
    dataIn.read(encryptedMessage);

    // use CBC/PKCS5PADDING, with 0 IV -- default for Microsoft Base Cryptographic Provider
    SecretKeySpec sessionKey = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, sessionKey, new IvParameterSpec(new byte[16]));

    cipher.doFinal(encryptedMessage);
}
catch (Exception e) {
  e.printStackTrace();
}

Em um exemplo semelhante, tentei permutações de não reverter os bytes da chave e não reverter os bytes na mensagem. Se eu criptografar e descriptografar com a chave importada em java, obtenho resultados válidos. Também posso criptografar e descriptografar exclusivamente em C ++.

Questões

Devo usar CBC / PKCS5PADDING? Esse é o padrão paraMS_ENH_RSA_AES_PROV? É um IV zerado, de fato, o padrão paraMS_ENH_RSA_AES_PROV? Existe alguma maneira de diagnosticar as especificidades de como a chave está se comportand Gostaria de ficar com os pacotes Java padrão em vez de instalar o BouncyCastle, mas existem diferenças que tornariam um pacote de terceiros funcionar melhor?

questionAnswers(3)

yourAnswerToTheQuestion