Почему AES/CTR/NoPadding не работает?

Для простоты я сейчас использую жестко закодированный ключ и IV. AesWriter (ниже) шифрует и записывает исходный открытый текст Abc\t1234\t\t\t\t\n в файл как 11,87,-74,122,-127,48,-118,39,82,-83,68,-30,-84. Но AesReader (также ниже) последовательно расшифровывает содержимое файла как zW?D?4?rc?~???~?_=p?J. Есть идеи, где я ошибаюсь?

public class AesWriter extends Activity {
    ...
    private void writeConfig() {
        ...
        try {
            Cipher cipher = Cipher.getInstance(AesReader.AES_ALGORITHM, 
                    AesReader.PROVIDER);
            cipher.init(Cipher.ENCRYPT_MODE, AesReader.getSecretKeySpec(),
                    AesReader.getIvParameterSpec()); 
            byte[] encrypted = cipher.doFinal(config.getBytes());
            OutputStreamWriter out =
                new OutputStreamWriter(openFileOutput(fileName, 0));
            out.write(AesReader.asHex(encrypted));
            out.close();
            ...

public class AesReader extends Activity {
    public static final String AES_ALGORITHM = "AES/CTR/NoPadding";
    public static final String PROVIDER = "BC"; 
    private static final byte[] aesKey128 = { // Hard coded for now
        78, -90, 42, 70, -5, 20, -114, 103, 
        -99, -25, 76, 95, -85, 94, 57, 54};
    private static final byte[] ivBytes = { // Hard coded for now
        -85, -67, -5, 88, 28, 49, 49, 85, 
        114, 83, -40, 119, -65, 91, 76, 108};
    private static final SecretKeySpec secretKeySpec = 
        new SecretKeySpec(aesKey128, "AES");
    private static final IvParameterSpec ivSpec = 
        new IvParameterSpec(ivBytes);
        ...
    private void readConfig() {
        String fileName = configuration.getFileName();
        try {
            InputStream is = openFileInput(fileName);
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            InputStreamReader isr = new InputStreamReader(cis);
            BufferedReader reader = new BufferedReader(isr);
            String s;
            while ((s = reader.readLine()) != null) {
                configuration.modify(s);
            }
            is.close();
            ...
    public static SecretKeySpec getSecretKeySpec() {
        return secretKeySpec;
    }
    public static IvParameterSpec getIvParameterSpec() {
        return ivSpec;
    }
    public static String asHex(byte buf[]) {
        StringBuffer strbuf = new StringBuffer(buf.length * 2);
        int i;
        for (i = 0; i < buf.length; i++) {
            if (((int) buf[i] & 0xff) < 0x10) {
                strbuf.append("0");
            }
            strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
        }

        return strbuf.toString();
    }

Рабочий код, основанный на предложении Эриксона:

public class FileIO {
    public final static String EOL = "\n";
    public static final String AES_ALGORITHM = "AES/CTR/NoPadding";
    public static final String PROVIDER = "BC"; 
    private static final byte[] AES_KEY_128 = { // Hard coded for now
        78, -90, 42, 70, -5, 20, -114, 103, 
        -99, -25, 76, 95, -85, 94, 57, 54};
    private static final byte[] IV = { // Hard coded for now
        -85, -67, -5, 88, 28, 49, 49, 85, 
        114, 83, -40, 119, -65, 91, 76, 108};
    private static final SecretKeySpec secretKeySpec = 
        new SecretKeySpec(AES_KEY_128, "AES");
    private static final IvParameterSpec ivSpec = 
        new IvParameterSpec(IV);

    public String readAesFile(Context c, String fileName) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            InputStream is = c.openFileInput(fileName);
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            InputStreamReader isr = new InputStreamReader(cis);
            BufferedReader reader = new BufferedReader(isr);
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append(EOL);
            }
            is.close();
        } catch (java.io.FileNotFoundException e) {
            // OK, file probably not created yet
            Log.i(this.getClass().toString(), e.getMessage(), e);
        } catch (Exception e) {
            Log.e(this.getClass().toString(), e.getMessage(), e);
        }
        return stringBuilder.toString();
    }

    public void writeAesFile(Context c, String fileName, String theFile) {
        try {
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM, PROVIDER); 
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(theFile.getBytes()); 
            OutputStream os = c.openFileOutput(fileName, 0);
            os.write(encrypted);
            os.flush();
            os.close();
        } catch (Exception e) {
            Log.e(this.getClass().toString(), e.getMessage(), e);
        }
    }
}

person jacknad    schedule 09.09.2010    source источник


Ответы (1)


Полный код не показан, но похоже, что вы записываете текст в шестнадцатеричном кодировании в файл, но читаете его без декодирования обратно в байты. Пропустите шестнадцатеричное кодирование (я предполагаю, что это должно помочь вам в отладке).

person erickson    schedule 09.09.2010
comment
Вот оно. Бесконечно благодарен. Я выделил функции ввода-вывода зашифрованных файлов в новый класс, чтобы помочь с моей путаницей. Я публикую рабочий код как редактирование моего исходного вопроса. - person jacknad; 10.09.2010