[8.5.0]
[myflow升级md5和加密校验]
This commit is contained in:
@@ -196,6 +196,10 @@ class UpgradeAppNetWorkManager private constructor() {
|
||||
Log.d(TAG,"MyFLow网络请求返回:${response}")
|
||||
SharedPrefsMgr.getInstance().putString(SharedPrefsConstants.APP_UPGRADE_CONTENT_MyFlow, if (info.result != null) response + "--vin:$tempVin" else "info.result == null --vin:$tempVin --type:$type")
|
||||
if (info.data != null) {
|
||||
if(info.data.encKey!=null&&info.data.encMd5!=null){
|
||||
val fileMd5 = AesEcbBase64Util.decryptFromBase64(info.data.encMd5,info.data.encKey)
|
||||
SharedPrefsMgr.getInstance().putString(SharedPrefsConstants.APP_UPGRADE_CONTENT_MYFLOW_CHECKMD5,"${info.data.fileAddr}_$fileMd5")
|
||||
}
|
||||
runCatching {
|
||||
block?.invoke(true, response)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.mogo.eagle.core.data.constants.MogoServicePaths
|
||||
import com.mogo.eagle.core.function.api.upgrade.IMoGoUpgradeProvider
|
||||
import com.mogo.eagle.core.function.call.base.CallerBase
|
||||
import com.elegant.utils.UiThreadHandler
|
||||
import com.mogo.commons.constants.SharedPrefsConstants
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.data.obu.MogoObuConst
|
||||
import com.mogo.eagle.core.function.api.devatools.IMogoDevaToolsUpgradeListener
|
||||
import com.mogo.eagle.core.function.api.devatools.download.*
|
||||
@@ -172,6 +174,19 @@ class UpgradeManager : IDownloadListener {
|
||||
}
|
||||
} else {
|
||||
val apk = File(localPath)
|
||||
val fileMd5WithUrl = SharedPrefsMgr.getInstance().getString(SharedPrefsConstants.APP_UPGRADE_CONTENT_MYFLOW_CHECKMD5)
|
||||
if(fileMd5WithUrl.startsWith(downloadUrl)) {
|
||||
Md5Util.getMd5FromFile(apk)?.let {fileMd5->
|
||||
if(fileMd5WithUrl.endsWith(fileMd5)){
|
||||
Logger.w(TAG, "md5校验通过...")
|
||||
}else{
|
||||
upgradeProvider?.recordTargetMd5CheckFailed("${StringUtils.getString(com.mogo.eagle.core.widget.R.string.module_core_compound_apk_md5_check_failed)}:[server_target_md5: ${fileMd5WithUrl}, file_md5: ${fileMd5}]")
|
||||
Logger.w(TAG, "md5校验失败...")
|
||||
// throw AssertionError("md5校验失败:[target:${patchInfo.targetMd5}]")
|
||||
throw AssertionError("${StringUtils.getString(com.mogo.eagle.core.widget.R.string.module_core_md5_check_failed)}:[target:${fileMd5WithUrl}]")
|
||||
}
|
||||
}
|
||||
}
|
||||
upgradeProvider?.recordInstallStart()
|
||||
withContext(Dispatchers.Main) {
|
||||
ApkInstaller.installApp(Utils.getApp(), apk) { code, reason ->
|
||||
|
||||
@@ -11,7 +11,9 @@ data class AppInfoMyFlow(
|
||||
val sn: String,
|
||||
val taskItemId: Int?,
|
||||
val versionCode: Int?,
|
||||
val versionNo: String
|
||||
val versionNo: String?,
|
||||
val encMd5: String?,
|
||||
val encKey: String?,
|
||||
){
|
||||
fun toAppInfo():AppInfo{
|
||||
val appInfo = AppInfo()
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.mogo.eagle.core.utilcode.util;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* Android平台专用的AES-ECB Base64加解密工具类
|
||||
* 适配Android的Base64工具类,优化异常处理
|
||||
*/
|
||||
public class AesEcbBase64Util {
|
||||
|
||||
// 测试方法(Android中建议在Activity/Fragment/ViewModel中调用)
|
||||
public static void testEncryptDecrypt() {
|
||||
String plainText = "41a59bbbb04b4f02b03672f1c177d4cc";
|
||||
String keyBase64 = "3OMe6b0jgPRIgngYxRdeGA==";
|
||||
|
||||
String encryptResult = AesEcbBase64Util.encryptToBase64(plainText, keyBase64);
|
||||
String decryptResult = AesEcbBase64Util.decryptFromBase64(encryptResult, keyBase64);
|
||||
|
||||
System.out.println("加密结果:" + encryptResult);
|
||||
System.out.println("解密结果:" + decryptResult);
|
||||
}
|
||||
|
||||
private static final String ALGO = "AES";
|
||||
private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
|
||||
private static final int KEY_LEN_BYTES = 16;
|
||||
|
||||
// 私有化构造方法,防止实例化
|
||||
private AesEcbBase64Util() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机的AES密钥(Base64编码)
|
||||
* @return 16字节密钥的Base64字符串
|
||||
*/
|
||||
public static String randomKeyBase64() {
|
||||
byte[] key = new byte[KEY_LEN_BYTES];
|
||||
new SecureRandom().nextBytes(key);
|
||||
// 替换为Android的Base64工具类,使用默认编码模式
|
||||
return Base64.encodeToString(key, Base64.NO_WRAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* AES加密并输出Base64编码结果
|
||||
* @param plaintext 明文
|
||||
* @param keyBase64 Base64编码的16字节AES密钥
|
||||
* @return Base64编码的密文
|
||||
* @throws IllegalArgumentException 密钥长度错误时抛出
|
||||
* @throws IllegalStateException 加密失败时抛出
|
||||
*/
|
||||
public static String encryptToBase64(String plaintext, String keyBase64) {
|
||||
try {
|
||||
// 解码Base64密钥
|
||||
byte[] key = Base64.decode(keyBase64, Base64.NO_WRAP);
|
||||
if (key.length != KEY_LEN_BYTES) {
|
||||
throw new IllegalArgumentException("无效的AES密钥长度: " + key.length + ",必须为16字节");
|
||||
}
|
||||
|
||||
// 初始化加密器
|
||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, ALGO));
|
||||
|
||||
// 处理空明文
|
||||
byte[] plainBytes = plaintext == null ? new byte[0] : plaintext.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] encryptBytes = cipher.doFinal(plainBytes);
|
||||
|
||||
// 加密结果转Base64
|
||||
return Base64.encodeToString(encryptBytes, Base64.NO_WRAP);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new IllegalStateException("AES加密失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Base64密文解密出明文
|
||||
* @param ciphertextBase64 Base64编码的密文
|
||||
* @param keyBase64 Base64编码的16字节AES密钥
|
||||
* @return 解密后的明文
|
||||
* @throws IllegalArgumentException 密钥长度错误时抛出
|
||||
* @throws IllegalStateException 解密失败时抛出
|
||||
*/
|
||||
public static String decryptFromBase64(String ciphertextBase64, String keyBase64) {
|
||||
try {
|
||||
// 解码Base64密钥
|
||||
byte[] key = Base64.decode(keyBase64, Base64.NO_WRAP);
|
||||
if (key.length != KEY_LEN_BYTES) {
|
||||
throw new IllegalArgumentException("无效的AES密钥长度: " + key.length + ",必须为16字节");
|
||||
}
|
||||
|
||||
// 解码Base64密文
|
||||
byte[] cipherBytes = Base64.decode(ciphertextBase64, Base64.NO_WRAP);
|
||||
|
||||
// 初始化解密器
|
||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, ALGO));
|
||||
|
||||
// 解密并转字符串
|
||||
byte[] plainBytes = cipher.doFinal(cipherBytes);
|
||||
return new String(plainBytes, StandardCharsets.UTF_8);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new IllegalStateException("AES解密失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ public class SharedPrefsConstants {
|
||||
public static final String HOST_ADDRESS_MyFLow = "host_address_update_myflow";
|
||||
public static final String APP_UPGRADE_CONTENT = "app_upgrade_content";
|
||||
public static final String APP_UPGRADE_CONTENT_MyFlow = "app_upgrade_content_myflow";
|
||||
public static final String APP_UPGRADE_CONTENT_MYFLOW_CHECKMD5 = "app_upgrade_content_myflow_check_md5";
|
||||
|
||||
public static final String APP_MAC = "app_mac";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user