Android HMAC-SHA1 отличается от стандартного Java HMAC-SHA1 - PullRequest
6 голосов
/ 13 августа 2011

У меня проблемы с некоторыми HMAC на Android. Я использую алгоритм SHA1 со следующим кодом, который появляется по всему Интернету при поиске Android hmac-sha1.

        String base_string = "This is a test string";
        String key = "testKey";
        try {
            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec secret = new SecretKeySpec(key.getBytes("UTF-8"), mac.getAlgorithm());
            mac.init(secret);
            byte[] digest = mac.doFinal(base_string.getBytes());

            String enc = new String(digest);

            // Base 64 Encode the results
            String retVal = Base64.encodeBase64String(enc.getBytes());
            Log.v(TAG, "String: " + base_string);
            Log.v(TAG, "key: " + key);
            Log.v(TAG, "result: " + retVal);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

Чтобы проверить этот код, я создал простую стандартную Java-программу (заменив вызовы Log.v на вызовы System.out.println, конечно), чтобы я мог сравнить с версией для Android. В обоих случаях я использую одинаковые тестовые значения для base_string и ключа.

Кроме того, я проверил закодированные результаты из стандартной Java с некоторыми функциями PHP и сервером проверки (с использованием некоторых токенов OAuth). Код прекрасно работает в стандартной программе Java, однако он не работает в программе Android. Я сделал много поисков и не могу понять, что не так. Кто-нибудь когда-нибудь испытывал это?

Вот результаты стандартных java и android ...

  • Java (и PHP): fH/+pz0J5XcPZH/d608zGSn7FKA=
  • Программа для Android: fH/vv73vv709Ce+/vXcPZH/vv73vv71PMxkp77+9FO+/vQ==

Рассматривая это немного подробнее, я уверен, что это функция hmac, а не кодировка Base64, где она путается при сравнении этих значений hmac, версия Android имеет всевозможные дополнительные пробелы и другие неизвестные символьные символы по сравнению с Java программа.

Любая помощь приветствуется!

1 Ответ

13 голосов
/ 13 августа 2011

Полагаю, это проблема строкового кодирования.

Что ты здесь делаешь?

        String enc = new String(digest);

        // Base 64 Encode the results
        String retVal = Base64.encodeBase64String(enc.getBytes());

Вы превращаете байты в строку, а затем снова возвращаетесь в байтовый массив (который затем кодируется с помощью base-64).

Вместо этого сделайте следующее:

        String retVal = Base64.encodeBase64String(digest);

Как правило, никогда не пользуйтесь String.getBytes() или new String(byte[]), если вам нужна переносимая программа. И никогда не пытайтесь преобразовать произвольные байтовые массивы (которые раньше не были строкой) в строку (отличную от Base64).

...