AES算法工具类:
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.7.18version>
dependency>
扒拉过去直接使用:
/**
* @author zqh
*/
public class AESUtil {
/** 加密
* @param encryptKey 密钥
* @param content 加密内容
* @return
*/
public static String encryptAES(String encryptKey, String content){
String finalKey = toMakeKey(encryptKey, 16, "0");
SymmetricCrypto aes = getAES(finalKey);
byte[] encryptContent = aes.encrypt(content);
String encode = Base64.encode(encryptContent);
return encode;
}
/** AES解密
* @param encryptKey 密钥
* @param content Base64编码的解密内容
* @return 原文
*/
public static String decryptAES(String encryptKey, String content) {
String finalKey = toMakeKey(encryptKey, 16, "0");
SymmetricCrypto aes = getAES(finalKey);
byte[] decodeBytes = Base64.decode(content);
byte[] decrypt = aes.decrypt(decodeBytes);
return new String(decrypt, Charset.forName("UTF-8"));
}
private static SymmetricCrypto getAES(String encryptKey) {
byte[] encodedKey = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue(), encryptKey.getBytes(StandardCharsets.UTF_8)).getEncoded();
return new SymmetricCrypto(SymmetricAlgorithm.AES, encodedKey);
}
/**
* 密钥key ,默认补的数字,补全16位数,以保证安全补全至少16位长度,android和ios对接通过
* @param key 密钥key
* @param length 密钥应有的长度
* @param text 默认补的文本
* @return 密钥
*/
private static String toMakeKey(String key, int length, String text) {
// 获取密钥长度
int strLen = key.length();
// 判断长度是否小于应有的长度
if (strLen < length) {
// 补全位数
StringBuilder builder = new StringBuilder();
// 将key添加至builder中
builder.append(key);
// 遍历添加默认文本
for (int i = 0; i < length - strLen; i++) {
builder.append(text);
}
// 赋值
key = builder.toString();
}else {
key = key.substring(0,16);
}
return key;
}
public static void main(String[] args) {
String content = "1";
String key = "appiron";
String encryptAES = encryptAES(key, content);
String decryptAES = decryptAES(key, encryptAES);
System.out.println(decryptAES);
}
}
/**
* @author zqh
*/
public class Sha1Util {
private static final String MAC_NAME = "HmacSHA1";
private static final String ENCODING = "UTF-8";
public static byte[] HmacSHA1Encrypt(String encryptText, String encryptKey) {
byte[] data;
try {
data = encryptKey.getBytes(ENCODING);
// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
// 生成一个指定 Mac 算法 的 Mac 对象
Mac mac = Mac.getInstance(MAC_NAME);
// 用给定密钥初始化 Mac 对象
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
// 完成 Mac 操作
return mac.doFinal(text);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
}
RSA解密
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcpkix-jdk15onartifactId>
<version>1.70version>
dependency>
<dependency>
<groupId>org.bouncycastlegroupId>
<artifactId>bcprov-jdk15onartifactId>
<version>1.70version>
dependency>
package com.appiron.emm.mdm.util;
/**
* @author lxs
* @PackageName:com.appiron.emm.job.test
* @ClassName:Pcks7EncryptOrDecryptUtil
* @Description:
* @date 2022/1/6 15:19
*/
public class Pcks7EncryptOrDecryptUtil {
private static final String PRIVATE_KEY_PATH = "C:\\Users\\Administrator\\Desktop\\apple\\1_pri.pem";
private static final String PRIVATE_KEY_PASSWORD="123456";
public static final String PUBLIC_KEY_PATH="C:\\Users\\Administrator\\Desktop\\apple\\1.cer";
private static PrivateKey PRIVATE_KEY = null;
private static RSAPublicKey PUBLIC_KEY = null;
private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void main(String[] args) throws Exception {
// String sendConent="3.0 161018173004 764764000001350 R THBPOps180808153209 0.01 E8CCDCDBDBB7428CF0CC9F06AB30B595067F4C89 ";
// String rsaPubEncrypt = encryptByRsaPub(PUBLIC_KEY_PATH,sendConent,"utf-8");//加密数据
// System.out.println(rsaPubEncrypt);
// System.out.println(decryptByContent(rsaPubEncrypt, PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD)); //解密数据
//第三方返回的数据
String encryptContent = "MIAGCSqGSIb3DQEHA6CAMIACAQAxggFrMIIBZwIBADBPMEoxFjAUBgNVBAMMDUVsdmlzIFl1ZW4gQ0ExCzAJBgNVBAYTAkNOMSMwIQYJKoZIhvcNAQkBFhRydWFuNTY2MTcxNDJAMTYzLmNvbQIBAjANBgkqhkiG9w0BAQEFAASCAQB1FpgG2PdfUQLB3Axj4tph6qtGN+kBFKDBJqaYou5OL+ksWmQKojZEvdVPSJhE2RdvHaaknZ/o/slY5i2hqAKWyeKhCP9jjvJKtIlyZ2thGxqNxhvRFUTUkfQ1kceAvBbjnc2PuF6okJw1e6ccIYv0mqWXekJl1tF/xZkUQrmLFjb0m710lVStJIrm8QSYCaJSunR5+OXkQOV/NS4/h1TJAM6VWpMQqF2AC1tupN8kDRYG/gRHpqQNi3VeDbQF0p2+O/fUpVEYVPl7u+ALVNXcYx98yiWrLfaF/WKeOHpUxVeNbzcvkxw0EC2fMfGPQ4FI9m/vOipQkBAzkpWVZ9cAMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEBeuFeAK5qACNT38rimx4+6ggASCAgD1VTm/gDb6+6qTR7coM4NjDedwfalZ+ZF0w0iR754rSP8G/eA7THtNY+AgdLuTdDs6FR7K6OMununDqo7dvoVX9j5lH0wci1YZoE3wjZHqe2GDC1sDxGOtnMAUH6t93/kqRmdVBGIiuooi8X1lVUbdJtbye/ZfnpnuBRHYb1KW5bMhFGKbzyAmZVKybEysvyxge/1QM+8U5LQpCIAZlY0WdZ/PkW9Df5ZgwZwGFDe6QuNwtQ1th4OodD6hRHBtklasFgwj5dhl3nmLWu0qfG5tUeHj9xxrSGcCuMElBceLhCHkWcwANoOMpDjmNOmYtKlUdYexPzXm6i5r3J+uYNWxxIlSbu/3CQysjb6q1lr7G+YbbABNCr78uC7T6nVDtKhNhbO1zFTqnrU5zYdlbDhZjxgmr1+1kx/0GDfSwmba7R/OK+72U8P6FUpLReJQmFnfmpzsIw143UnOHzIdyl3nIHeyT4iN3qzDDP1O0gS4Bt+IKhSRdJbz47eI3Zh9GJSnOKXPRyuGdThmDGM/lqzOJ9bXdx9CE4Iu+U8JssdToM7KE8c6UlRBlEh+lhrJZ64x7Su6bPJOq+Zu84cu8iFVvv8oW4f6Pjngurs4d3GUKOV+2BPzbu2Bw/tgRxPmKuS38vlatPZOgjj8+jePuOhYFxcOpyLAkd5FZW2AU5+zYgAAAAAAAAAAAAA=";
System.out.println(decryptByContent(encryptContent, PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD));
}
/**
* 使用私钥加密
*/
public static String encryptByRsaPub(String content) {
return encryptByRsaPub( PUBLIC_KEY_PATH,content,"utf-8");
}
/**
* 使用私钥加密
*/
public static String encryptByRsaPub(String publicKeyPath , String content,String charSet) {
try {
X509Certificate cert = getX509Certificate(publicKeyPath);
//添加数字信封
CMSTypedData msg = new CMSProcessableByteArray(content.getBytes(charSet));
CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(
cert).setProvider("BC"));
CMSEnvelopedData ed = edGen.generate(msg,
new JceCMSContentEncryptorBuilder(PKCSObjectIdentifiers.rc4)
.setProvider("BC").build());
String rslt = new String(Base64.getEncoder().encode(ed.getEncoded()));
System.out.println(rslt);
return rslt;
} catch (CertificateEncodingException | CMSException | IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 使用公钥解密
* @param encryptContent 比如:MIICEQYJKoZIhvcNAQcDoIICAjCCAf4CAQAxggFAMIIBPAIBADAkMBYxFDASBgNVBAMTC......
* @param privatePemKeyPath xxxx.pem
* @param privatePemKeyPassword
* @return
*/
public static String decryptByContent(String encryptContent,String privatePemKeyPath,String privatePemKeyPassword) {
return decryptByContent(encryptContent,getPrivateKey(privatePemKeyPath, privatePemKeyPassword));
}
public static String decryptByContent(String encryptContent,PrivateKey privateKey) {
return decryptByContent(Base64.getDecoder().decode(encryptContent),privateKey);
}
public static String decryptByContent(String encryptContent) {
return decryptByContent(Base64.getDecoder().decode(encryptContent),getPrivateKey(PRIVATE_KEY_PATH, PRIVATE_KEY_PASSWORD));
}
public static String decryptByContent(byte[] encryptContent,PrivateKey privateKey) {
try {
CMSEnvelopedDataParser cmsEnvelopedDataParser = new CMSEnvelopedDataParser(encryptContent);
Collection<RecipientInformation> recInfos = cmsEnvelopedDataParser.getRecipientInfos().getRecipients();
Iterator<RecipientInformation> recipientIterator = recInfos.iterator();
if (recipientIterator.hasNext()) {
RecipientInformation recipientInformation = (RecipientInformation) recipientIterator.next();
JceKeyTransEnvelopedRecipient jceKeyTransEnvelopedRecipient = new JceKeyTransEnvelopedRecipient(privateKey);
byte[] contentBytes = recipientInformation.getContent(jceKeyTransEnvelopedRecipient);
String decryptContent = new String(contentBytes);
return decryptContent;
}
} catch (CMSException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static PrivateKey getPrivateKey(String pemFilePath, String password){
if(PRIVATE_KEY != null) {
return PRIVATE_KEY;
}
Security.addProvider(new BouncyCastleProvider());
KeyPair kp;
try{
kp = (KeyPair)initKeyPair(new File(pemFilePath), password.toCharArray());
PrivateKey privateKey = kp.getPrivate();
return (PRIVATE_KEY = privateKey);
}catch(Exception e){
e.printStackTrace();
}
return null;
}
public static KeyPair initKeyPair(File pemFile, char[] password) throws Exception{
PEMParser pemParser = new PEMParser(new FileReader(pemFile));
Object object = pemParser.readObject();
pemParser.close();
PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
//获得密钥对
KeyPair kp = null;
if(object instanceof PEMEncryptedKeyPair){
kp = converter.getKeyPair(((PEMEncryptedKeyPair)object).decryptKeyPair(decProv));
}else{
kp = converter.getKeyPair((PEMKeyPair)object);
}
return kp;
}
public static RSAPublicKey getRSAPublicKey(String crtFileName) {
if(PUBLIC_KEY != null) {
return PUBLIC_KEY;
}
return (PUBLIC_KEY = (RSAPublicKey) getX509Certificate(crtFileName).getPublicKey());
}
/**
* 获取公钥
*/
public static X509Certificate getX509Certificate(String crtFileName) {
try {
CertificateFactory certificatefactory;
X509Certificate cert;
// 使用公钥对对称密钥进行加密 //若此处不加参数 "BC" 会报异常:CertificateException -
certificatefactory = CertificateFactory.getInstance("X.509", "BC");
// 读取.crt文件;你可以读取绝对路径文件下的crt,返回一个InputStream(或其子类)即可。
InputStream bais = new FileInputStream(crtFileName);
cert = (X509Certificate) certificatefactory.generateCertificate(bais);
return cert;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static String byteArrayToString(byte[] data) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < data.length; i++) {
// 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
// 取出字节的低四位 作为索引得到相应的十六进制标识符
stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
if (i < data.length - 1) {
stringBuilder.append(' ');
}
}
return stringBuilder.toString();
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/** * Convert char to byte * @param c char * @return byte */
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
}
一些认证信息,
{
”consumer_key”: ”CK_00fadb3d36c6094cf479838455321b7c”,
”consumer_secret”: ”CS_5fb17e5676db0cf875211937e5166d0f662ea1f9”,
”access_token”: ”AT_O2109279022Oe03b641fd6f07d7face7894211d521fd8bef09c3O137392”,
”access_secret”: ”AS_837c228d968ff303837086a5a54be645314ef755”
”access_token_expiry”: ”2013-09-09T02:24:28Z”
}
需要发送一个GET请求, 请求头中,有一个oauth_signature=”wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D”
字段, 是需要通过计算得出的。
GET /session HTTP/1.1
Authorization: OAuth realm=”ADM”,
oauth_consumer_key=”CK_00fadb3d36c6094cf479838455321b7c”,
2019-03-25 | Copyright © 2019 Apple Inc. All Rights Reserved.
99
oauth_token=”AT_O2109279022Oe03b641fd6f07d7face7894211d521fd8bef09c3O137392”,
oauth_signature_method=”HMAC-SHA1”,
oauth_signature=”wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D”,
oauth_timestamp=”137131200”,
oauth_nonce=”4572616e48616d6d65724c61686176”,
oauth_version=”1.0”
总体流程:
private String getOauthSignature(String authTokenUrl, JSONObject abmToken, String nonce, long timeStamp) {
StringBuilder paramBuilder = new StringBuilder();
paramBuilder.append(CodeConstants.OAUTH_CONSUMER_KEY + CodeConstants.EQUAL_STR);
paramBuilder.append(abmToken.getStr(CodeConstants.CONSUMER_KEY));
paramBuilder.append(CodeConstants.AND_STR + CodeConstants.OAUTH_NONCE_KEY + CodeConstants.EQUAL_STR);
paramBuilder.append(nonce);
paramBuilder.append(CodeConstants.AND_STR + CodeConstants.OAUTH_SIGNATURE_METHOD_KEY + CodeConstants.EQUAL_STR);
paramBuilder.append(CodeConstants.OAUTH_SIGNATURE_METHOD);
paramBuilder.append(CodeConstants.AND_STR + CodeConstants.OAUTH_TIMESTAMP_KEY +CodeConstants.EQUAL_STR);
paramBuilder.append(timeStamp);
paramBuilder.append(CodeConstants.AND_STR + CodeConstants.OAUTH_TOKEN_KEY + CodeConstants.EQUAL_STR);
paramBuilder.append(abmToken.getStr(CodeConstants.ACCESS_TOKEN));
paramBuilder.append(CodeConstants.AND_STR + CodeConstants.OAUTH_VERSION_KEY + CodeConstants.EQUAL_STR);
paramBuilder.append(CodeConstants.OAUTH_VERSION);
String encodeKey = abmToken.getStr(CodeConstants.CONSUMER_SECRET) + CodeConstants.AND_STR + abmToken.getStr(CodeConstants.ACCESS_SECRET);
try {
//1.对 HTTP请求路径 进行URL编码
String encodeUrl = URLEncoder.encode(authTokenUrl, CodeConstants.CHARSET_UTF_8);
//2. 对参数 进行URL编码
String encodeParam = URLEncoder.encode(paramBuilder.toString(), CodeConstants.CHARSET_UTF_8);
//3 拼接加密的基础字符串
String waitSha1EncodeStr = CodeConstants.METHOD_OF_GET + CodeConstants.AND_STR + encodeUrl + CodeConstants.AND_STR + encodeParam;
//4. 以签名基本字符串waitSha1EncodeStr作为文本, 消费者密钥和使用者密钥拼接后的字符串作为键,进行 HMAC-SHA1 加密
byte[] signBytes = Sha1Util.HmacSHA1Encrypt(waitSha1EncodeStr, encodeKey);
//5.base64编码
String encode = Base64.encode(signBytes);
//6. 在签名进行 URL编码
String result = URLEncoder.encode(encode, CodeConstants.CHARSET_UTF_8);
return result;
} catch (UnsupportedEncodingException e) {
LogUtils.error(log,"URL编码失败, 异常原因 : {}",e.getMessage());
}
return null;
}
//getOauthSignature
public final static String AND_STR = "&";
public final static String EQUAL_STR = "=";
public final static String OAUTH_CONSUMER_KEY = "oauth_consumer_key";
public final static String OAUTH_NONCE_KEY = "oauth_nonce";
public final static String OAUTH_SIGNATURE_METHOD_KEY = "oauth_signature_method";
public final static String OAUTH_SIGNATURE_KEY = "oauth_signature";
public final static String OAUTH_TIMESTAMP_KEY = "oauth_timestamp";
public final static String OAUTH_TOKEN_KEY = "oauth_token";
public final static String OAUTH_VERSION_KEY = "oauth_version";
public final static String CHARSET_UTF_8 = "UTF-8";
public final static String METHOD_OF_GET = "GET";