// 设置字符串指定长度,不足。末尾补= public static String setStrLength(String par) { int length = 35; StringBuilder str = new StringBuilder(par); if (par.length() < length) { for (int i = 0; i < length - par.length(); i++) { str.append("="); } } return str.toString(); }
// 腾讯上架,空白包签名
jre 添加到系统环境变量中 jarsigner -verbose -keystore D:\AndroidStudioProjects\xxx\app\秘钥名称.jks -signedjar D:\AndroidStudioProjects\xxx\app\tap_sign.apk D:\AndroidStudioProjects\xxx\app\tap_unsign.apk 秘钥别名
// jre 添加到系统环境变量中
jarsigner -verbose -keystore D:\AndroidStudioProjects\xxx\app\秘钥名称.jks -signedjar D:\AndroidStudioProjects\xxx\app\tap_sign.apk D:\AndroidStudioProjects\xxx\app\tap_unsign.apk 秘钥别名
// 判断软件是否在后台
private void registerActivityLifecycleCallbacks() { // 放在 Application onCreate 中执行
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
mCount++;
if (!mFront) {
mFront = true;
L.e("AppContext------->处于前台");
CommonAppConfig.getInstance().setFrontGround(true);
}
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
mCount--;
if (mCount == 0) {
mFront = false;
L.e("AppContext------->处于后台");
CommonAppConfig.getInstance().setFrontGround(false);
}
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
// 后台启动页面设置
boolean allowed = isAllowed(this);
private boolean isAllowed(Context context) {
AppOpsManager ops = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
int op = 10021;
Method method = ops.getClass().getMethod("checkOpNoThrow", new Class[]{int.class, int.class, String.class});
Integer result = (Integer) method.invoke(ops, op, android.os.Process.myUid(), context.getPackageName());
return result == AppOpsManager.MODE_ALLOWED;
} catch (Exception e) {
Log.e("===============", "not support");
}
return false;
}
// java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
/**
* 忽略OKHttp所有证书验证(信任所有证书)添加到 Application 的 onCreate 方法中
*/
private void handleSSLHandshake1() {
try {
HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(null, null, (X509TrustManager) null);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
//其他配置
.build();
OkHttpUtils.initClient(okHttpClient);
//使用原生的Http请求
/*TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("TLS");
// trustAllCerts信任所有的证书
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});*/
} catch (Exception ignored) {
}
}
// rsa加密
public class RSAUtils {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小(如果秘钥是1024bit,解密最大块是128,如果秘钥是2048bit,解密最大块是256)
*/
private static final int MAX_DECRYPT_BLOCK = 128;
private static PrivateKey globalPrivateKey = null;
private static PublicKey globalPublicKey = null;
private static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4Gxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx8Gl56RjPjanjVQgylF6HK1Q//AAgdD94Ef2v+RVgnVDttFQBmLEjgtbmw9wLsynihaQNyxcwHQIDAQAB";
public static PublicKey getPublicByPublic(String publicKey) throws Exception {
if(globalPublicKey != null){
return globalPublicKey;
}
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509EncodedKeySpec ks = new X509EncodedKeySpec(Base64.decode(publicKey, NO_WRAP));
KeyFactory kf = KeyFactory.getInstance("RSA");
globalPublicKey = kf.generatePublic(ks);
return globalPublicKey;
}
// 返回加密后的数据,例如:返回加密后的密码
public static String encrypt(String data) throws Exception{
byte[] keyBytes = Base64.decode(PUBLIC_KEY, NO_WRAP);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] mi = cipher.doFinal(data.getBytes());
return Base64.encodeToString(mi, Base64.DEFAULT);
}
}
// RSA/RSA2 生成签名
参考:RSA/RSA2 进行签名和验签 – zyy小元子 – 博客园
用到的第三方库:
implementation 'com.google.code.gson:gson:2.8.6'
//网络
api 'com.zhy:okhttputils:2.6.2'
api 'com.squareup.okhttp3:okhttp:3.8.1'
api files('libs\\commons-net-3.3.jar')
调用
TreeMap<String, String> params = OkHttpUtil.getPublicParams();
params.put("method", 具体请求的接口/或者请求的参数);
params.put("sign", OkHttpUtil.signData(params));
public static TreeMap<String, String> getPublicParams() { // 添加参数
String serialNumber = getSerialNumber();
AppInfoBean appInfoBean = AppInfoBean.getAppInfoBean()
.setDeviceSn(serialNumber)
.save();
TreeMap<String, String> params = new TreeMap<>();
String privateKey = appInfoBean.getPrivateKey();
params.put("privateKey", privateKey);
params.put("charset", "utf-8"); // 请求使用的编码格式,如utf-8,gbk,gb2312等 // 示例值 utf-8
params.put("sign_type", "RSA2"); // 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和 RSA,推荐使用RSA2 // 示例值 RSA2
params.put("version", "BASE_URL_VERSION");
String timeStamp = DateUtil.timeStamp2Date3("" + System.currentTimeMillis());
params.put("timestamp", timeStamp);
params.put("biz_content", "{\"deviceSn\":\"" + appInfoBean.getDeviceSn()
+ "\",\"softwareVersion\":\"" + OkHttpUtil.softVersion()
+ "\"}");
return params;
}
public static String signData(TreeMap<String, String> publicParams) { // 获取加密字符串
String sha256RSA = rsaSign(OkHttpUtil.paramsSortMap(publicParams), publicParams);
return sha256RSA;
}
/**
* 排序,返回 Map
* @param treeMap
* @return
*/
public static Map paramsSortMap(TreeMap<String, String> treeMap) {
Map map = new HashMap();
StringBuffer stringBuffer = new StringBuffer();
Iterator<Map.Entry<String, String>> it = treeMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
stringBuffer.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
map.put(entry.getKey(), entry.getValue());
}
return map;
}
// 注意导入的对应的开发包
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Map;
import java.util.TreeMap;
public class RSAUtils {
/**
* 2021年6月18日14:22:07
* RSA/RSA2 生成签名
* RSA最大解密密文大小(如果秘钥是1024bit,解密最大块是128,如果秘钥是2048bit,解密最大块是256)
*
* @param map 包含 sign_type、privateKey、charset
* @return
* @throws Exception
*/
private static final String SIGN_TYPE_RSA2 = "RSA2";
private static final String SIGN_TYPE_RSA = "RSA";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
public static String rsaSign(Map map, TreeMap<String, String> paramsSortMap) {
String signedS = "签名错误";
try {
PrivateKey priKey = null;
Signature signature = null;
String signType = map.get("sign_type").toString();
String privateKey = PRIVATE_KEY // map.get("privateKey").toString();
String charset = map.get("charset").toString();
// String content = getSignContent(map);
String content = OkHttpUtil.paramsSort(paramsSortMap);
map.put("content", content);
System.out.println("请求参数生成的字符串为:" + content);
if (SIGN_TYPE_RSA.equals(signType)) {
priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
signature = Signature.getInstance(SIGN_ALGORITHMS);
} else if (SIGN_TYPE_RSA2.equals(signType)) {
priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
} else {
throw new Exception("不是支持的签名类型 : : signType=" + signType);
}
signature.initSign(priKey);
if (charset.isEmpty()) {
signature.update(content.getBytes());
} else {
signature.update(content.getBytes(charset));
}
byte[] signed = signature.sign();
signedS = new String(org.apache.commons.net.util.Base64.encodeBase64(signed));
} catch (Exception e) {
e.printStackTrace();
}
return signedS;
}
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
if (ins == null || algorithm.isEmpty()) {
return null;
}
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
byte[] encodedKey = readText(ins).getBytes();
encodedKey = org.apache.commons.net.util.Base64.decodeBase64(encodedKey);
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
private static String readText(InputStream ins) throws IOException {
Reader reader = new InputStreamReader(ins);
StringWriter writer = new StringWriter();
io(reader, writer, -1);
return writer.toString();
}
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static void io(Reader in, Writer out, int bufferSize) throws IOException {
if (bufferSize == -1) {
bufferSize = DEFAULT_BUFFER_SIZE >> 1;
}
char[] buffer = new char[bufferSize];
int amount;
while ((amount = in.read(buffer)) >= 0) {
out.write(buffer, 0, amount);
}
}
}
/***
* 获取设备的序列号
* @return
*/
public static String getSerialNumber() {
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception e) {
e.printStackTrace();
}
return serial;
}