Два первых байта в строке: поведение преобразования?

У меня есть байтовый массив, который является хешем файла. Это сделано с помощью messageDigest, поэтому есть прокладка. Затем я делаю короткий хэш, который представляет собой только два первых байта хеша, например:

 byte[] shorthash = new byte[2];
 System.arraycopy(hash, 0, shortHash, 0, 2);

Чтобы сделать его читаемым для пользователя и сохранить в БД, я конвертирую его в String с помощью Base64 Encoder:

Base64.getUrlEncoder().encodeToString(hash); //Same for shorthash

Я не понимаю:

  1. Почему String представляет мой короткий хэш длиной в четыре символа? Я думал, что символ - это один или два байта, поэтому, поскольку я копирую только два байта, у меня не должно быть больше двух символов, верно?

  2. Почему моя короткая хеш-строка не совпадает с началом хеш-строки?

Например, у меня будет:

Hash: LE5D8vCsMp3Lcf-RBwBRbO1v4soGq7BBZ9kB_2SJnGY=
Shorthash: Rak=

Вы можете увидеть = в конце каждого; это определенно происходит из-за заполнения MessageDigest, так что это нормально для хеша, но почему для короткого? Это должны быть два ПЕРВЫХ байта, а = находится в конце!

Более того: поскольку я хотел избавиться от этого Padding, я решил сделать это:

String finalHash = Base64.getUrlEncoder().withoutPadding().encodeToString(hash);
byte[] shorthash = new byte[2];
System.arraycopy(hash.getBytes(), 0, shortHash, 0, 2);
String finalShorthash = Base64.getUrlEncoder().encodeToString(shorthash);

Я не хотел копировать строку напрямую, так как я не совсем уверен, что будет двумя байтами в строке.

Затем = ушел из-за моего хэша, но не из-за моего короткого хэша. Я предполагаю, что мне нужно добавить опцию «withoutPadding» к моему короткому хешу, но я не понимаю почему, поскольку это копия моего хэша, у которой больше не должно быть отступов. За исключением случаев, когда заполнение отсутствует только в строковом представлении, а не в байте за ним?

Может кто-нибудь объяснить такое поведение? Это происходит из-за преобразования между byte [] и String?

Base64 требуется один байт для кодирования 6 бит, поэтому следует ожидать, что строка в кодировке base64 длиннее, чем исходная последовательность байтов.

tkausl 01.09.2018 12:03

Можете ли вы просто преобразовать массив из двух байтов в шестнадцатеричную строку? Таким образом, он будет более читабельным, чем строка с базой 64

Maurizio Ricci 01.09.2018 12:06

Спасибо за обзор. Да, думаю, я мог бы сделать это в шестнадцатеричном формате, Base64 - это только первое решение, которое я нашел. Я могу это сделать, но я все еще хочу понять, что такое странное поведение здесь. @tkausl дал ответ на первую проблему, спасибо!

Ablia 01.09.2018 12:19

Base64 дополняется числом, кратным четырем (хотя в некоторых схемах base64 заполнение не является обязательным). Это заполнение не имеет ничего общего с заполнением в схеме хеширования.

Mark Rotteveel 01.09.2018 12:20
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
50
1

Ответы 1

«Почему String представляет мою короткую хеш-код длиной в четыре символа?»

Потому что вы его закодировали в base64. Каждая цифра base64 представляет ровно 6 бит данных. У вас 16 бит. Двух цифр недостаточно (всего 12 бит), поэтому вам нужно 3 цифры для представления этих битов. Четвертая цифра - это заполнение, потому что base64 обычно нормализуется, чтобы быть кратным 4 цифрам.

И аналогично 32-байтовый хэш (вероятно, SHA-256 или SHA3-256?) Составляет 256 бит и 256/6> 42, поэтому для него требуется 43 цифры плюс 1 символ заполнения в base64.

dave_thompson_085 01.09.2018 17:48

Другие вопросы по теме