Как создать подпись, используя HMACSHA1 и секретный ключ для подключения к Kayako API - PullRequest
7 голосов
/ 12 марта 2011

Я пытаюсь подключиться к API стороннего приложения с помощью HTTP-клиента apache commons. API, который я пытаюсь подключить: http://wiki.kayako.com/display/DEV/REST+API.

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

Согласно документации API это шаги для создания подписи

  1. Генерация случайной строки для создания соли (в PHP вы бы использовали mt_and () для этого)
  2. Генерируйте подпись, хэшируя соль, используя SHA256 с секретным ключом в качестве ключа (в PHP вы бы использовали hash_hmac () для этого)
  3. base64 кодирует подпись (в PHP вы бы использовали base64_encode () для этого)
  4. URL кодирует вывод (в PHP вы бы использовали для этого urlencode ())

ОБНОВЛЕНО

Согласно полученным ответам, я изменяю часть своего кода и создаю демо-счет на Kayako для тестирования API

Я использую следующий класс для генерации подписи

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.util.encoders.Base64Encoder;

public class GenSign2 {
    public static void main(String[] args) throws GeneralSecurityException,
            IOException {
        String secretKey = "M2Y2YjkxZDEtYmNlOC1mYmI0LTkxZTgtOTNiY2RiMDhmN2E2YjExNGUwYjktNGJkYy1jZTM0LWQ1MWYtZGIwYWRlZTE0NGNh";
        String salt = "0123456789";

        String generateHmacSHA256Signature = generateHmacSHA256Signature(salt,
                secretKey);
        System.out.println("Signature: " + generateHmacSHA256Signature);

        String urlEncodedSign = URLEncoder.encode(generateHmacSHA256Signature,
                "UTF-8");

        System.out.println("Url encoded value: " + urlEncodedSign);
    }

    public static String generateHmacSHA256Signature(String data, String key)
            throws GeneralSecurityException, IOException {
        byte[] hmacData = null;

        try {
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"),
                    "HmacSHA256");
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(secretKey);
            hmacData = mac.doFinal(data.getBytes("UTF-8"));
            ByteArrayOutputStream bout = new ByteArrayOutputStream();

            new Base64Encoder().encode(hmacData, 0, hmacData.length, bout);
            return bout.toString("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new GeneralSecurityException(e);
        }
    }
}

И тест API выглядит следующим образом

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

public class TestApi {

    public static void main(String[] args) throws ClientProtocolException,
            IOException, URISyntaxException {
        HttpClient client = new DefaultHttpClient();

        List<NameValuePair> qparams = new ArrayList<NameValuePair>();
        qparams.add(new BasicNameValuePair("apikey",
                "f165dc40-ce3f-6864-7d5e-27a7188b2e62"));
        qparams.add(new BasicNameValuePair("salt", "0123456789"));
        qparams.add(new BasicNameValuePair("signature", "mbrhpXkP0LzNMNDygHAorqMx%2FDGovl%2FauMTOMB6RNMA%3D"));

        HttpPost httpget = new HttpPost(
                "http://aruntest.kayako.com/api/index.php?e=/Core/Test");

        HttpResponse response = client.execute(httpget);
        System.out.println(response.getProtocolVersion());
        System.out.println(response.getStatusLine().getStatusCode());
        System.out.println(response.getStatusLine().getReasonPhrase());
        System.out.println(response.getStatusLine().toString());
    }

}

Демо-сайт доступен с помощью URL: http://aruntest.kayako.com/admin/
Пользователь: admin
Пароль: ty386rhjzz

При попытке подключения выдается исключение неавторизованного доступа.

Ответы [ 3 ]

4 голосов
/ 12 марта 2011

Попробуйте сравнить ваш метод подписи с этим (он работает)

public static String generateHmacSHA256Signature(String data, String key)   throws GeneralSecurityException {
    byte[] hmacData = null;

    try {
        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKey);
        hmacData = mac.doFinal(data.getBytes("UTF-8"));
        return new BASE64Encoder().encode(hmacData);
    } catch (UnsupportedEncodingException e) {
        // TODO: handle exception
        throw new GeneralSecurityException(e);
    }
}

Результат этого вызова будет значением вашего атрибута. Подпись

String signature = generateHmacSHA256Signature(salt, key);
qparams.add(new BasicNameValuePair("signature", signature));

Простой способ создания соли / одноразового номера

String nonce = String.valueOf(System.currentTimeMillis());

См. Пример:

1 голос
/ 26 августа 2011

Kayako обновил свою документацию новым образцом java , который отлично работает.

0 голосов
/ 12 марта 2011

Я думаю, что вся рутина getSaltedKey() не нужна.Вы просто подписываете соль (она должна была называться nonce ) с HMAC и подписываетесь с помощью предоставленного ключа, похоже, что вы не должны подписывать ключ + соль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...