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 + "×tamp=" + 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;
}
}