1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/durcframework-easyopen

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
签名算法.md 8 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 30.11.2024 18:34 ac99f10

Алгоритм подписи

Алгоритм подписи описывается следующим образом:

  1. Отсортировать параметры запроса по имени в порядке возрастания;
  2. Соединить имена и значения параметров в одну строку: <paramName1><paramValue1><paramName2><paramValue2>...;
  3. Добавить секретный ключ в начало и конец строки параметров: <secret><запрос параметров><secret>;
  4. Выполнить MD5-хеширование (все символы в верхнем регистре) полученной строки, результат хеширования будет являться подписью для соответствующих параметров запроса;
  5. Отправить полученную подпись вместе с остальными параметрами запроса на открытую платформу сервиса.

Пример параметров

{
    "name": "file.upload",
    "version": "",
    "app_key": "admin",
    "data": "%7B%22goods_name%22%3A%22iphoneX%22%7D",
    "timestamp": "2018-07-17 16:34:34",
    "format": "json",
    "sign": "966E54AE152F0D60840E65A15376D924"
}

Пример запроса

import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.Test;

import com.alibaba.fastjson.JSON;

import junit.framework.TestCase;

public class PostTest extends TestCase {

    @Test
    public void testPost() throws IOException {
        String appKey = "test";
        String secret = "123456";
        // 业务参数
        Map<String, String> jsonMap = new HashMap<String, String>();
        jsonMap.put("goodsName", "iphoneX");

        String json = JSON.toJSONString(jsonMap);
        json = URLEncoder.encode(json, "utf-8");

        // 系统参数
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("name", "goods.get");
        param.put("app_key", appKey);
        param.put("data", json);
        param.put("timestamp", getTime());
        param.put("version", "");
        param.put("access_token", "");

        String sign = buildSign(param, secret);

        param.put("sign", sign);

        /*
        // 最终请求数据
        {
            "sign": "2AE534A15AACE112EE43B9CCF6BD4383",
            "timestamp": "2018-03-21 12:57:30",
            "name": "goods.get",
            "data": "%7B%22goodsName%22%3A%22iphoneX%22%7D",
            "app_key": "test",
            "version": ""
        }
        */
        System.out.println("=====请求数据=====");
        String postJson = JSON.toJSONString(param);
        System.out.println(postJson);
        // contentType:application/json
        // postJson放到请求体中
        // String resp = HttpUtil.post(postJson); // 发送请求
        /*
        响应结果:
        {
            "code":"0",
            "data":{
                "pageIndex":1,
                "pageSize":10,
                "rows":[
                    {
                        "goods_name":"iPhoneX",
                        "id":1,
                        "price":8000
                    },
                    {
                        "goods_name":"三星",
                        "id":2,
                        "price":7000
                    }
               ],
               "total":100
            }
        }
        */
    }

    /**
     * 构建签名
     *
     * @param paramsMap
     *            参数
     * @param secret
     *            密钥
     * @return
     * @throws IOException
     */
    public static String buildSign(Map<String, ?> paramsMap, String secret) throws IOException {
        Set<String> keySet = paramsMap.keySet();
        List<String> paramNames = new ArrayList<String>(keySet);

        Collections.sort(paramNames);

        StringBuilder paramNameValue = new StringBuilder();

        for (String paramName : paramNames) {
            paramNameValue.append(paramName).append(paramsMap.get(paramName));
        }

        String source = secret + paramNameValue.toString() + secret;

        return md5(source);
    }

    /**
     * 生成md5,全部大写
     *
     * @param message
     * @return
     */
    public static String md5(String message) {
        try {
            // 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 2 将消息变成byte数组
            byte[] input = message.getBytes();

            // 3 计算后获得字节数组,这就是那128位了
            byte[] buff = md.digest(input);

            // 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串
            return byte2hex(buff);
        } catch (Exception e) {
    }}
``` ```
бросить новое RuntimeException(e);
    }
}

/**
 * Преобразование двоичных данных в шестнадцатеричную строку
 *
 * @param bytes
 * @return
 */
private static String byte2hex(byte[] bytes) {
    StringBuilder sign = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(bytes[i] & 0xFF);
        if (hex.length() == 1) {
            sign.append("0");
        }
        sign.append(hex.toUpperCase());
    }
    return sign.toString();
}

public String getTime() {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}

Передача данных с использованием шифрования на основе открытого и закрытого ключей + AES:

  1. Заранее разместите открытый ключ на клиенте, а закрытый ключ — на сервере.
  2. Клиент генерирует случайный код randomKey.
  3. randomKey шифруется с помощью открытого ключа RSA: str = rsa_encode(randomKey, publicKey).
  4. Отправляется str на сервер.
  5. Сервер расшифровывает str с помощью закрытого ключа, получая randomKey: randomKey = rsa_decode(str, privateKey).
  6. Сервер использует randomKey для симметричного шифрования значения (предположим, значение равно «0»): resp = aes_encode("0", randomKey).
  7. Клиент расшифровывает resp с помощью своего randomKey. Если результатом является «0», то рукопожатие успешно завершено. В дальнейшем все данные будут передаваться с использованием этого randomKey и симметричного шифрования.

Примечание: Хакер может получить доступ к открытому ключу, но не сможет узнать случайный код randomKey, сгенерированный клиентом. Если str будет изменена, рукопожатие завершится неудачно. Основная цель этого процесса — безопасно передать randomKey на сервер, чтобы использовать его для симметричного шифрования при передаче данных. Симметричное шифрование невозможно взломать хакеру. Этот процесс похож на HTTPS, за исключением того, что сервер не может правильно отправить открытый ключ клиенту (браузеру), поэтому требуется вмешательство центра сертификации (CA).

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/durcframework-easyopen.git
git@api.gitlife.ru:oschina-mirror/durcframework-easyopen.git
oschina-mirror
durcframework-easyopen
durcframework-easyopen
master