用户登录SHA+MD5加签,验签过程

安全规范

请求报文和响应报文采用对称加密方式

报文采用MD5+SHA的签名方式,具体签名字段参照报文里的SIGN字段说明,签名使用的工具包后面一并提供,按照说明使用即可。

SHA安全签名机制说明

MD5+SHA安全签名机制是对接方和开发方约定一个签名key,每次在做签名时将参数包括key先进行sort排序拼接成一个待签名字符串,经MD5加密运算后得到一个加密字符串,然后在对该加密字符串做SHA加密运算后得到一个签名串,对接方和开发方通过在检验时先对参数进行相同规则的排序并拼接成字符串进行MD5加密,得到MD5密文,然后对得到的密文字段进行SHA加密得到一个签名串,两个签名串经比对后确定是否一致,如果一致,则签名通过。

请求时签名

先通过约定好的排序规则对请求参数进行排序,并形成一个字符串,对字符串进行MD5的加密,得到密文,再将得到的密文和约定好的密钥,通过SHA加签处理进行生成一个签名串,并将得到的签名串放入sign字段

通知和返回时验证签名

对请求参数进行相同规则的排序并拼接成字符串进行MD5加密,得到MD5密文,然后对得到的密文字段进行SHA加密得到一个签名串,两个签名串经比对后确定是否一致,如果一致,则签名通过

加签参数:

我需要给第三方提供:

//传递的url
http://。。。。。。。


//规定好的ak值
private String accessKey;
//双方规定好的所需要的参数
private String ***;
//双方规定好的密钥
private String secret;

验证的时候:

//加签过后的签名
private String sign;
//规定好的ak值
private String accessKey;
//双方规定好的所需要的参数
private String ***;
//双方规定好的密钥
private String secret;

加密示例:

数据加签:

/**
 * 数据加签demo
 */
public static void signDemo(){
    //需要加签的key
    String key = "****";
    //需要加签的密钥
    String secret = "****";
    //携带的请求参数
    Map<String, String> data = new HashMap<>();
    data.put("sign","");//加签的时候 签名参数可以置空
    data.put("所需要传递的参数","xxx");
    data.put("所需要传递的参数", "xxx");
    data.put("accessKey", "xxx");//双方所规定的ak值
    //先进行排序和MD5加密(下面是特定的方法,在后面代码块中会有体现)
    String signature = HmacSHA1Signer.generateSignature(data);
    //使用加签工具
    String sign = HmacSHA1Signer.signString(signature, secret);
    System.out.println("加签完成:"+sign);

}

数据验签

/**
 * 数据验签demo
 */
public static void checkSignDemo(){
    // 1 获取参数传递的签名和ak值
    String accessKey = request.getAccessKey();
    String sign = request.getSign();
    // 2 通过key去查询对应的密钥
    //查询到需要加签的密钥
    String secret = "****";
    //处理请求参数
    Map<String, String> data = new HashMap<>();
    //构造当前签名所需要的参数
    data.put("sign","");//url传递过来的签名信息
    data.put("请求url所携带的参数",request.getUserMobile());
    data.put("请求url所携带的参数",request.getUserNickname());
    data.put("accessKey",request.getAccessKey());//url传递过来的ak值
    //排序和生产MD5密文
    String signature = HmacSHA1Signer.generateSignature(data);
    //生成签名
    String mySign = HmacSHA1Signer.signString(signature, authinfo.getAccessSecret());
    //验证
    boolean b = mySign..equals(sign);
    System.out.println("验签结果:"+b);
}

加签所使用的工具类:

/**
 * HmacSHA1 加签包
 *
 * @author dacongming
 * @version V1.0.0 
 */
public class HmacSHA1Signer {
    private static final String ALGORITHM_NAME = "HmacSHA1";
    public static final String ENCODING = "UTF-8";

