nie odszyfrowywania tego, co zaszyfrowałem

Mam dziwny problem ...

Oparte na moim rozwiązaniuOdszyfrowywanie zakodowanego pliku jako bajtu []

Napisałem więc małą klasę Cypherów, aby pomóc w szyfrowaniu / deszyfrowaniu ... Kiedyś szyfrowaliśmy klucz zapisany w jakimś miejscu, a inny wstępnie zaszyfrowany klucz przechowywano gdzie indziej. Ale to trochę nieistotny bankomat.

proces szyfrowania przebiegał tak:

pobrać zakodowaną tablicę bajtówużyj go do odszyfrowania klucza2użyj klucza2, aby odszyfrować daneużyj klucza 1, aby dalej odszyfrować danemieć odszyfrowane dane

Przechowywałem zakodowane dane jako ciąg szesnastkowy, użyłem tych dwóch funkcji, aby się tam dostać

private static String byteArrayToHexString(byte[] b)
{
    StringBuffer sb = new StringBuffer(b.length * 2);
    for (int i = 0; i < b.length; i++)
    {
        int v = b[i] & 0xff;
        if (v < 16)
        {
            sb.append('0');
        }
        sb.append(Integer.toHexString(v));
    }
    return sb.toString().toUpperCase();
}

private static byte[] hexStringToByteArray(String s)
{
    byte[] b = new byte[s.length() / 2];
    for (int i = 0; i < b.length; i++)
    {
        int index = i * 2;
        int v = Integer.parseInt(s.substring(index, index + 2), 16); //THIS LINE
        b[i] = (byte) v;
    }
    return b;
}

To działało bez zarzutu; w rzeczywistości działał tak dobrze, że wdrożyłem go w moim prawdziwym projekcie. Projekt nie został uruchomiony z powodu tego, że nie testowałem go dokładnie.

Okazuje się, że kryptuje / deszyfruje prawie wszystkie pliki, z wyjątkiem jednego - że nie chce się go odszyfrować.

Wskazałem jednak problem - linia THIS zgłasza wyjątek IllegalNumberFormat; w pewnym momencie zapoznałem się z tymhttp://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 także. Chciałbym i mogę powrócić do tej metody, jeśli ktoś opisuje sposób na ominięcie przypadku, gdy ciąg o długości 2 jest konwertowany na cztery bajty, które rzucają wyjątek IllegalNumberFormatException.

Uznałem więc, że skoro nie mogę zdekodować pliku (i oczywiście nie mogę go udostępnić tutaj, żebyście mogli go wypróbować), musiałem go jakoś przekształcić, aby był bezpieczny dla transportu. Wpisz klasę Base64Coder, która koduje łańcuchy base64 ...

Wydawało się, że wprowadzono nową kwestię - padding był coraz trudniejszy.

Pytanie jest proste - co robię źle? Muszę dostosować się do tych danych i musi być w stanie poprawnie i równo szyfrować / deszyfrować. Chciałbym, aby propozycja najlżejszego rozwiązania możliwa była przy najmniejszej kopii / wklejeniu ... pseudokod nie zadziała tutaj.

Oto, co teraz robię ....

public static char[] encrypt2(byte[] value) throws GeneralSecurityException, IOException
{
    SecretKeySpec key1 = getSecretKeySpec(true);
    System.err.println("encrypt():\t" + key1.toString());
    Cipher cipher = Cipher.getInstance(CRYPTOSYS);
    cipher.init(Cipher.ENCRYPT_MODE, key1, cipher.getParameters());
    byte[] encrypted = cipher.doFinal(value);

    SecretKeySpec key2 = getSecretKeySpec(false);
    cipher = Cipher.getInstance(CRYPTOSYS);
    cipher.init(Cipher.ENCRYPT_MODE, key2, cipher.getParameters());
    byte[] encrypted2 = cipher.doFinal(encrypted);

    return Base64Coder.encode(encrypted2);
}

