钉钉/微信开放平台加解密(钉钉/微信加密解密) 钉钉/微信AES 加密解密

1.钉钉开放平台加解密方法

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * 钉钉开放平台加解密方法
 * 在ORACLE官方网站下载JCE无限制权限策略文件
 * JDK6的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
 * JDK7的下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
 */
public class DingTalkEncryptor {
    private static final Charset CHARSET = Charset.forName("utf-8");
    private static final Base64 base64 = new Base64();
    private byte[] aesKey;
    private String token;
    private String corpId;
    private static final Integer AES_ENCODE_KEY_LENGTH = Integer.valueOf(43);
    private static final Integer RANDOM_LENGTH = Integer.valueOf(16);

    public DingTalkEncryptor(String token, String encodingAesKey, String corpId) throws DingTalkEncryptException {
        if(null != encodingAesKey && encodingAesKey.length() == AES_ENCODE_KEY_LENGTH.intValue()) {
            this.token = token;
            this.corpId = corpId;
            this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
        } else {
            throw new DingTalkEncryptException(Integer.valueOf(900004));
        }
    }

    public Map<String, String> getEncryptedMap(String plaintext, Long timeStamp, String nonce) throws DingTalkEncryptException {
        if(null == plaintext) {
            throw new DingTalkEncryptException(Integer.valueOf(900001));
        } else if(null == timeStamp) {
            throw new DingTalkEncryptException(Integer.valueOf(900002));
        } else if(null == nonce) {
            throw new DingTalkEncryptException(Integer.valueOf(900003));
        } else {
            String encrypt = this.encrypt(DingTalkUtils.getRandomStr(RANDOM_LENGTH.intValue()), plaintext);
            String signature = this.getSignature(this.token, String.valueOf(timeStamp), nonce, encrypt);
            Map<String, String> resultMap = new HashMap();
            resultMap.put("msg_signature", signature);
            resultMap.put("encrypt", encrypt);
            resultMap.put("timeStamp", String.valueOf(timeStamp));
            resultMap.put("nonce", nonce);
            return resultMap;
        }
    }

    public String getDecryptMsg(String msgSignature, String timeStamp, String nonce, String encryptMsg) throws DingTalkEncryptException {
        String signature = this.getSignature(this.token, timeStamp, nonce, encryptMsg);
        if(!signature.equals(msgSignature)) {
            throw new DingTalkEncryptException(Integer.valueOf(900006));
        } else {
            String result = this.decrypt(encryptMsg);
            return result;
        }
    }

    private String encrypt(String random, String plaintext) throws DingTalkEncryptException {
        try {
            byte[] randomBytes = random.getBytes(CHARSET);
            byte[] plainTextBytes = plaintext.getBytes(CHARSET);
            byte[] lengthByte = DingTalkUtils.int2Bytes(plainTextBytes.length);
            byte[] corpidBytes = this.corpId.getBytes(CHARSET);
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
            byteStream.write(randomBytes);
            byteStream.write(lengthByte);
            byteStream.write(plainTextBytes);
            byteStream.write(corpidBytes);
            byte[] padBytes = PKCS7Padding.getPaddingBytes(byteStream.size());
            byteStream.write(padBytes);
            byte[] unencrypted = byteStream.toByteArray();
            byteStream.close();
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(this.aesKey, 0, 16);
            cipher.init(1, keySpec, iv);
            byte[] encrypted = cipher.doFinal(unencrypted);
            String result = base64.encodeToString(encrypted);
            return result;
        } catch (Exception var15) {
            throw new DingTalkEncryptException(Integer.valueOf(900007));
        }
    }

