Java实现微信小程序登录的时候遇到的加密算法——sha1算法和AES-128-CBC

引言

在微信小程序登录的时候,如果用户之前都没有在相关的应用平台登录过(没有关注过开发者的公众号,没有微信登录过web端,app端),那要获取全平台唯一的unionId,就会遇到一个sha1验签和AES-128-CBC解密问题。然后微信很坑爹的给出的SDK中居然只有php,nodeJs,C++,python,没有给出java的demo。参考微信说明地址:
1.https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
2.https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserInfo.html

关于sha1的验签方法,网上其实有很多;同时AES-128-CBC解密也有很多,但是针对AES-128-CBC加密的就比较少。这里展示博主使用的工具类。

具体做法

一、引入相应的包


    org.bouncycastle
    bcprov-jdk15on
    1.51

二、AESDecryptUtil源代码展示

package com.yuxun.fantuan.framework.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Arrays;

/**
 * @author wyk on 2018/11/14
 */
@Slf4j
public class AESDecryptUtil {
    // 算法名称
    private static final String KEY_ALGORITHM = "AES";

    /**
     * 加解密算法/模式/填充方式
     */
    private static final String algorithmStr = "AES/CBC/PKCS7Padding";

    private static Key key;
    private static Cipher cipher;

    public static String encrypt(byte[] originalContent, byte[] encryptKey, byte[] ivByte) {
        try {
            encryptKey = Base64.decodeBase64(encryptKey);
            ivByte = Base64.decodeBase64(ivByte);

            init(encryptKey);
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivByte));
            byte[] encrypted = cipher.doFinal(originalContent);
            return new String(Base64.encodeBase64(encrypted),StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            log.error("AES加密算法出错",e);
        }
    }

    /**
     * 解密方法
     * @param encryptedDataStr
     * @param keyBytesStr
     * @param ivStr
     * @return
     */
    public static String decrypt(String encryptedDataStr, String keyBytesStr, String ivStr) {
        byte[] encryptedText = null;
        byte[] encryptedData = null;
        byte[] sessionkey = null;
        byte[] iv = null;

        try {
            sessionkey = Base64.decodeBase64(keyBytesStr);
            encryptedData = Base64.decodeBase64(encryptedDataStr);
            iv = Base64.decodeBase64(ivStr);

            init(sessionkey);
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            log.error("AES解密算法出错",e);
        }
        assert encryptedText != null;
        return new String(encryptedText,StandardCharsets.UTF_8);
    }

    public static void main(String[] args) {

        String content = "{\"phoneNumber\":\"18789536667\"}";
        String key = "9QJPlP2TyuDFH1A73pnGqg==";
        String iv = "SABdIDCax6u7H0f6OILGzw==";

        String encrptContent = AESDecryptUtil.encrypt(content.getBytes(),key.getBytes(),iv.getBytes());
        System.out.println(encrptContent);

        System.out.println(AESDecryptUtil.decrypt(encrptContent, key, iv));
    }
}

另外,顺便记录一下验证签名的sha1算法

String sha1Hex = DigestUtils.sha1Hex(miniLoginUserInfoDTO.getRawData()+sessionKey);

你可能感兴趣的:(Java实现微信小程序登录的时候遇到的加密算法——sha1算法和AES-128-CBC)