save temporary

This commit is contained in:
CounterFire2023 2023-08-21 10:26:24 +08:00
parent 2fd2850fbd
commit 38957d9407
9 changed files with 256 additions and 66 deletions

View File

@ -5,6 +5,7 @@
<application
android:allowBackup="true"
android:requestLegacyExternalStorage="true"
android:name=".MainApplication"
android:icon="@mipmap/ic_launcher"
tools:replace="android:icon"
@ -46,7 +47,7 @@
<activity
android:name=".MainActivity"
android:screenOrientation="sensorLandscape"
android:theme="@style/CebgMainActivity"
android:theme="@style/CEBGThemeSelector"
android:launchMode="singleTask"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density"
android:resizeableActivity="false"
@ -105,7 +106,10 @@
android:theme="@style/WebViewTheme" />
<activity
android:name=".activity.BiometricActivity"
android:theme="@style/AppCompatTranslucent" />
android:theme="@style/DayNightActivity"
android:screenOrientation="sensorLandscape"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|layoutDirection"
/>
<activity
android:name=".activity.CustomCaptureActivity"
android:theme="@style/CaptureTheme" />
@ -203,6 +207,9 @@
<uses-feature
android:name="android.hardware.touchscreen.multitouch.distinct"
android:required="false" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@ -222,7 +229,6 @@
android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
@ -230,7 +236,10 @@
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<queries>
<package android:name="com.zhiliaoapp.musically" />
<package android:name="com.ss.android.ugc.trill" />

View File

