美文网首页
Java实现微信小程序登录的时候遇到的加密算法——sha1算法和

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

作者: YukunWen | 来源:发表于2018-11-14 18:59 被阅读139次

    引言

    在微信小程序登录的时候,如果用户之前都没有在相关的应用平台登录过(没有关注过开发者的公众号,没有微信登录过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加密的就比较少。这里展示博主使用的工具类。

    具体做法

    一、引入相应的包

    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.51</version>
    </dependency>
    

    二、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算法和

          本文链接:https://www.haomeiwen.com/subject/jxxsfqtx.html