public static byte[] decrypt2(char[] message) throws GeneralSecurityException, IOException
{
    SecretKeySpec key1 = getSecretKeySpec(false);
    System.err.println("decrypt():\t" + key1.toString());
    Cipher cipher = Cipher.getInstance(CRYPTOSYS);
    cipher.init(Cipher.DECRYPT_MODE, key1);
    byte[] decrypted = cipher.doFinal(Base64Coder.decode(message));

    SecretKeySpec key2 = getSecretKeySpec(true);
    cipher = Cipher.getInstance(CRYPTOSYS);
    cipher.init(Cipher.DECRYPT_MODE, key2);
    byte[] decrypted2 = cipher.doFinal(decrypted);

    return decrypted2;
}

Należy pamiętać, że klucze są obecnie w pełni eksponowane (na stałe) do celów testowych.

Oto mój test

public static void main(String... args) throws Exception
{
    //      byte[] data = "hello".getBytes();
    File PEM = new File(PATH_TO_FILES + SOURCE_PEM);
    File DER = new File(PATH_TO_FILES + SOURCE_DER);
    File cryptoPEM = new File(PATH_TO_FILES + "cryptopem");
    File cryptoDER = new File(PATH_TO_FILES + "cryptoder");

    byte[] cryptokey = encryptA(ASSET_KEY);
    System.out.println(new String(cryptokey));

    //pem key
    System.out.println("PEM");
    byte[] data = getBytesFromFile(PEM);
    char[] crypted = encrypt2(data);
    //      FileOutputStream fos = new FileOutputStream(cryptoPEM);
    FileWriter fw = new FileWriter(cryptoPEM);
    fw.write(crypted);
    fw.flush();

    //der key
    System.out.println("DER");
    data = getBytesFromFile(DER);
    crypted = encrypt2(data);
    fw = new FileWriter(cryptoDER);
    fw.write(crypted);
    fw.flush();

    //opentext
    System.out.println("checking PEM...");
    crypted = Base64Coder.encode(getBytesFromFile(cryptoPEM));
    byte[] decrypted = decrypt2(crypted,  false);
    byte[] decryptedData = decrypted;

    if (!Arrays.equals(getBytesFromFile(PEM), decryptedData)) { throw new Exception("PEM Data was not decrypted successfully"); }

    System.out.println("checking DER...");
    crypted = Base64Coder.encode(getBytesFromFile(cryptoDER));
    decrypted = decrypt2(crypted,  false);
    decryptedData = decrypted;

    if (!Arrays.equals(getBytesFromFile(DER), decryptedData)) { throw new Exception("DER Data was not decrypted successfully"); }
}

Otrzymuję teraz wyjątek InvalidBlockSizeException .... Proszę, ktoś rzuci trochę światła na ten temat, chcę, żeby to zadziałało ...

Zastąpienie „key2” dla IV w celu późniejszego użycia w „AES / CBC / PKCS5Padding” to opcja, którą teraz rozważam. Zasadniczo nic się nie zmieni, z wyjątkiem drugiego kroku szyfrowania. Teoretycznie i metodycznie zachowuję to samo - chyba że opisane zostanie lepsze rozwiązanie.

Na koniec chciałbym podkreślić, że jest to pytanie programisty, a nie pytanie studenta bezpieczeństwa IT, więc właściwy kod jest ceniony bardziej niż teoretyczna odpowiedź, która obejmuje mało prawdopodobne przypadki uboczne.

EDYTUJ: cóż, nie mogę podać numerów, które powodują wyjątek IllegalNumberFormatException, ponieważ zgubiłem kod z dzisiejszego ranka. Wydaje mi się, że nie jestem w stanie powtórzyć tego problemu, więc sądzę, że próbuję zrozumieć, że ta część jest bezużyteczna.

Oto wynik testu próbnego:

encrypt():  javax.crypto.spec.SecretKeySpec@15dd7
5@��_׵G�j��!�c;D�i�lR?z�j\
PEM
encrypt():  javax.crypto.spec.SecretKeySpec@15dd7
DER
encrypt():  javax.crypto.spec.SecretKeySpec@15dd7
checking PEM...
decrypt():  javax.crypto.spec.SecretKeySpec@15c78
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

co oznacza, że ​​Base64 trochę to psuje ...

questionAnswers(3)

yourAnswerToTheQuestion