From 38957d94079b81a6506a3335f343bc5ec788486d Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:26:24 +0800 Subject: [PATCH] save temporary --- app/AndroidManifest.xml | 15 ++- .../com/cege/games/release/MainActivity.java | 91 +++++++++++-------- .../release/activity/BiometricActivity.java | 44 ++++++--- app/src/com/jc/jcfw/JcSDK.java | 27 +++++- .../com/jc/jcfw/security/BiometricHelper.java | 19 ++-- .../com/jc/jcfw/security/BiometricResult.java | 61 +++++++++++++ .../security/CryptographyManagerImpl.java | 4 + app/src/com/jc/jcfw/util/Installation.java | 56 ++++++++++++ res/values/styles.xml | 5 + 9 files changed, 256 insertions(+), 66 deletions(-) create mode 100644 app/src/com/jc/jcfw/security/BiometricResult.java create mode 100644 app/src/com/jc/jcfw/util/Installation.java diff --git a/app/AndroidManifest.xml b/app/AndroidManifest.xml index b1b25d8..ec4b8b0 100644 --- a/app/AndroidManifest.xml +++ b/app/AndroidManifest.xml @@ -5,6 +5,7 @@ + android:theme="@style/DayNightActivity" + android:screenOrientation="sensorLandscape" + android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|layoutDirection" + /> @@ -203,6 +207,9 @@ + @@ -222,7 +229,6 @@ android:name="android.permission.CAPTURE_VIDEO_OUTPUT" tools:ignore="ProtectedPermissions" /> - + + diff --git a/app/src/com/cege/games/release/MainActivity.java b/app/src/com/cege/games/release/MainActivity.java index b053e65..2f6fa72 100644 --- a/app/src/com/cege/games/release/MainActivity.java +++ b/app/src/com/cege/games/release/MainActivity.java @@ -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 "); + + } } \ No newline at end of file diff --git a/app/src/com/cege/games/release/activity/BiometricActivity.java b/app/src/com/cege/games/release/activity/BiometricActivity.java index 73d5f27..68b633f 100644 --- a/app/src/com/cege/games/release/activity/BiometricActivity.java +++ b/app/src/com/cege/games/release/activity/BiometricActivity.java @@ -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)); } diff --git a/app/src/com/jc/jcfw/JcSDK.java b/app/src/com/jc/jcfw/JcSDK.java index 9724ab3..2b8e9bb 100644 --- a/app/src/com/jc/jcfw/JcSDK.java +++ b/app/src/com/jc/jcfw/JcSDK.java @@ -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 */ diff --git a/app/src/com/jc/jcfw/security/BiometricHelper.java b/app/src/com/jc/jcfw/security/BiometricHelper.java index d7c41e6..3a40475 100644 --- a/app/src/com/jc/jcfw/security/BiometricHelper.java +++ b/app/src/com/jc/jcfw/security/BiometricHelper.java @@ -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 func) { + public static BiometricPrompt createBiometricPrompt(FragmentActivity activity, Consumer 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())); } }); } diff --git a/app/src/com/jc/jcfw/security/BiometricResult.java b/app/src/com/jc/jcfw/security/BiometricResult.java new file mode 100644 index 0000000..45b31a8 --- /dev/null +++ b/app/src/com/jc/jcfw/security/BiometricResult.java @@ -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; + } +} diff --git a/app/src/com/jc/jcfw/security/CryptographyManagerImpl.java b/app/src/com/jc/jcfw/security/CryptographyManagerImpl.java index f23443b..856aa7f 100644 --- a/app/src/com/jc/jcfw/security/CryptographyManagerImpl.java +++ b/app/src/com/jc/jcfw/security/CryptographyManagerImpl.java @@ -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 { diff --git a/app/src/com/jc/jcfw/util/Installation.java b/app/src/com/jc/jcfw/util/Installation.java new file mode 100644 index 0000000..4e65f02 --- /dev/null +++ b/app/src/com/jc/jcfw/util/Installation.java @@ -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; + } +} diff --git a/res/values/styles.xml b/res/values/styles.xml index a255e0d..e867333 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -14,6 +14,11 @@ true @android:style/Animation.Translucent +