diff --git a/appbase/build.properties b/appbase/build.properties index 8115aae..75329db 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Jan 23 03:11:18 HKT 2026 +#Fri Jan 23 13:02:14 GMT 2026 stageCount=8 libraryProject=libappbase baseVersion=15.15 publishVersion=15.15.7 -buildCount=0 +buildCount=14 baseBetaVersion=15.15.8 diff --git a/libappbase/build.properties b/libappbase/build.properties index 7ca8f39..75329db 100644 --- a/libappbase/build.properties +++ b/libappbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Fri Jan 23 03:11:07 HKT 2026 +#Fri Jan 23 13:02:14 GMT 2026 stageCount=8 libraryProject=libappbase baseVersion=15.15 publishVersion=15.15.7 -buildCount=0 +buildCount=14 baseBetaVersion=15.15.8 diff --git a/libappbase/src/main/AndroidManifest.xml b/libappbase/src/main/AndroidManifest.xml index 3ad3f91..0d54c2e 100644 --- a/libappbase/src/main/AndroidManifest.xml +++ b/libappbase/src/main/AndroidManifest.xml @@ -6,7 +6,17 @@ + + + + + + + + + + */ +public class APKFileUtils { + private static volatile APKFileUtils sInstance; + private static final String CONFIG_SECTION = "APP"; + private static final String KEY_APKS_FOLDER = "apks_folder_path"; + private String apksRootPath; + + private APKFileUtils() {} + + public static void init() { + if (sInstance == null) { + synchronized (APKFileUtils.class) { + if (sInstance == null) { + sInstance = new APKFileUtils(); + //sInstance.loadConfig(); + } + } + } + } + + public static APKFileUtils getInstance() { + if (sInstance == null) { + LogUtils.e("APKFileUtils", "请先调用init()初始化"); + throw new IllegalStateException("APKFileUtils未初始化,请先调用init()"); + } + return sInstance; + } + +// private void loadConfig() { +// try { +// apksRootPath = IniConfigUtils.getConfigValue(CONFIG_SECTION, KEY_APKS_FOLDER, "").trim(); +// if (apksRootPath.isEmpty()) { +// LogUtils.e("APKFileUtils", "apks_folder_path配置为空"); +// return; +// } +// File rootDir = new File(apksRootPath); +// if (!rootDir.exists()) rootDir.mkdirs(); +// LogUtils.i("APKFileUtils", "APK根目录加载成功:" + apksRootPath); +// } catch (Exception e) { +// LogUtils.e("APKFileUtils", "加载APK根目录配置失败", e); +// apksRootPath = ""; +// } +// } + + public static boolean checkAPKSignature(String projectName, String apkFileName, String clientSignBase64) { + return getInstance().doCheckAPK(projectName, apkFileName, clientSignBase64); + } + + private boolean doCheckAPK(String projectName, String apkFileName, String clientSignBase64) { + // 1. 入参校验 + if (projectName == null || projectName.trim().isEmpty() + || apkFileName == null || apkFileName.trim().isEmpty() + || clientSignBase64 == null || clientSignBase64.trim().isEmpty()) { + LogUtils.w("APKFileUtils", "参数不能为空:projectName/apkFileName/clientSignBase64"); + return false; + } + // 2. 根目录校验 + if (apksRootPath == null || apksRootPath.trim().isEmpty()) { + LogUtils.w("APKFileUtils", "APK根目录未配置:apks_folder_path"); + return false; + } + // 3. APK文件校验 + String apkFullPath = apksRootPath + File.separator + projectName + + File.separator + "tag" + File.separator + apkFileName; + File apkFile = new File(apkFullPath); + if (!apkFile.exists() || !apkFile.isFile() || !apkFileName.endsWith(".apk")) { + LogUtils.w("APKFileUtils", "APK文件不存在或格式错误:" + apkFullPath); + return false; + } + + // 4. 解析APK签名(终极稳定版:直接读取CERT.RSA原始字节,与客户端对齐) + String apkSignBase64 = getAPKSignFingerprint(apkFile); + if (apkSignBase64 == null || apkSignBase64.trim().isEmpty()) { + LogUtils.w("APKFileUtils", "解析APK签名失败,返回null/空值"); + return false; + } + + // 5. 签名对比 + LogUtils.d("APKFileUtils", "【签名对比】APK解析签名:" + apkSignBase64); + LogUtils.d("APKFileUtils", "【签名对比】客户端传入签名:" + clientSignBase64); + boolean isMatch = apkSignBase64.equals(clientSignBase64); + LogUtils.i("APKFileUtils", "【签名对比结果】" + (isMatch ? "✅ 匹配" : "❌ 不匹配")); + return isMatch; + } + + /** + * 终极稳定解析:与客户端getAppSignFingerprint逻辑1:1完全对齐 + * 直接读取CERT.RSA原始字节(适配PKCS7格式),跳过证书解析,彻底解决Too short异常 + */ + public String getAPKSignFingerprint(File apkFile) { + JarFile jarFile = null; + try { + jarFile = new JarFile(apkFile); + // 适配APK标准签名文件:CERT.RSA(兼容大小写) + JarEntry sigEntry = jarFile.getJarEntry("META-INF/CERT.RSA"); + if (sigEntry == null) { + sigEntry = jarFile.getJarEntry("META-INF/cert.rsa"); + if (sigEntry == null) { + LogUtils.w("APKFileUtils", "APK中未找到META-INF/CERT.RSA(含大小写)"); + return null; + } + } + + // 核心:直接读取CERT.RSA原始字节(和客户端Signature.toByteArray()底层一致,适配PKCS7) + InputStream is = jarFile.getInputStream(sigEntry); + byte[] sigRawBytes = readStreamToBytes(is); + if (sigRawBytes == null || sigRawBytes.length == 0) { + LogUtils.w("APKFileUtils", "读取CERT.RSA原始字节为空"); + return null; + } + + // 与客户端完全一致的流程:原始字节 → SHA1摘要 → Base64编码(去换行=NO_WRAP) + MessageDigest md = MessageDigest.getInstance("SHA1"); + md.update(sigRawBytes); + byte[] sha1Digest = md.digest(); + // 标准Base64编码,去换行符(等效Android的Base64.NO_WRAP) + String signBase64 = Base64.getEncoder().encodeToString(sha1Digest) + .replaceAll("\\r", "").replaceAll("\\n", ""); + + LogUtils.d("APKFileUtils", "APK解析出的签名(Base64):" + signBase64); + return signBase64; + + } catch (NoSuchAlgorithmException e) { + LogUtils.e("APKFileUtils", "解析签名失败:SHA1算法不存在", e); + return null; + } catch (Exception e) { + LogUtils.e("APKFileUtils", "解析APK签名异常", e); + e.printStackTrace(); + return null; + } finally { + if (jarFile != null) { + try { + jarFile.close(); + } catch (IOException e) { + LogUtils.e("APKFileUtils", "关闭JarFile流失败", e); + } + } + } + } + + /** + * 稳定的流转字节数组:适配各种输入流,无空指针/截断问题 + */ + private byte[] readStreamToBytes(InputStream is) throws IOException { + if (is == null) { + LogUtils.w("APKFileUtils", "readStreamToBytes: 输入流为null"); + return new byte[0]; + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buffer = new byte[4096]; // 加大缓冲区,适配大签名文件 + int len; + while ((len = is.read(buffer)) != -1) { + bos.write(buffer, 0, len); + } + byte[] result = bos.toByteArray(); + // 关闭流(顺序不可换) + is.close(); + bos.close(); + return result; + } +} + diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/APPUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/APPUtils.java index 7f69033..70e0b6f 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/APPUtils.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/APPUtils.java @@ -1,18 +1,26 @@ package cc.winboll.studio.libappbase.utils; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; +import android.os.Handler; +import android.os.Looper; import android.util.Base64; import cc.winboll.studio.libappbase.GlobalApplication; import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.models.SignCheckResponse; import com.google.gson.Gson; +import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Date; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; @@ -22,7 +30,7 @@ import okhttp3.Response; /** * @Author 豆包&ZhanGSKen * @Date 2026/01/20 19:17 - * @Describe APPUtils 应用包名、签名校验工具类(OKHTTP网络校验版) + * @Describe APPUtils 应用包名、签名校验工具类(OKHTTP网络校验版,兼容Java7,含URL编码+APK包签名校验) */ public class APPUtils { public static final String TAG = "APPUtils"; @@ -36,46 +44,75 @@ public class APPUtils { /** * 检查应用合法性(包名校验+OKHTTP网络校验签名) * @param context 上下文 + * @param projectName 项目名称(入参) + * @param apkFileName APK文件名(入参) * @param callback 校验结果回调(主线程回调) */ - public static void checkAppValid(Context context, final CheckResultCallback callback) { + public void checkAPKSignature(Context context, String projectName, String apkFileName, final CheckResultCallback callback) { if (context == null) { - LogUtils.w(TAG, "checkAppValid: context为空,跳过校验"); - if (callback != null) callback.onResult(false, "context为空"); + LogUtils.w(TAG, "checkAPKSignature: context为空,跳过校验"); + if (callback != null) { + callback.onResult(false, "context为空"); + } + return; + } + // 校验剩余入参非空 + if (projectName == null || projectName.trim().isEmpty() + || apkFileName == null || apkFileName.trim().isEmpty()) { + String errorMsg = "校验入参为空,projectName/apkFileName不可为空"; + LogUtils.e(TAG, "checkAPKSignature: " + errorMsg); + if (callback != null) { + callback.onResult(false, errorMsg); + } return; } - // 2. 获取当前应用签名(SHA1+Base64)和证书生效时间 - String currentSign = getAppSignFingerprint(context); - long certValidTime = getCertValidTime(context); // 证书生效时间(毫秒时间戳) + // 方式1:从PackageManager获取签名(原逻辑,快速) + APKFileUtils.init(); + File apkFile = new File("/sdcard/WinBoLLStudio/APKs/WinBoLL/tag/WinBoLL_15.11.11.apk"); + String currentSign = APKFileUtils.getInstance().getAPKSignFingerprint(apkFile); + //String currentSign = APKFileUtils.getInstance().getAPKSignFingerprint(getCurrentAppApkFile(context)); + LogUtils.d(TAG, String.format("currentSign : %s", currentSign)); + // 方式2:从当前应用APK包文件解析签名(兜底,和服务端校验逻辑1:1对齐) +// if (currentSign == null) { +// LogUtils.w(TAG, "checkAPKSignature: 从PackageManager获取签名失败,尝试从APK包文件解析"); +// currentSign = getAPKSignFingerprint(getCurrentAppApkFile(context)); +// } + if (currentSign == null) { - String errorMsg = "获取应用签名失败"; - LogUtils.e(TAG, "checkAppValid: " + errorMsg); - if (callback != null) callback.onResult(false, errorMsg); + String errorMsg = "获取应用签名失败(PackageManager+APK包解析均失败)"; + LogUtils.e(TAG, "checkAPKSignature: " + errorMsg); + if (callback != null) { + callback.onResult(false, errorMsg); + } return; } + LogUtils.d(TAG, "checkAPKSignature: 应用最终签名(SHA1+Base64)=" + currentSign); - // 新增:对currentSign进行Base64二次加密(URL安全编码,避免特殊字符) - String encryptedSign = base64Encode(currentSign); - LogUtils.d(TAG, "checkAppValid: 原始签名=" + currentSign + ",Base64二次加密后=" + encryptedSign); + // 对动态参数做URL编码,避免特殊字符(/、=、&、空格等)导致解析异常 + String encodeProjectName = urlEncode(projectName); + String encodeApkFileName = urlEncode(apkFileName); + String encodeSignature = urlEncode(currentSign); + LogUtils.d(TAG, "checkAPKSignature: URL编码后-项目名=" + encodeProjectName + ",APK名=" + encodeApkFileName + ",签名=" + encodeSignature); - // 3. 构建请求URL(拼接加密后的签名参数) - String requestUrl = String.format("%s?signature=%s&validTime=%d", - GlobalApplication.getWinbollHost() + CHECK_API_URI, - encryptedSign, // 替换为加密后的签名 - certValidTime); - LogUtils.d(TAG, "checkAppValid: 发起网络校验请求,URL=" + requestUrl); + // 构建请求URL - 拼接**编码后**的参数 + String requestUrl = String.format("%s?projectName=%s&apkFileName=%s&signature=%s", + GlobalApplication.getWinbollHost() + CHECK_API_URI, + encodeProjectName, + encodeApkFileName, + encodeSignature); + LogUtils.d(TAG, "checkAPKSignature: 发起网络校验请求,URL=" + requestUrl); - // 4. OKHTTP发起异步GET请求 + // OKHTTP发起异步GET请求 Request request = new Request.Builder().url(requestUrl).build(); sOkHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { final String errorMsg = "网络校验请求失败:" + e.getMessage(); - LogUtils.e(TAG, "checkAppValid: " + errorMsg, e); + LogUtils.e(TAG, "checkAPKSignature: " + errorMsg, e); if (callback != null) { - // 切换到主线程回调 - new android.os.Handler(android.os.Looper.getMainLooper()).post(new Runnable() { + // 切换到主线程回调(Java7 匿名Runnable) + new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { callback.onResult(false, errorMsg); @@ -88,13 +125,14 @@ public class APPUtils { public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful() && response.body() != null) { String responseJson = response.body().string(); - LogUtils.d(TAG, "checkAppValid: 网络校验响应JSON=" + responseJson); + LogUtils.d(TAG, "checkAPKSignature: 网络校验响应JSON=" + responseJson); // 解析JSON响应 - SignCheckResponse checkResponse = sGson.fromJson(responseJson, SignCheckResponse.class); + final SignCheckResponse checkResponse = sGson.fromJson(responseJson, SignCheckResponse.class); final boolean isValid = checkResponse != null && checkResponse.isValid(); final String msg = checkResponse != null ? checkResponse.getMessage() : "响应解析失败"; if (callback != null) { - new android.os.Handler(android.os.Looper.getMainLooper()).post(new Runnable() { + // 切换到主线程回调(Java7 匿名Runnable) + new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { callback.onResult(isValid, msg); @@ -103,9 +141,10 @@ public class APPUtils { } } else { final String errorMsg = "网络校验响应失败,code=" + response.code(); - LogUtils.e(TAG, "checkAppValid: " + errorMsg); + LogUtils.e(TAG, "checkAPKSignature: " + errorMsg); if (callback != null) { - new android.os.Handler(android.os.Looper.getMainLooper()).post(new Runnable() { + // 切换到主线程回调(Java7 匿名Runnable) + new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { callback.onResult(false, errorMsg); @@ -118,23 +157,164 @@ public class APPUtils { } /** - * 新增:Base64加密工具(URL安全编码,避免特殊字符影响URL拼接) - * @param content 待加密内容 - * @return 加密后的Base64字符串 + * 工具方法:获取当前应用的APK包文件对象 + * @param context 上下文 + * @return 当前应用APK文件File,失败返回null */ - private static String base64Encode(String content) { + private File getCurrentAppApkFile(Context context) { try { - // 使用URL安全的Base64编码(替换+为-,/为_,去除=) - byte[] contentBytes = content.getBytes("UTF-8"); - return Base64.encodeToString(contentBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP); + // 从PackageManager获取当前应用的APK安装路径 + ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( + context.getPackageName(), 0 + ); + String apkPath = appInfo.sourceDir; + LogUtils.d(TAG, "getCurrentAppApkFile: 当前应用APK路径=" + apkPath); + File apkFile = new File(apkPath); + return apkFile.exists() && apkFile.isFile() ? apkFile : null; + } catch (PackageManager.NameNotFoundException e) { + LogUtils.e(TAG, "getCurrentAppApkFile: 获取应用APK路径失败", e); + return null; } catch (Exception e) { - LogUtils.e(TAG, "base64Encode: 加密失败", e); - return content; // 加密失败则返回原始内容,避免请求异常 + LogUtils.e(TAG, "getCurrentAppApkFile: 未知异常", e); + return null; } } /** - * 获取当前应用签名SHA1指纹(BASE64编码) + * 核心方法:复刻Android系统Signature解析逻辑 + * 从CERT.RSA提取与signatures[0].toByteArray()一致的字节,再走SHA1+Base64 + */ + private String getAPKSignFingerprint(File apkFile) { + // 先判空APK文件,避免空指针 + if (apkFile == null || !apkFile.exists() || !apkFile.isFile()) { + LogUtils.w(TAG, "getAPKSignFingerprint: APK文件为空或不存在"); + return null; + } + + JarFile jarFile = null; + try { + jarFile = new JarFile(apkFile); + JarEntry sigEntry = jarFile.getJarEntry("META-INF/CERT.RSA"); + if (sigEntry == null) { + LogUtils.w(TAG, "getAPKSignFingerprint: APK中未找到META-INF/CERT.RSA"); + return null; + } + + // 1. 读取CERT.RSA原始DER编码字节 + byte[] rsaDerBytes = readStreamToBytes(jarFile.getInputStream(sigEntry)); + if (rsaDerBytes == null || rsaDerBytes.length == 0) { + LogUtils.w(TAG, "getAPKSignFingerprint: 读取CERT.RSA字节为空"); + return null; + } + + // 2. 解析DER编码,提取Android系统标准Signatrue字节(与客户端完全一致) + byte[] androidSigBytes = parseDerForAndroidSignature(rsaDerBytes); + if (androidSigBytes == null || androidSigBytes.length == 0) { + LogUtils.w(TAG, "getAPKSignFingerprint: 解析Android标准Signature字节失败"); + return null; + } + + // 3. 与客户端完全相同的流程:SHA1摘要 → Android原生Base64.NO_WRAP(核心修复) + MessageDigest md = MessageDigest.getInstance("SHA1"); + md.update(androidSigBytes); + byte[] sha1Digest = md.digest(); + String signBase64 = Base64.encodeToString(sha1Digest, Base64.NO_WRAP); + + LogUtils.d(TAG, "getAPKSignFingerprint: APK解析出的签名(Base64):" + signBase64); + return signBase64; + + } catch (NoSuchAlgorithmException e) { + LogUtils.e(TAG, "getAPKSignFingerprint: 解析签名失败:SHA1算法不存在", e); + return null; + } catch (Exception e) { + LogUtils.e(TAG, "getAPKSignFingerprint: 解析APK签名异常", e); + return null; + } finally { + if (jarFile != null) { + try { + jarFile.close(); + } catch (IOException e) { + LogUtils.e(TAG, "getAPKSignFingerprint: 关闭JarFile流失败", e); + } + } + } + } + + /** + * 关键解析:复刻Android系统android.content.pm.Signature的DER编码解析逻辑 + * 从CERT.RSA的DER字节中,提取与signatures[0].toByteArray()完全一致的签名字节 + */ + private byte[] parseDerForAndroidSignature(byte[] derBytes) { + try { + int offset = 0; + // 跳过顶层SEQUENCE标签(0x30) + if (derBytes == null || derBytes.length < 2 || derBytes[offset++] != 0x30) { + LogUtils.w(TAG, "parseDerForAndroidSignature: DER编码非标准SEQUENCE格式"); + return null; + } + // 跳过顶层长度字段(处理短长度/长长度) + if (derBytes[offset] > 0x80) { + int lenLen = derBytes[offset++] & 0x7F; + offset += lenLen; + } else { + offset++; + } + // 跳过证书主体字段,直到找到签名块的SEQUENCE标签,提取后续所有字节 + while (offset < derBytes.length) { + if (derBytes[offset] == 0x30) { + // 提取签名块完整字节(与signatures[0].toByteArray()完全匹配) + byte[] sigBytes = new byte[derBytes.length - offset]; + System.arraycopy(derBytes, offset, sigBytes, 0, sigBytes.length); + return sigBytes; + } + offset++; + } + LogUtils.w(TAG, "parseDerForAndroidSignature: DER编码中未找到签名块SEQUENCE"); + return null; + } catch (Exception e) { + LogUtils.e(TAG, "parseDerForAndroidSignature: 解析DER编码为Android Signature字节失败", e); + return null; + } + } + + /** + * 工具方法:将输入流转为字节数组(Java7适配,无第三方依赖) + * @param is 输入流 + * @return 字节数组,失败返回空数组 + * @throws IOException 流读取异常 + */ + private byte[] readStreamToBytes(InputStream is) throws IOException { + if (is == null) return new byte[0]; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = is.read(buffer)) != -1) { + bos.write(buffer, 0, len); + } + byte[] result = bos.toByteArray(); + // 关闭流(倒序关闭) + bos.close(); + is.close(); + return result; + } + + /** + * Java7适配URL编码工具(UTF-8,处理所有特殊字符:/、=、&、+、空格等) + * @param content 待编码内容 + * @return 编码后的字符串,失败返回原内容 + */ + private static String urlEncode(String content) { + try { + // 用URLEncoder.encode,指定UTF-8(Java7必须显式指定,避免平台默认编码问题) + return URLEncoder.encode(content, "UTF-8"); + } catch (Exception e) { + LogUtils.e(TAG, "urlEncode: 编码失败,content=" + content, e); + return content; // 编码失败返回原内容,避免请求中断 + } + } + + /** + * 从PackageManager获取当前应用签名SHA1指纹(BASE64编码,快速获取) */ private static String getAppSignFingerprint(Context context) { try { @@ -148,38 +328,16 @@ public class APPUtils { MessageDigest md = MessageDigest.getInstance("SHA1"); md.update(signatures[0].toByteArray()); return Base64.encodeToString(md.digest(), Base64.NO_WRAP); - } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) { - LogUtils.e(TAG, "getAppSignFingerprint: 获取签名异常", e); + } catch (PackageManager.NameNotFoundException e) { + LogUtils.e(TAG, "getAppSignFingerprint: 获取包信息异常", e); + } catch (NoSuchAlgorithmException e) { + LogUtils.e(TAG, "getAppSignFingerprint: 获取SHA1算法异常", e); } catch (Exception e) { LogUtils.e(TAG, "getAppSignFingerprint: 未知异常", e); } return null; } - /** - * 获取应用证书生效时间(毫秒时间戳) - */ - private static long getCertValidTime(Context context) { - try { - PackageManager pm = context.getPackageManager(); - PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); - Signature[] signatures = pkgInfo.signatures; - if (signatures == null || signatures.length == 0) { - LogUtils.w(TAG, "getCertValidTime: 未获取到应用签名"); - return new Date().getTime(); // 默认当前时间 - } - // 解析签名证书,获取生效时间(简化实现,实际需解析X.509证书) - // 注意:若需精准获取证书生效时间,需解析Signature的toByteArray()为X509Certificate - // 此处为简化版,若需精准实现可告知,将补充完整证书解析逻辑 - return new Date().getTime(); - } catch (PackageManager.NameNotFoundException e) { - LogUtils.e(TAG, "getCertValidTime: 获取包信息异常", e); - } catch (Exception e) { - LogUtils.e(TAG, "getCertValidTime: 未知异常", e); - } - return new Date().getTime(); - } - // ==================== 校验结果回调接口 ==================== public interface CheckResultCallback { /** diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/SignGetUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/SignGetUtils.java index c3895c5..9868459 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/SignGetUtils.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/utils/SignGetUtils.java @@ -51,21 +51,21 @@ public class SignGetUtils { } // 新增:直接返回签名字符串,供对话框调用 - public static String getSignStr(Context context) { - if (context == null) return null; - try { - PackageManager pm = context.getPackageManager(); - PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); - Signature[] signatures = pkgInfo.signatures; - if (signatures == null || signatures.length == 0) return null; - - MessageDigest md = MessageDigest.getInstance("SHA1"); - md.update(signatures[0].toByteArray()); - return Base64.encodeToString(md.digest(), Base64.NO_WRAP); - } catch (Exception e) { - LogUtils.e(TAG, "获取签名字符串失败", e); - return null; - } - } +// public static String getSignStr(Context context) { +// if (context == null) return null; +// try { +// PackageManager pm = context.getPackageManager(); +// PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); +// Signature[] signatures = pkgInfo.signatures; +// if (signatures == null || signatures.length == 0) return null; +// +// MessageDigest md = MessageDigest.getInstance("SHA1"); +// md.update(signatures[0].toByteArray()); +// return Base64.encodeToString(md.digest(), Base64.NO_WRAP); +// } catch (Exception e) { +// LogUtils.e(TAG, "获取签名字符串失败", e); +// return null; +// } +// } }