    /**
     *
     * @methodName: generateSignature
     * @param: [data, key, signType]
     * @describe: 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     * @auther: dacongming
     * @date: 2021/11/11 11:11
     **/
    public static String generateSignature(Map<String, String> data) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if(null != data.get(k)) {
                // 参数值为空,则不参与签名
                if (data.get(k).trim().length() > 0) {
                    if(k.equals("sign")){
                        continue;
                    }
        //将排序之后的参数进行拼接                                
        sb.append(k).append("=").append(data.get(k).trim()).append("&");
                }
            }
        }
        //去除最后一个&符号
        String md5String = MD5(sb.substring(0,sb.length()-1)).toUpperCase();
        return md5String;
    }

    /**
     *
     * @methodName: MD5
     * @param: [data]
     * @describe: 生成 MD5
     * @auther: dacongming
     * @date: 2021/11/11 11:11
     **/
    public static String MD5(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }

    /**
     * 获取加签值
     * @param stringToSign
     * @param accessKeySecret
     * @return
     */
    public static String signString(String stringToSign, String accessKeySecret) {
        try {
            Mac mac = Mac.getInstance(ALGORITHM_NAME);
            mac.init(new SecretKeySpec(
                    accessKeySecret.getBytes(ENCODING),
                    ALGORITHM_NAME
            ));
            byte[] signData = mac.doFinal(stringToSign.getBytes(ENCODING));
            return DatatypeConverter.printBase64Binary(signData);
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
            throw new IllegalArgumentException(e.toString());
        }
    }

    public String getSignerName() {
        return "HMAC-SHA1";
    }

    public String getSignerVersion() {
        return "1.0";
    }

    public String getSignerType() {
        return null;
    }
}

结束

如果有哪些不对的地方,请多多指教

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我会分别回答您的两个问题。 首先是 JAVA 实现 ECDSA 加签JAVA 中的 ECDSA 加签可以通过使用 Bouncy Castle 加密库来实现。下面是一个简单的示例代码: ```java import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import java.security.*; import java.security.spec.ECGenParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public class ECDSASample { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); // 生成公私钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC"); ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256k1"); keyPairGenerator.initialize(ecGenParameterSpec); KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 加签 String message = "hello world"; Signature signature = Signature.getInstance("SHA256withECDSA", "BC"); signature.initSign(keyPair.getPrivate()); signature.update(message.getBytes()); byte[] sigBytes = signature.sign(); System.out.println("Signature: " + Hex.toHexString(sigBytes)); } } ``` 在上面的代码中,我们首先使用 Bouncy Castle 加密库来实现 ECDSA。然后使用 KeyPairGenerator 生成公私钥对,并且使用 SHA256withECDSA 算法进行加签。最后,我们使用 Hex.toHexString 将字节数组转换为十六进制字符串。 接下来是 C 语言实现 ECDSA 验签。 C 语言中的 ECDSA 验签可以通过使用 OpenSSL 库来实现。下面是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <openssl/ec.h> #include <openssl/ecdsa.h> #include <openssl/evp.h> #include <openssl/obj_mac.h> int main() { // 生成公私钥对 EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp256k1); EC_KEY_generate_key(key); const BIGNUM *priv_key = EC_KEY_get0_private_key(key); const EC_POINT *pub_key = EC_KEY_get0_public_key(key); // 加签 char message[] = "hello world"; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_DigestInit(ctx, EVP_sha256()); EVP_DigestUpdate(ctx, message, strlen(message)); unsigned int sig_len = ECDSA_size(key); unsigned char *sig = (unsigned char *) malloc(sig_len); ECDSA_sign(0, (const unsigned char *) EVP_MD_CTX_md(ctx), EVP_MD_CTX_size(ctx), sig, &sig_len, (EC_KEY *) priv_key); // 验签 int result = ECDSA_verify(0, (const unsigned char *) EVP_MD_CTX_md(ctx), EVP_MD_CTX_size(ctx), sig, sig_len, (EC_KEY *) pub_key); printf("Verify result: %d\n", result); // 释放资源 free(sig); EVP_MD_CTX_free(ctx); EC_KEY_free(key); return 0; } ``` 在上面的代码中,我们首先使用 OpenSSL 库来实现 ECDSA。然后使用 EC_KEY_new_by_curve_name 函数生成公私钥对,并且使用 EVP_sha256 算法进行加签验签。最后,我们使用 ECDSA_verify 函数对签名进行验签,并且输出验签结果。 希望我的回答能够帮到您,如有任何疑问,请随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值