    private String decrypt(String text) throws DingTalkEncryptException {
        byte[] originalArr;
        byte[] networkOrder;
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(this.aesKey, 0, 16));
            cipher.init(2, keySpec, iv);
            networkOrder = Base64.decodeBase64(text);
            originalArr = cipher.doFinal(networkOrder);
        } catch (Exception var9) {
            throw new DingTalkEncryptException(Integer.valueOf(900008));
        }

        String plainText;
        String fromCorpid;
        try {
            byte[] bytes = PKCS7Padding.removePaddingBytes(originalArr);
            networkOrder = Arrays.copyOfRange(bytes, 16, 20);
            int plainTextLegth = DingTalkUtils.bytes2int(networkOrder);
            plainText = new String(Arrays.copyOfRange(bytes, 20, 20 + plainTextLegth), CHARSET);
            fromCorpid = new String(Arrays.copyOfRange(bytes, 20 + plainTextLegth, bytes.length), CHARSET);
        } catch (Exception var8) {
            throw new DingTalkEncryptException(Integer.valueOf(900009));
        }

        if(!fromCorpid.equals(this.corpId)) {
            throw new DingTalkEncryptException(Integer.valueOf(900010));
        } else {
            return plainText;
        }
    }

    public String getSignature(String token, String timestamp, String nonce, String encrypt) throws DingTalkEncryptException {
        try {
            String[] array = new String[]{token, timestamp, nonce, encrypt};
            Arrays.sort(array);
            StringBuffer sb = new StringBuffer();

            for(int i = 0; i < 4; ++i) {
                sb.append(array[i]);
            }

            String str = sb.toString();
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();
            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";

            for(int i = 0; i < digest.length; ++i) {
                shaHex = Integer.toHexString(digest[i] & 255);
                if(shaHex.length() < 2) {
                    hexstr.append(0);
                }

                hexstr.append(shaHex);
            }

            return hexstr.toString();
        } catch (Exception var13) {
            throw new DingTalkEncryptException(Integer.valueOf(900006));
        }
    }
}

2.钉钉jsapi签名工具类

import java.security.MessageDigest;
import java.util.Formatter;

/**
 * 钉钉jsapi签名工具类
 */

public class DingTalkJsApiSingnature {
    public DingTalkJsApiSingnature() {
    }

    public static String getJsApiSingnature(String url, String nonce, Long timeStamp, String jsTicket) throws DingTalkEncryptException {
        String plainTex = "jsapi_ticket=" + jsTicket + "&noncestr=" + nonce + "&timestamp=" + timeStamp + "&url=" + url;
        String signature = "";

        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(plainTex.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
            return signature;
        } catch (Exception var7) {
            throw new DingTalkEncryptException(Integer.valueOf(900006));
        }
    }

    private static String byteToHex(byte[] hash) {
        Formatter formatter = new Formatter();
        byte[] var2 = hash;
        int var3 = hash.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            byte b = var2[var4];
            formatter.format("%02x", new Object[]{Byte.valueOf(b)});
        }

        String result = formatter.toString();
        formatter.close();
        return result;
    }

    public static void main(String[] args) throws Exception {
        String url = "http://10.62.53.138:3000/jsapi";
        String nonce = "abcdefgh";
        Long timeStamp = Long.valueOf(1437027269927L);
        String tikcet = "zHoQdGJuH0ZDebwo7sLqLzHGUueLmkWCC4RycYgkuvDu3eoROgN5qhwnQLgfzwEXtuR9SDzh6BdhyVngzAjrxV";
        System.err.println(getJsApiSingnature(url, nonce, timeStamp, tikcet));
    }
}

3.PKCS7算法的加密填充

import java.nio.charset.Charset;
import java.util.Arrays;

/*
 * PKCS7算法的加密填充
 */


public class PKCS7Padding {
    private static final Charset CHARSET = Charset.forName("utf-8");
    private static final int BLOCK_SIZE = 32;

    public PKCS7Padding() {
    }

    public static byte[] getPaddingBytes(int count) {
        int amountToPad = 32 - count % 32;
        if(amountToPad == 0) {
            amountToPad = 32;
        }

        char padChr = chr(amountToPad);
        String tmp = new String();

        for(int index = 0; index < amountToPad; ++index) {
            tmp = tmp + padChr;
        }

        return tmp.getBytes(CHARSET);
    }