@ -4,6 +4,8 @@ import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRON
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@ -35,7 +37,6 @@ import com.bytedance.sdk.open.tiktok.base.VideoObject;
import com.bytedance.sdk.open.tiktok.share.Share;
import com.cege.games.release.activity.BiometricActivity;
import com.cege.games.release.activity.CustomCaptureActivity;
import com.cege.games.release.activity.UnityPlayerActivity;
import com.cege.games.release.activity.WebPageActivity;
import com.cege.games.release.apple.AppleLoginActivity;
import com.cege.games.release.dialog.QRCodeActivity;
@ -67,10 +68,12 @@ import com.jc.jcfw.security.BiometricHelper;
import com.jc.jcfw.security.CryptographyManager;
import com.jc.jcfw.security.CryptographyManagerImpl;
import com.jc.jcfw.security.EncryptedData;
import com.jc.jcfw.util.Installation;
import com.jc.jcfw.util.JsonUtils;
import com.king.zxing.CameraScan;
import com.king.zxing.util.CodeUtils;
import com.king.zxing.util.LogUtils;
import com.unity3d.player.UnityPlayerActivity;
import net.openid.appauth.AppAuthConfiguration;
import net.openid.appauth.AuthState;
@ -147,6 +150,7 @@ public class MainActivity extends UnityPlayerActivity
private CountDownLatch mAuthIntentLatch = new CountDownLatch(1);
private TikTokOpenApi tiktokOpenApi;
public String getFunId() {
return funId;
}
@ -160,8 +164,8 @@ public class MainActivity extends UnityPlayerActivity
private FirebaseAnalytics mFirebaseAnalytics;
private AppEventsLogger fbLogger;
private BiometricPrompt.PromptInfo promptInfo;
private CryptographyManager cryptographyManager;
private AccountManager accountManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -204,8 +208,10 @@ public class MainActivity extends UnityPlayerActivity
PayClient payClient = PayClient.getInstance();
payClient.init(this);
promptInfo = BiometricHelper.createPromptInfo(this);
cryptographyManager = new CryptographyManagerImpl();
accountManager = AccountManager.get(this);
String id = Installation.id(this);
Log.i(TAG, "custom id:: " + id);
Log.i(TAG, "build info::" + Installation.getBuildInfo());
}
@Override
@ -285,7 +291,6 @@ public class MainActivity extends UnityPlayerActivity
// begin for unity
protected void onLoadNativeLibraries() {
try {
ApplicationInfo ai = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
@ -855,15 +860,12 @@ public class MainActivity extends UnityPlayerActivity
public void showPage(String fid, final String url) {
runOnUiThread(() -> {
Log.i(TAG, "show page: " + url);
// Intent intent = new Intent(this, WebPageActivity.class);
// intent.putExtra("url", url);
// Intent intent = new Intent(this, BiometricActivity.class);
// intent.putExtra("action", "encrypt");
// intent.putExtra("key", "1111");
// startActivity(intent);
Intent intent = new Intent(this, WebPageActivity.class);
intent.putExtra("url", url);
startActivity(intent);
// picker video file and share to tiktok
// openFileSelector();
authenticateToEncrypt("1111");
// authenticateToEncrypt("1111");
});
}
@ -910,32 +912,43 @@ public class MainActivity extends UnityPlayerActivity
startActivityForResult(intent, FILE_SELECTOR_CODE);
}
public void authenticateToEncrypt(String text) {
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager
.BIOMETRIC_SUCCESS) {
Cipher cipher = cryptographyManager.getInitializedCipherForEncryption("cebg_wallet_key");
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(MainActivity.this, _cipher -> {
EncryptedData encryptedData = cryptographyManager.encryptData(text, _cipher);
String encryptedString = Base64.encodeToString(encryptedData.getCiphertext(), Base64.DEFAULT);
String ivString = Base64.encodeToString(encryptedData.getInitializationVector(), Base64.DEFAULT);
Log.i(TAG, "encrypted msg: " + encryptedString);
Log.i(TAG, "encrypted iv: " + ivString);
});
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
}
}
public void authenticateToDecrypt(String text, String iv) {
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager
.BIOMETRIC_SUCCESS) {
byte[] ivData = Base64.decode(iv, Base64.DEFAULT);
byte[] textData = Base64.decode(text, Base64.DEFAULT);
Cipher cipher = cryptographyManager.getInitializedCipherForDecryption("cebg_wallet_key", ivData);
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(MainActivity.this, _cipher -> {
String decryptedMsg = cryptographyManager.decryptData(textData, _cipher);
Log.i(TAG, "decrypted msg: " + decryptedMsg);
});
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
}
public void passStorageState(String funid, String account) {
Log.i(TAG, "passStorageState with: " + account);
}
public void storagePass(String funid, String account, String password) {
Log.i(TAG, "storagePass with: " + account + " | " + password);
// save to account manage
final Account act = new Account(account, "main");
accountManager.addAccountExplicitly(act, password, null);
// runOnUiThread(() -> {
// Intent intent = new Intent(this, BiometricActivity.class);
// intent.putExtra("action", "encrypt");
// intent.putExtra("funid", funId);
// intent.putExtra("account", account);
// intent.putExtra("password", password);
// startActivity(intent);
// });
}
public void authGetStoragePass(String funid, String account) {
Log.i(TAG, "authGetStoragePass with: " + account);
Account[] accounts = accountManager.getAccounts();
for (Account act : accounts) {
Log.i(TAG, "authGetStoragePass account: " + act.name + " | " + act.type + " | " + accountManager.getPassword(act));
}
// runOnUiThread(() -> {
// Intent intent = new Intent(this, BiometricActivity.class);
// intent.putExtra("action", "decrypt");
// intent.putExtra("funid", funId);
// intent.putExtra("account", account);
// startActivity(intent);
// });
}
public void getClientId(String funid) {
Log.i(TAG, "getClientId ");
}
}

View File

