ANDROID 问题整理 九

// 设置字符串指定长度,不足。末尾补=
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.

参考:(4条消息) java.security.cert.CertPathValidatorException: Trust anchor for certification path not found._wardenlzr的博客-CSDN博客 

/**
 * 忽略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小元子 – 博客园

用到的第三方库:

commons-net-3.3.zip

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));

AppInfoBean.zip

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值