    public static byte[] removePaddingBytes(byte[] decrypted) {
        int pad = decrypted[decrypted.length - 1];
        if(pad < 1 || pad > 32) {
            pad = 0;
        }

        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
    }

    private static char chr(int a) {
        byte target = (byte)(a & 255);
        return (char)target;
    }
}

4.钉钉开放平台加解密异常类



import java.util.HashMap;
import java.util.Map;

/**
 * 钉钉开放平台加解密异常类
 */
public class DingTalkEncryptException extends Exception {
    /**成功**/
    public static final int SUCCESS = 0;
    /**加密明文文本非法**/
    public final static int  ENCRYPTION_PLAINTEXT_ILLEGAL = 900001;
    /**加密时间戳参数非法**/
    public final static int  ENCRYPTION_TIMESTAMP_ILLEGAL = 900002;
    /**加密随机字符串参数非法**/
    public final static int  ENCRYPTION_NONCE_ILLEGAL = 900003;
    /**不合法的aeskey**/
    public final static int AES_KEY_ILLEGAL = 900004;
    /**签名不匹配**/
    public final static int SIGNATURE_NOT_MATCH = 900005;
    /**计算签名错误**/
    public final static int COMPUTE_SIGNATURE_ERROR = 900006;
    /**计算加密文字错误**/
    public final static int COMPUTE_ENCRYPT_TEXT_ERROR  = 900007;
    /**计算解密文字错误**/
    public final static int COMPUTE_DECRYPT_TEXT_ERROR  = 900008;
    /**计算解密文字长度不匹配**/
    public final static int COMPUTE_DECRYPT_TEXT_LENGTH_ERROR  = 900009;
    /**计算解密文字corpid不匹配**/
    public final static int COMPUTE_DECRYPT_TEXT_CORPID_ERROR  = 900010;
    private static final long serialVersionUID = -7009381945707655052L;

    private static Map<Integer,String> msgMap = new HashMap<Integer,String>();
    static{
        msgMap.put(SUCCESS,"成功");
        msgMap.put(ENCRYPTION_PLAINTEXT_ILLEGAL,"加密明文文本非法");
        msgMap.put(ENCRYPTION_TIMESTAMP_ILLEGAL,"加密时间戳参数非法");
        msgMap.put(ENCRYPTION_NONCE_ILLEGAL,"加密随机字符串参数非法");
        msgMap.put(SIGNATURE_NOT_MATCH,"签名不匹配");
        msgMap.put(COMPUTE_SIGNATURE_ERROR,"签名计算失败");
        msgMap.put(AES_KEY_ILLEGAL,"不合法的aes key");
        msgMap.put(COMPUTE_ENCRYPT_TEXT_ERROR,"计算加密文字错误");
        msgMap.put(COMPUTE_DECRYPT_TEXT_ERROR,"计算解密文字错误");
        msgMap.put(COMPUTE_DECRYPT_TEXT_LENGTH_ERROR,"计算解密文字长度不匹配");
        msgMap.put(COMPUTE_DECRYPT_TEXT_CORPID_ERROR,"计算解密文字corpid或者suiteKey不匹配");
    }

    public Integer  code;
    public DingTalkEncryptException(Integer exceptionCode){
        super(msgMap.get(exceptionCode));
        this.code = exceptionCode;
    }
}

5.加解密工具类

package com.maycur.dingtalk.common.util.aes;

import java.util.Random;

/**
 * 加解密工具类
 */
public class DingTalkUtils {
    public DingTalkUtils() {
    }

    public static String getRandomStr(int count) {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();

        for(int i = 0; i < count; ++i) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }

        return sb.toString();
    }

    public static byte[] int2Bytes(int count) {
        byte[] byteArr = new byte[]{(byte)(count >> 24 & 255), (byte)(count >> 16 & 255), (byte)(count >> 8 & 255), (byte)(count & 255)};
        return byteArr;
    }

    public static int bytes2int(byte[] byteArr) {
        int count = 0;

        for(int i = 0; i < 4; ++i) {
            count <<= 8;
            count |= byteArr[i] & 255;
        }

        return count;
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值