Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Изменяется кол-во байт в строке после шифрования


Автор: 4epT 4.10.2011, 18:11
Здравствуйте! делаю шифрования на Java. В функцию приходит строка, я ее перегоняю в массив байт и делю на блоки (по 8 элементов). Затем к каждому блоку применю XOR с ключем (побайтно). После чего набор байт полученный после шифрования превращается в строку. Если строку перегнать в массив байт, мы получим что там элементов стало в разы больше ... 

Вот пример:

Код

int j = 0;
        
        String outText = "";
        
        for(int i = 0; i < textInByte.length / K; i++){
            
            byte[] bI = new byte[K];
            byte[] bResult = new byte[K];
            
            for(int k = 0; k < K; k++){
                bI[k] = textInByte[j++];
            }
            
            for(int k = 0; k < K; k++){
                bResult[k] = (byte) (bI[k] ^ IV[k]);
            }
            
            outText += new String(bResult, Charset.defaultCharset());
            
        }

System.out.println(outText.getBytes().length + " = " + textInByte.length); // Тут будет примерно следующие 118 = 56


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

Автор: Stolzen 4.10.2011, 18:20
В разы - это в 2?
Попробуйте вместо Charset.defaultCharset() в new String(bResult, Charset.defaultCharset()); использовать "UTF-8"

Автор: 4epT 4.10.2011, 21:11
Нет, разница не в 2 раза ... всегда по разному. 

Попробовал с UTF-8 та же проблема ... 

Может есть какие то специальные хелпер классы для конвертации строк в байты и назад ?

Автор: aleksandy 5.10.2011, 07:44
http://www.skipy.ru/technics/encodings.html

Автор: Stolzen 5.10.2011, 08:27
Код

static Charset utf8 = Charset.forName("UTF-8");

public static void main(String[] args) {
    
    byte key = (byte) 0xAB;
    
    String s1 = "строка в UTF-8";
    byte[] bytesOfS1 = s1.getBytes(utf8);
    String s2 = new String(bytesOfS1, utf8);
    System.out.println(s2);
    
    int length = bytesOfS1.length;
    byte[] xoredBytes = new byte[length];
    
    for (int i = 0; i < length; ++i) {
        xoredBytes[i] = (byte) (bytesOfS1[i] ^ key);
    }
    
    String s3 = new String(xoredBytes, utf8);
    System.out.println(s3);
    
    byte[] unXoredBytes = new byte[length];
    for (int i = 0; i < length; ++i) {
        unXoredBytes[i] = (byte) (xoredBytes[i] ^ key);
    }
    
    String result = new String(unXoredBytes, utf8);
    System.out.println(result);
}

Автор: 4epT 5.10.2011, 11:18
Stolzen, твой пример работает. Но я по прежнему не вижу разницы между моим кодом и твоим ...

aleksandy, стаьтю прочитал, спасибо. Но так и не понял что я не так делаю ... я везде использую одну кодировку, и следовательно все должно работать ...


Изменил кодировку с UTF-8 на windows-1251 и кол-во символов стало совпадать до кодирования и после, но русские буквы он маскирует квадратами ((

Как можно явно указать кодировку при создании String ? 

Автор: Skipy 5.10.2011, 11:38
Цитата(4epT @ 5.10.2011,  11:18)
Как можно явно указать кодировку при создании String ?

Например, почитать документацию: http://download.oracle.com/javase/6/docs/api/java/lang/String.html, String(byte[], String)

Неожиданный ход, правда?

Автор: 4epT 5.10.2011, 11:47
Цитата(Skipy @ 5.10.2011,  11:38)
Например, почитать документацию: http://download.oracle.com/javase/6/docs/api/java/lang/String.html#String(byte%5B. Неожиданный ход, правда?

В документации смотрел ... просто ожидал что то вроде:

Код

String str = new String("Строка" , Charset.forName("UTF-8"));


Сделал вот так:

Код

String str = new String("Строка".getBytes() , Charset.forName("windows-1251"));


Вроде заработало все! Всем спасибо!

Автор: math64 5.10.2011, 13:41
Код

static Charset utf8 = Charset.forName("UTF-8");
static Charset win1251 = Charset.forName("windows-1251");
byte[] key = "Ключ".getBytes(win1251);

byte[] bytes = s.getBytes("Строка".getBytes(win1251));
for(int i = 0; i < bytes.length; i++)
  bytes[i] ^= key[i%key.length];
String str = new Sting(bytes, win1251); // Байты должны быть в кодировке 1251 - можно получить исключение
String str = new Sting(bytes, utf8); // Исключение ещё более вероятно

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

Автор: 4epT 5.10.2011, 14:11
А какое может быть исключение ?

Если везде использовать одну и ту же кодировку, есть ли возможность поймать исключение ?

Автор: math64 5.10.2011, 20:09
В windows-1251 есть неиспользуемые коды - если они попадутся получишь исключенте
В utf-8 символы с кодами > 127 кодируются несколькими байтами, если есть только первый байт, а нет второго или наоборот - тоже получишь исключение

Автор: math64 6.10.2011, 10:58
Я ошибся - не бросает исключения, а вставляет '?' на место символов, которые не смог перекодировать
Код

for(int i=128; i <256;i++) {
byte[] bytes = new byte[] { (byte)i };
byte b = new String(bytes, win1251).getBytes(win1251)[0];
if (b != bytes[0])
System.out.println("Нет символа в кодировке: " + i + " заменяется на " + b);
}

Вывод:
Код

Нет символа в кодировке: 152 заменяется на 63


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)