@ -2,9 +2,11 @@ package com.cege.games.release.activity;
import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;
import static androidx.biometric.BiometricPrompt.ERROR_USER_CANCELED;
import android.content.Intent;
import android.os.Bundle;
import android.security.keystore.KeyInfo;
import android.util.Base64;
import android.util.Log;
@ -34,26 +36,36 @@ public class BiometricActivity extends AppCompatActivity {
cryptographyManager = new CryptographyManagerImpl();
Intent intent = getIntent();
String action = intent.getStringExtra("action");
String key = intent.getStringExtra("key");
String funId = intent.getStringExtra("funid");
String account = intent.getStringExtra("account");
// check if action is exists
// if ("encrypt".equals(action)) {
// authenticateToEncrypt(key);
// } else if ("decrypt".equals(action)) {
// String iv = intent.getStringExtra("iv");
// authenticateToDecrypt(key, iv);
// }
if ("encrypt".equals(action)) {
String password = intent.getStringExtra("password");
authenticateToEncrypt(funId, password);
} else if ("decrypt".equals(action)) {
String iv = intent.getStringExtra("iv");
authenticateToDecrypt(account, iv);
}
}
public void authenticateToEncrypt(String text) {
public void authenticateToEncrypt(String funId, String text) {
if (BiometricManager.from(this)
.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL) == BiometricManager.BIOMETRIC_SUCCESS) {
Cipher cipher = cryptographyManager.getInitializedCipherForEncryption("cebg_wallet_key");
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _cipher -> {
EncryptedData encryptedData = cryptographyManager.encryptData(text, _cipher);
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _result -> {
if (_result.isError()) {
if (_result.getErrcode() == ERROR_USER_CANCELED) {
// close current activity
finish();
}
return;
}
EncryptedData encryptedData = cryptographyManager.encryptData(text, _result.getCipher());
String encryptedString = Base64.encodeToString(encryptedData.getCiphertext(), Base64.DEFAULT);
String ivString = Base64.encodeToString(encryptedData.getInitializationVector(), Base64.DEFAULT);
Log.i(TAG, "encrypted msg: " + encryptedString);
Log.i(TAG, "encrypted iv: " + ivString);
finish();
});
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
}
@ -65,9 +77,17 @@ public class BiometricActivity extends AppCompatActivity {
byte[] ivData = Base64.decode(iv, Base64.DEFAULT);
byte[] textData = Base64.decode(text, Base64.DEFAULT);
Cipher cipher = cryptographyManager.getInitializedCipherForDecryption("cebg_wallet_key", ivData);
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _cipher -> {
String decryptedMsg = cryptographyManager.decryptData(textData, _cipher);
BiometricPrompt biometricPrompt = BiometricHelper.createBiometricPrompt(this, _result -> {
if (_result.isError()) {
if (_result.getErrcode() == ERROR_USER_CANCELED) {
// close current activity
finish();
}
return;
}
String decryptedMsg = cryptographyManager.decryptData(textData, _result.getCipher());
Log.i(TAG, "decrypted msg: " + decryptedMsg);
finish();
});
biometricPrompt.authenticate(promptInfo, new BiometricPrompt.CryptoObject(cipher));
}

View File

@ -34,7 +34,7 @@ public class JcSDK {
/**
* @Deprecated
* 不使用该方法, 直接由unity调用cpp方法
* 不使用该方法, 直接由unity调用cpp方法
* @param password
*/
public static void initWallet(String password) {
@ -58,8 +58,8 @@ public class JcSDK {
* check if metamask installed and jump to metamask
*
* @param url
* sample:
* "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri();
* sample:
* "https://metamask.app.link/wc?uri="+ExampleApplication.config.toWCUri();
*/
public static void toWallet(String url) {
@ -137,6 +137,7 @@ public class JcSDK {
}
payClient.queryProductList(funid, skuList);
}
public static void buyProduct(String funid, String productId, String orderId) {
Log.i(TAG, "buyProduct with: " + productId);
if (payClient == null) {
@ -153,6 +154,26 @@ public class JcSDK {
payClient.queryPurchase(funid);
}
public static void passStorageState(String funid, String account) {
Log.i(TAG, "passStorageState with: " + account);
MainActivity.app.passStorageState(funid, account);
}
public static void storagePass(String funid, String account, String password) {
Log.i(TAG, "storagePass with: " + account);
MainActivity.app.storagePass(funid, account, password);
}
public static void authGetStoragePass(String funid, String account) {
Log.i(TAG, "authGetStoragePass with: " + account);
MainActivity.app.authGetStoragePass(funid, account);
}
public static void getClientId(String funid) {
Log.i(TAG, "getClientId ");
MainActivity.app.getClientId(funid);
}
/**
* 回调至js
*/

View File

@ -19,6 +19,9 @@ import java.util.function.Consumer;
import javax.crypto.Cipher;
public class BiometricHelper {
public static final int ERROR_BIOMETRIC_FAIL = 100;
public static final int ERROR_BIOMETRIC_NO_CIPHER = 101;
private static final String TAG = BiometricHelper.class.getSimpleName();
public static BiometricPrompt.PromptInfo createPromptInfo(Context context) {
BiometricPrompt.PromptInfo promptInfo = new BiometricPrompt.PromptInfo.Builder()
@ -34,28 +37,26 @@ public class BiometricHelper {
return promptInfo;
}
public static BiometricPrompt createBiometricPrompt(FragmentActivity activity, Consumer<Cipher> func) {
public static BiometricPrompt createBiometricPrompt(FragmentActivity activity, Consumer<BiometricResult> func) {
Executor executor = ContextCompat.getMainExecutor(activity.getApplicationContext());
return new BiometricPrompt(activity, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Log.i(TAG, "Authentication error: " + errString);
public void onAuthenticationError(int errcode, @NonNull CharSequence errString) {
super.onAuthenticationError(errcode, errString);
Log.i(TAG, "Authentication error: " + errcode +" | "+ errString);
func.accept(new BiometricResult(errcode, (String) errString));
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Log.i(TAG, "Authentication failed!");
func.accept(new BiometricResult(ERROR_BIOMETRIC_FAIL, "Authentication failed"));
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.i(TAG, "Authentication succeeded!");
try {
func.accept(result.getCryptoObject().getCipher());
} catch (Exception e) {
Log.e("BiometricHelper", e.getMessage());
}
func.accept(new BiometricResult(result.getCryptoObject().getCipher()));
}
});
}

View File

@ -0,0 +1,61 @@
package com.jc.jcfw.security;
import androidx.annotation.Nullable;
import javax.crypto.Cipher;
public class BiometricResult {
private Cipher cipher;
private boolean error;
private int errcode;
private String errmsg;
public BiometricResult(Cipher cipher) {
if (null != cipher) {
this.cipher = cipher;
this.error = false;
} else {
this.error = true;
this.errcode = 101;
this.errmsg = "cipher is null";
}
}
public BiometricResult(int errcode, String errmsg) {
this.error = true;
this.errcode = errcode;
this.errmsg = errmsg;
}
@Nullable
public Cipher getCipher() {
return cipher;
}
public void setCipher(Cipher cipher) {
this.cipher = cipher;
}
public boolean isError() {
return error;
}
public void setError(boolean error) {
this.error = error;
}
public int getErrcode() {
return errcode;
}
public void setErrcode(int errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
}

View File

@ -5,15 +5,19 @@ import static android.security.keystore.KeyProperties.ENCRYPTION_PADDING_PKCS7;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.util.Log;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class CryptographyManagerImpl implements CryptographyManager {

View File

@ -0,0 +1,56 @@
package com.jc.jcfw.util;
import android.content.Context;
import android.os.Build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.UUID;
public class Installation {
private static String sID = null;
private static final String INSTALLATION = "INSTALLATION";
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
try {
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return sID;
}
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, "r");
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
}
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
}
public static String getBuildInfo() {
//这里选用了几个不会随系统更新而改变的值
StringBuffer buildSB = new StringBuffer();
buildSB.append(Build.BRAND).append("/");
buildSB.append(Build.PRODUCT).append("/");
buildSB.append(Build.DEVICE).append("/");
buildSB.append(Build.ID).append("/");
buildSB.append(Build.VERSION.INCREMENTAL);
return buildSB.toString();
// return Build.FINGERPRINT;
}
}

View File

@ -14,6 +14,11 @@
<item name="android:windowFullscreen">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
</style>
<style name="DayNightActivity" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
</style>
<style name="CebgMainActivity" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@android:color/black</item>
<item name="android:windowNoTitle">true</item>