From 6b654215d972bc2a270d1456fa2b7727765894ea Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Thu, 4 May 2023 12:57:53 +0530 Subject: [PATCH 1/8] session-manager-sdk added Signed-off-by: Gaurav Goel --- build.gradle | 1 + core/build.gradle | 9 + .../main/java/com/web3auth/core/Web3Auth.kt | 176 ++++-------------- .../web3auth/core/types/Web3AuthOptions.kt | 4 +- 4 files changed, 50 insertions(+), 140 deletions(-) diff --git a/build.gradle b/build.gradle index fbfafa2..4c92541 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,7 @@ allprojects { repositories { google() mavenCentral() + maven { url "https://jitpack.io" } } } diff --git a/core/build.gradle b/core/build.gradle index 66ef0cc..51d8cea 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -31,6 +31,12 @@ android { } } +allprojects { + repositories { + maven { url "https://jitpack.io" } + } +} + dependencies { // Default implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" @@ -61,6 +67,9 @@ dependencies { implementation 'androidx.security:security-crypto:1.1.0-alpha05' implementation 'org.web3j:core:4.8.8-android' + //session-manager-sdk + implementation 'com.github.grvgoel81:session-manager-android:0.0.1' + // Test testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/core/src/main/java/com/web3auth/core/Web3Auth.kt b/core/src/main/java/com/web3auth/core/Web3Auth.kt index b5028a1..ebc6633 100644 --- a/core/src/main/java/com/web3auth/core/Web3Auth.kt +++ b/core/src/main/java/com/web3auth/core/Web3Auth.kt @@ -8,17 +8,11 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.core.os.postDelayed import com.google.gson.GsonBuilder import com.web3auth.core.api.ApiHelper -import com.web3auth.core.api.Web3AuthApi -import com.web3auth.core.api.models.LogoutApiRequest import com.web3auth.core.keystore.KeyStoreManagerUtils import com.web3auth.core.types.* -import com.web3auth.core.types.Base64 +import com.web3auth.session_manager_android.SessionManager import java8.util.concurrent.CompletableFuture -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import org.json.JSONObject -import java.math.BigInteger -import java.nio.charset.StandardCharsets import java.util.* class Web3Auth(web3AuthOptions: Web3AuthOptions) { @@ -28,9 +22,8 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) { private var loginCompletableFuture: CompletableFuture = CompletableFuture() private var web3AuthResponse = Web3AuthResponse() - private val web3AuthApi = ApiHelper.getInstance().create(Web3AuthApi::class.java) - private var sessionId: String? = null private var web3AuthOption = web3AuthOptions + private var sessionManager: SessionManager = SessionManager(web3AuthOption.context) private fun initiateKeyStoreManager() { KeyStoreManagerUtils.getKeyGenerator() @@ -127,11 +120,8 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) { } else if (web3AuthResponse.privKey.isNullOrBlank()) { loginCompletableFuture.completeExceptionally(Exception(Web3AuthError.getError(ErrorCode.SOMETHING_WENT_WRONG))) } else { - web3AuthResponse.sessionId?.let { - KeyStoreManagerUtils.encryptData( - KeyStoreManagerUtils.SESSION_ID, it - ) - } + web3AuthResponse.sessionId?.let { sessionManager.saveSessionId(it) } + if (web3AuthResponse.userInfo?.dappShare?.isNotEmpty() == true) { KeyStoreManagerUtils.encryptData( web3AuthResponse.userInfo?.verifier.plus(" | ") @@ -164,60 +154,12 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) { fun logout(): CompletableFuture { val logoutCompletableFuture: CompletableFuture = CompletableFuture() if (ApiHelper.isNetworkAvailable(web3AuthOption.context)) { - try { - val ephemKey = - KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.EPHEM_PUBLIC_Key) - val ivKey = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.IV_KEY) - val mac = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.MAC) - sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID) - - if (ephemKey.isNullOrEmpty() || ivKey.isNullOrEmpty() || mac.isNullOrEmpty() || sessionId.isNullOrEmpty()) { + val sessionResponse: CompletableFuture = sessionManager.invalidateSession() + sessionResponse.whenComplete { _, error -> + if (error == null) { logoutCompletableFuture.complete(null) } else { - val aes256cbc = AES256CBC( - sessionId, ephemKey, ivKey.toString() - ) - val encryptedData = aes256cbc.encrypt("".toByteArray(StandardCharsets.UTF_8)) - val encryptedMetadata = ShareMetadata(ivKey, ephemKey, encryptedData, mac) - val gsonData = gson.toJson(encryptedMetadata) - - GlobalScope.launch { - val result = web3AuthApi.logout( - LogoutApiRequest( - key = "04".plus(KeyStoreManagerUtils.getPubKey(sessionId = sessionId.toString())), - data = gsonData, - signature = KeyStoreManagerUtils.getECDSASignature( - sessionId?.let { BigInteger(it, 16) }, gsonData - ), - timeout = 1 - ) - ) - if (result.isSuccessful) { - //Delete local storage - val loginConfigItem: LoginConfigItem? = - web3AuthOption.loginConfig?.values?.first() - KeyStoreManagerUtils.deletePreferencesData(loginConfigItem?.verifier.toString()) - Handler(Looper.getMainLooper()).postDelayed(10) { - logoutCompletableFuture.complete(null) - } - } else { - Handler(Looper.getMainLooper()).postDelayed(10) { - logoutCompletableFuture.completeExceptionally( - Exception( - Web3AuthError.getError( - ErrorCode.SOMETHING_WENT_WRONG - ) - ) - ) - } - } - } - } - - } catch (ex: Exception) { - ex.printStackTrace() - Handler(Looper.getMainLooper()).postDelayed(10) { - logoutCompletableFuture.completeExceptionally(ex) + logoutCompletableFuture.completeExceptionally(Exception(error)) } } } else { @@ -232,87 +174,47 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) { */ private fun authorizeSession(): CompletableFuture { val sessionCompletableFuture: CompletableFuture = CompletableFuture() - sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID) - if (sessionId != null && sessionId?.isNotEmpty() == true) { - val pubKey = "04".plus(KeyStoreManagerUtils.getPubKey(sessionId.toString())) - GlobalScope.launch { - try { - val result = web3AuthApi.authorizeSession(pubKey) - if (result.isSuccessful && result.body() != null) { - val messageObj = JSONObject(result.body()?.message).toString() - val shareMetadata = gson.fromJson( - messageObj, ShareMetadata::class.java - ) - - KeyStoreManagerUtils.savePreferenceData( - KeyStoreManagerUtils.EPHEM_PUBLIC_Key, - shareMetadata.ephemPublicKey.toString() - ) - KeyStoreManagerUtils.savePreferenceData( - KeyStoreManagerUtils.IV_KEY, shareMetadata.iv.toString() - ) - KeyStoreManagerUtils.savePreferenceData( - KeyStoreManagerUtils.MAC, shareMetadata.mac.toString() - ) - - val aes256cbc = AES256CBC( - sessionId, shareMetadata.ephemPublicKey, shareMetadata.iv.toString() - ) - - // Implementation specific oddity - hex string actually gets passed as a base64 string - val encryptedShareBytes = - AES256CBC.toByteArray(BigInteger(shareMetadata.ciphertext, 16)) - val share = aes256cbc.decrypt(Base64.encodeBytes(encryptedShareBytes)) - val tempJson = JSONObject(share.toString()) - tempJson.put("userInfo", tempJson.get("store")) - tempJson.remove("store") - web3AuthResponse = - gson.fromJson(tempJson.toString(), Web3AuthResponse::class.java) - if (web3AuthResponse.error?.isNotBlank() == true) { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.completeExceptionally( - UnKnownException( - web3AuthResponse.error ?: Web3AuthError.getError( - ErrorCode.SOMETHING_WENT_WRONG - ) - ) - ) - } - } else if (web3AuthResponse.privKey.isNullOrBlank()) { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.completeExceptionally( - Exception( - Web3AuthError.getError(ErrorCode.SOMETHING_WENT_WRONG) - ) - ) - } - } else { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.complete(web3AuthResponse) - } - } - } else { + val sessionResponse: CompletableFuture = sessionManager.authorizeSession(true) + sessionResponse.whenComplete { response, error -> + if (error == null) { + val tempJson = JSONObject(response) + tempJson.put("userInfo", tempJson.get("store")) + tempJson.remove("store") + web3AuthResponse = + gson.fromJson(tempJson.toString(), Web3AuthResponse::class.java) + if (web3AuthResponse.error?.isNotBlank() == true) { + Handler(Looper.getMainLooper()).postDelayed(10) { sessionCompletableFuture.completeExceptionally( - Exception( - Web3AuthError.getError( - ErrorCode.NOUSERFOUND + UnKnownException( + web3AuthResponse.error ?: Web3AuthError.getError( + ErrorCode.SOMETHING_WENT_WRONG ) ) ) } - } catch (ex: Exception) { - ex.printStackTrace() - sessionCompletableFuture.completeExceptionally( - Exception( - Web3AuthError.getError( - ErrorCode.NOUSERFOUND + } else if (web3AuthResponse.privKey.isNullOrBlank()) { + Handler(Looper.getMainLooper()).postDelayed(10) { + sessionCompletableFuture.completeExceptionally( + Exception( + Web3AuthError.getError(ErrorCode.SOMETHING_WENT_WRONG) ) ) - ) + } + } else { + Handler(Looper.getMainLooper()).postDelayed(10) { + sessionCompletableFuture.complete(web3AuthResponse) + } } + } else { + sessionCompletableFuture.completeExceptionally( + Exception( + Web3AuthError.getError( + ErrorCode.NOUSERFOUND + ) + ) + ) } } - return sessionCompletableFuture } diff --git a/core/src/main/java/com/web3auth/core/types/Web3AuthOptions.kt b/core/src/main/java/com/web3auth/core/types/Web3AuthOptions.kt index 4cf9290..1eb0e0d 100644 --- a/core/src/main/java/com/web3auth/core/types/Web3AuthOptions.kt +++ b/core/src/main/java/com/web3auth/core/types/Web3AuthOptions.kt @@ -2,7 +2,6 @@ package com.web3auth.core.types import android.content.Context import android.net.Uri -import com.web3auth.core.Web3Auth data class Web3AuthOptions( var context: Context, @@ -17,8 +16,7 @@ data class Web3AuthOptions( ) fun getSdkUrl(network: Network): String { - var sdkUrl = "" - sdkUrl = if (network == Network.TESTNET) { + val sdkUrl: String = if (network == Network.TESTNET) { "https://dev-sdk.openlogin.com" } else { "https://sdk.openlogin.com" From 79fad8d77a0716f20eaf224c42d8371724f41620 Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Mon, 8 May 2023 15:45:20 +0530 Subject: [PATCH 2/8] code cleaning. Signed-off-by: Gaurav Goel --- .../java/com/web3auth/core/api/ApiHelper.kt | 28 - .../java/com/web3auth/core/api/Web3AuthApi.kt | 18 - .../core/api/models/LogoutApiRequest.kt | 8 - .../core/api/models/StoreApiResponse.kt | 6 - .../core/keystore/KeyStoreManagerUtils.kt | 70 - .../com/web3auth/core/types/AES256CBC.java | 99 - .../java/com/web3auth/core/types/Base64.java | 1953 ----------------- .../core/types/ECPointArithmetic.java | 198 -- .../java/com/web3auth/core/types/SHA512.java | 12 - .../com/web3auth/core/types/ShareMetadata.kt | 11 - .../com/web3auth/core/types/TorusException.kt | 6 - 11 files changed, 2409 deletions(-) delete mode 100644 core/src/main/java/com/web3auth/core/api/Web3AuthApi.kt delete mode 100644 core/src/main/java/com/web3auth/core/api/models/LogoutApiRequest.kt delete mode 100644 core/src/main/java/com/web3auth/core/api/models/StoreApiResponse.kt delete mode 100644 core/src/main/java/com/web3auth/core/types/AES256CBC.java delete mode 100644 core/src/main/java/com/web3auth/core/types/Base64.java delete mode 100644 core/src/main/java/com/web3auth/core/types/ECPointArithmetic.java delete mode 100644 core/src/main/java/com/web3auth/core/types/SHA512.java delete mode 100644 core/src/main/java/com/web3auth/core/types/ShareMetadata.kt delete mode 100644 core/src/main/java/com/web3auth/core/types/TorusException.kt diff --git a/core/src/main/java/com/web3auth/core/api/ApiHelper.kt b/core/src/main/java/com/web3auth/core/api/ApiHelper.kt index b5e64a7..c27818b 100644 --- a/core/src/main/java/com/web3auth/core/api/ApiHelper.kt +++ b/core/src/main/java/com/web3auth/core/api/ApiHelper.kt @@ -4,37 +4,9 @@ import android.content.Context import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.os.Build -import com.google.gson.GsonBuilder -import com.web3auth.core.BuildConfig -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory -import java.util.concurrent.TimeUnit object ApiHelper { - private const val baseUrl = "https://broadcast-server.tor.us" - - private val okHttpClient = OkHttpClient().newBuilder() - .readTimeout(60, TimeUnit.SECONDS) - .connectTimeout(20, TimeUnit.SECONDS) - .addInterceptor(HttpLoggingInterceptor().apply { - if (BuildConfig.DEBUG) { - level = HttpLoggingInterceptor.Level.BODY - } - }) - .build() - - private val builder = GsonBuilder().disableHtmlEscaping().create() - - fun getInstance(): Retrofit { - return Retrofit.Builder().baseUrl(baseUrl) - .addConverterFactory(GsonConverterFactory.create(builder)) - .client(okHttpClient) - .build() - } - fun isNetworkAvailable(context: Context?): Boolean { if (context == null) return false val connectivityManager = diff --git a/core/src/main/java/com/web3auth/core/api/Web3AuthApi.kt b/core/src/main/java/com/web3auth/core/api/Web3AuthApi.kt deleted file mode 100644 index 75a7f00..0000000 --- a/core/src/main/java/com/web3auth/core/api/Web3AuthApi.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.web3auth.core.api - -import com.web3auth.core.api.models.LogoutApiRequest -import com.web3auth.core.api.models.StoreApiResponse -import org.json.JSONObject -import retrofit2.Response -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.Query - -interface Web3AuthApi { - @GET("/store/get") - suspend fun authorizeSession(@Query("key") key: String): Response - - @POST("/store/set") - suspend fun logout(@Body logoutApiRequest: LogoutApiRequest): Response -} \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/api/models/LogoutApiRequest.kt b/core/src/main/java/com/web3auth/core/api/models/LogoutApiRequest.kt deleted file mode 100644 index 9aef3e7..0000000 --- a/core/src/main/java/com/web3auth/core/api/models/LogoutApiRequest.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.web3auth.core.api.models - -data class LogoutApiRequest( - val key: String? = null, - val data: String? = null, - val signature: String? = null, - val timeout: Long = 0L -) \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/api/models/StoreApiResponse.kt b/core/src/main/java/com/web3auth/core/api/models/StoreApiResponse.kt deleted file mode 100644 index 508d72c..0000000 --- a/core/src/main/java/com/web3auth/core/api/models/StoreApiResponse.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.web3auth.core.api.models - -data class StoreApiResponse( - val message: String? = null, - val success: Boolean? = false, -) \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt b/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt index c93ffb9..0417781 100644 --- a/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt +++ b/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt @@ -5,31 +5,18 @@ import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyProperties import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys -import org.bouncycastle.asn1.ASN1EncodableVector -import org.bouncycastle.asn1.ASN1Integer -import org.bouncycastle.asn1.DERSequence -import org.web3j.crypto.ECKeyPair -import org.web3j.crypto.Hash -import java.math.BigInteger -import java.nio.charset.StandardCharsets import java.security.KeyStore -import java.util.* import javax.crypto.Cipher import javax.crypto.KeyGenerator import javax.crypto.SecretKey import javax.crypto.spec.IvParameterSpec import kotlin.text.Charsets.UTF_8 - object KeyStoreManagerUtils { private const val TRANSFORMATION = "AES/CBC/PKCS7Padding" private const val Android_KEY_STORE = "AndroidKeyStore" private const val WEB3AUTH = "Web3Auth" - const val IV_KEY = "ivKey" - const val EPHEM_PUBLIC_Key = "ephemPublicKey" - const val MAC = "mac" - const val SESSION_ID = "sessionId" private lateinit var encryptedPairData: Pair private val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) @@ -112,20 +99,6 @@ object KeyStoreManagerUtils { return result } - /** - * Store encrypted data into preferences - */ - fun savePreferenceData(key: String, data: String) { - sharedPreferences.edit().putString(key, data)?.apply() - } - - /** - * Retrieve decrypted data from preferences - */ - fun getPreferencesData(key: String): String? { - return sharedPreferences.getString(key, "") - } - /** * Delete All local storage */ @@ -149,47 +122,4 @@ object KeyStoreManagerUtils { keyStore.getEntry(WEB3AUTH, null) as KeyStore.SecretKeyEntry return secreteKeyEntry.secretKey } - - /** - * Get Public key from sessionID - */ - fun getPubKey(sessionId: String): String { - val derivedECKeyPair: ECKeyPair = ECKeyPair.create(BigInteger(sessionId, 16)) - return derivedECKeyPair.publicKey.toString(16) - } - - /** - * Get Private key from sessionID - */ - fun getPrivateKey(sessionId: String): String { - val derivedECKeyPair: ECKeyPair = ECKeyPair.create(BigInteger(sessionId, 16)) - return derivedECKeyPair.privateKey.toString(16) - } - - /** - * Generate Signature with privateKey and message - */ - fun getECDSASignature(privateKey: BigInteger?, data: String): String? { - val derivedECKeyPair = ECKeyPair.create(privateKey) - val hashedData = Hash.sha3(data.toByteArray(StandardCharsets.UTF_8)) - val signature = derivedECKeyPair.sign(hashedData) - val v = ASN1EncodableVector() - v.add(ASN1Integer(signature.r)) - v.add(ASN1Integer(signature.s)) - val der = DERSequence(v) - val sigBytes = der.encoded - return convertByteToHexadecimal(sigBytes) - } - - /** - * convert byte array to hex string - */ - private fun convertByteToHexadecimal(byteArray: ByteArray): String { - var hex = "" - // Iterating through each byte in the array - for (i in byteArray) { - hex += String.format("%02X", i) - } - return hex.lowercase(Locale.ROOT) - } } \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/types/AES256CBC.java b/core/src/main/java/com/web3auth/core/types/AES256CBC.java deleted file mode 100644 index d0dac64..0000000 --- a/core/src/main/java/com/web3auth/core/types/AES256CBC.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.web3auth.core.types; - -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.security.Key; -import java.security.NoSuchAlgorithmException; -import java.security.spec.AlgorithmParameterSpec; -import java.security.spec.ECFieldFp; -import java.security.spec.EllipticCurve; -import java.util.Arrays; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -public class AES256CBC { - private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; - private final byte[] AES_ENCRYPTION_KEY; - private final byte[] ENCRYPTION_IV; - - public AES256CBC(String privateKeyHex, String ephemPublicKeyHex, String encryptionIvHex) throws NoSuchAlgorithmException { - byte[] hash = SHA512.digest(toByteArray(ecdh(privateKeyHex, ephemPublicKeyHex))); - byte[] encKeyBytes = Arrays.copyOfRange(hash, 0, 32); - AES_ENCRYPTION_KEY = encKeyBytes; - ENCRYPTION_IV = toByteArray(encryptionIvHex); - } - - /** - * Utility method to convert a BigInteger to a byte array in unsigned - * format as needed in the handshake messages. BigInteger uses - * 2's complement format, i.e. it prepends an extra zero if the MSB - * is set. We remove that. - */ - public static byte[] toByteArray(BigInteger bi) { - byte[] b = bi.toByteArray(); - if (b.length > 1 && b[0] == 0) { - int n = b.length - 1; - byte[] newArray = new byte[n]; - System.arraycopy(b, 1, newArray, 0, n); - b = newArray; - } - return b; - } - - public static byte[] toByteArray(String s) { - int len = s.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) - + Character.digit(s.charAt(i+1), 16)); - } - return data; - } - - public String encrypt(byte[] src) throws TorusException { - Cipher cipher; - try { - cipher = Cipher.getInstance(TRANSFORMATION); - cipher.init(Cipher.ENCRYPT_MODE, makeKey(), makeIv()); - return Base64.encodeBytes(cipher.doFinal(src)); - } catch (Exception e) { - e.printStackTrace(); - throw new TorusException("Torus Internal Error", e); - } - } - - public String decrypt(String src) throws TorusException { - Cipher cipher; - try { - cipher = Cipher.getInstance(TRANSFORMATION); - cipher.init(Cipher.DECRYPT_MODE, makeKey(), makeIv()); - byte[] decrypt = cipher.doFinal(Base64.decode(src)); - return new String(decrypt, StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - throw new TorusException("Torus Internal Error", e); - } - - } - - private BigInteger ecdh(String privateKeyHex, String ephemPublicKeyHex) { - String affineX = ephemPublicKeyHex.substring(2, 66); - String affineY = ephemPublicKeyHex.substring(66); - - ECPointArithmetic ecPoint = new ECPointArithmetic(new EllipticCurve( - new ECFieldFp(new BigInteger("115792089237316195423570985008687907853269984665640564039457584007908834671663")), - new BigInteger("0"), - new BigInteger("7")), new BigInteger(affineX, 16), new BigInteger(affineY, 16), null); - return ecPoint.multiply(new BigInteger(privateKeyHex, 16)).getX(); - } - - private Key makeKey() { - return new SecretKeySpec(AES_ENCRYPTION_KEY, "AES"); - } - - private AlgorithmParameterSpec makeIv() { - return new IvParameterSpec(ENCRYPTION_IV); - } -} diff --git a/core/src/main/java/com/web3auth/core/types/Base64.java b/core/src/main/java/com/web3auth/core/types/Base64.java deleted file mode 100644 index a2ba791..0000000 --- a/core/src/main/java/com/web3auth/core/types/Base64.java +++ /dev/null @@ -1,1953 +0,0 @@ -package com.web3auth.core.types; - -import java.nio.charset.StandardCharsets; - -public class Base64 { - - /* ******** P U B L I C F I E L D S ******** */ - - - /** - * No options specified. Value is zero. - */ - public final static int NO_OPTIONS = 0; - - /** - * Specify encoding in first bit. Value is one. - */ - public final static int ENCODE = 1; - - - /** - * Specify decoding in first bit. Value is zero. - */ - public final static int DECODE = 0; - - - /** - * Specify that data should be gzip-compressed in second bit. Value is two. - */ - public final static int GZIP = 2; - - /** - * Specify that gzipped data should not be automatically gunzipped. - */ - public final static int DONT_GUNZIP = 4; - - - /** - * Do break lines when encoding. Value is 8. - */ - public final static int DO_BREAK_LINES = 8; - - /** - * Encode using Base64-like encoding that is URL- and Filename-safe as described - * in Section 4 of RFC3548: - * http://www.faqs.org/rfcs/rfc3548.html. - * It is important to note that data encoded this way is not officially valid Base64, - * or at the very least should not be called Base64 without also specifying that is - * was encoded using the URL- and Filename-safe dialect. - */ - public final static int URL_SAFE = 16; - - - /** - * Encode using the special "ordered" dialect of Base64 described here: - * http://www.faqs.org/qa/rfcc-1940.html. - */ - public final static int ORDERED = 32; - - - /* ******** P R I V A T E F I E L D S ******** */ - - - /** - * Maximum line length (76) of Base64 output. - */ - private final static int MAX_LINE_LENGTH = 76; - - - /** - * The equals sign (=) as a byte. - */ - private final static byte EQUALS_SIGN = (byte) '='; - - - /** - * The new line character (\n) as a byte. - */ - private final static byte NEW_LINE = (byte) '\n'; - - - /** - * Preferred encoding. - */ - private final static String PREFERRED_ENCODING = "US-ASCII"; - - - private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding - private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding - - - /* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ - - /** - * The 64 valid Base64 values. - */ - /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ - private final static byte[] _STANDARD_ALPHABET = { - (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', - (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', - (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', - (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', - (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', - (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', - (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+', (byte) '/' - }; - - - /** - * Translates a Base64 value to either its 6-bit reconstruction value - * or a negative number indicating some other meaning. - **/ - private final static byte[] _STANDARD_DECODABET = { - -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - 62, // Plus sign at decimal 43 - -9, -9, -9, // Decimal 44 - 46 - 63, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, -9, -9, // Decimal 91 - 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - , -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 128 - 139 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 140 - 152 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 153 - 165 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 166 - 178 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 179 - 191 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 192 - 204 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 205 - 217 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 218 - 230 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 231 - 243 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 // Decimal 244 - 255 - }; - - - /* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ - - /** - * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: - * http://www.faqs.org/rfcs/rfc3548.html. - * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." - */ - private final static byte[] _URL_SAFE_ALPHABET = { - (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', - (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', - (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', - (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', - (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', - (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', - (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '-', (byte) '_' - }; - - /** - * Used in decoding URL- and Filename-safe dialects of Base64. - */ - private final static byte[] _URL_SAFE_DECODABET = { - -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 62, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N' - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z' - -9, -9, -9, -9, // Decimal 91 - 94 - 63, // Underscore at decimal 95 - -9, // Decimal 96 - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm' - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - , -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 128 - 139 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 140 - 152 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 153 - 165 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 166 - 178 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 179 - 191 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 192 - 204 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 205 - 217 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 218 - 230 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 231 - 243 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 // Decimal 244 - 255 - }; - - - - /* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ - - /** - * I don't get the point of this technique, but someone requested it, - * and it is described here: - * http://www.faqs.org/qa/rfcc-1940.html. - */ - private final static byte[] _ORDERED_ALPHABET = { - (byte) '-', - (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', - (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', - (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', - (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', - (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', - (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', - (byte) '_', - (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', - (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', - (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', - (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z' - }; - - /** - * Used in decoding the "ordered" dialect of Base64. - */ - private final static byte[] _ORDERED_DECODABET = { - -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8 - -5, -5, // Whitespace: Tab and Linefeed - -9, -9, // Decimal 11 - 12 - -5, // Whitespace: Carriage Return - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26 - -9, -9, -9, -9, -9, // Decimal 27 - 31 - -5, // Whitespace: Space - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42 - -9, // Plus sign at decimal 43 - -9, // Decimal 44 - 0, // Minus sign at decimal 45 - -9, // Decimal 46 - -9, // Slash at decimal 47 - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // Numbers zero through nine - -9, -9, -9, // Decimal 58 - 60 - -1, // Equals sign at decimal 61 - -9, -9, -9, // Decimal 62 - 64 - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, // Letters 'A' through 'M' - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, // Letters 'N' through 'Z' - -9, -9, -9, -9, // Decimal 91 - 94 - 37, // Underscore at decimal 95 - -9, // Decimal 96 - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, // Letters 'a' through 'm' - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // Letters 'n' through 'z' - -9, -9, -9, -9, -9 // Decimal 123 - 127 - , -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 128 - 139 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 140 - 152 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 153 - 165 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 166 - 178 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 179 - 191 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 192 - 204 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 205 - 217 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 218 - 230 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 231 - 243 - -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9 // Decimal 244 - 255 - }; - - - /* ******** D E T E R M I N E W H I C H A L H A B E T ******** */ - - - /** - * Defeats instantiation. - */ - private Base64() { - } - - /** - * Returns one of the _SOMETHING_ALPHABET byte arrays depending on - * the options specified. - * It's possible, though silly, to specify ORDERED and URLSAFE - * in which case one of them will be picked, though there is - * no guarantee as to which one will be picked. - */ - private static byte[] getAlphabet(int options) { - if ((options & URL_SAFE) == URL_SAFE) { - return _URL_SAFE_ALPHABET; - } else if ((options & ORDERED) == ORDERED) { - return _ORDERED_ALPHABET; - } else { - return _STANDARD_ALPHABET; - } - } // end getAlphabet - - /** - * Returns one of the _SOMETHING_DECODABET byte arrays depending on - * the options specified. - * It's possible, though silly, to specify ORDERED and URL_SAFE - * in which case one of them will be picked, though there is - * no guarantee as to which one will be picked. - */ - private static byte[] getDecodabet(int options) { - if ((options & URL_SAFE) == URL_SAFE) { - return _URL_SAFE_DECODABET; - } else if ((options & ORDERED) == ORDERED) { - return _ORDERED_DECODABET; - } else { - return _STANDARD_DECODABET; - } - } // end getAlphabet - - - - - /* ******** E N C O D I N G M E T H O D S ******** */ - - /** - * Encodes up to the first three bytes of array threeBytes - * and returns a four-byte array in Base64 notation. - * The actual number of significant bytes in your array is - * given by numSigBytes. - * The array threeBytes needs only be as big as - * numSigBytes. - * Code can reuse a byte array by passing a four-byte array as b4. - * - * @param b4 A reusable byte array to reduce array instantiation - * @param threeBytes the array to convert - * @param numSigBytes the number of significant bytes in your array - * @return four byte array in Base64 notation. - * @since 1.5.1 - */ - private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes, int options) { - encode3to4(threeBytes, 0, numSigBytes, b4, 0, options); - return b4; - } // end encode3to4 - - - /** - *

Encodes up to three bytes of the array source - * and writes the resulting four Base64 bytes to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 3 for - * the source array or destOffset + 4 for - * the destination array. - * The actual number of significant bytes in your array is - * given by numSigBytes.

- *

This is the lowest level of the encoding methods with - * all possible parameters.

- * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param numSigBytes the number of significant bytes in your array - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @return the destination array - * @since 1.3 - */ - private static byte[] encode3to4( - byte[] source, int srcOffset, int numSigBytes, - byte[] destination, int destOffset, int options) { - - byte[] ALPHABET = getAlphabet(options); - - // 1 2 3 - // 01234567890123456789012345678901 Bit position - // --------000000001111111122222222 Array position from threeBytes - // --------| || || || | Six bit groups to index ALPHABET - // >>18 >>12 >> 6 >> 0 Right shift necessary - // 0x3f 0x3f 0x3f Additional AND - - // Create buffer with zero-padding if there are only one or two - // significant bytes passed in the array. - // We have to shift left 24 in order to flush out the 1's that appear - // when Java treats a value as negative that is cast from a byte to an int. - int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0) - | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0) - | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0); - - switch (numSigBytes) { - case 3: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f]; - return destination; - - case 2: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f]; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - case 1: - destination[destOffset] = ALPHABET[(inBuff >>> 18)]; - destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f]; - destination[destOffset + 2] = EQUALS_SIGN; - destination[destOffset + 3] = EQUALS_SIGN; - return destination; - - default: - return destination; - } // end switch - } // end encode3to4 - - - /** - * Performs Base64 encoding on the raw ByteBuffer, - * writing it to the encoded ByteBuffer. - * This is an experimental feature. Currently it does not - * pass along any options (such as {@link #DO_BREAK_LINES} - * or {@link #GZIP}. - * - * @param raw input buffer - * @param encoded output buffer - * @since 2.3 - */ - public static void encode(java.nio.ByteBuffer raw, java.nio.ByteBuffer encoded) { - byte[] raw3 = new byte[3]; - byte[] enc4 = new byte[4]; - - while (raw.hasRemaining()) { - int rem = Math.min(3, raw.remaining()); - raw.get(raw3, 0, rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS); - encoded.put(enc4); - } // end input remaining - } - - - /** - * Performs Base64 encoding on the raw ByteBuffer, - * writing it to the encoded CharBuffer. - * This is an experimental feature. Currently it does not - * pass along any options (such as {@link #DO_BREAK_LINES} - * or {@link #GZIP}. - * - * @param raw input buffer - * @param encoded output buffer - * @since 2.3 - */ - public static void encode(java.nio.ByteBuffer raw, java.nio.CharBuffer encoded) { - byte[] raw3 = new byte[3]; - byte[] enc4 = new byte[4]; - - while (raw.hasRemaining()) { - int rem = Math.min(3, raw.remaining()); - raw.get(raw3, 0, rem); - Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS); - for (int i = 0; i < 4; i++) { - encoded.put((char) (enc4[i] & 0xFF)); - } - } // end input remaining - } - - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. - * - *

As of v 2.3, if the object - * cannot be serialized or there is another error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- *

- * The object is not GZip-compressed before being encoded. - * - * @param serializableObject The object to encode - * @return The Base64-encoded object - * @throws java.io.IOException if there is an error - * @throws NullPointerException if serializedObject is null - * @since 1.4 - */ - public static String encodeObject(java.io.Serializable serializableObject) - throws java.io.IOException { - return encodeObject(serializableObject, NO_OPTIONS); - } // end encodeObject - - - /** - * Serializes an object and returns the Base64-encoded - * version of that serialized object. - * - *

As of v 2.3, if the object - * cannot be serialized or there is another error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- *

- * The object is not GZip-compressed before being encoded. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     * 
- *

- * Example: encodeObject( myObj, Base64.GZIP ) or - *

- * Example: encodeObject( myObj, Base64.GZIP | Base64.DO_BREAK_LINES ) - * - * @param serializableObject The object to encode - * @param options Specified options - * @return The Base64-encoded object - * @throws java.io.IOException if there is an error - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @since 2.0 - */ - public static String encodeObject(java.io.Serializable serializableObject, int options) - throws java.io.IOException { - - if (serializableObject == null) { - throw new NullPointerException("Cannot serialize a null object."); - } // end if: null - - // Streams - java.io.ByteArrayOutputStream baos = null; - java.io.OutputStream b64os = null; - java.util.zip.GZIPOutputStream gzos = null; - java.io.ObjectOutputStream oos = null; - - - try { - // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream - baos = new java.io.ByteArrayOutputStream(); - b64os = new OutputStream(baos, ENCODE | options); - if ((options & GZIP) != 0) { - // Gzip - gzos = new java.util.zip.GZIPOutputStream(b64os); - oos = new java.io.ObjectOutputStream(gzos); - } else { - // Not gzipped - oos = new java.io.ObjectOutputStream(b64os); - } - oos.writeObject(serializableObject); - } // end try - catch (java.io.IOException e) { - // Catch it and then throw it immediately so that - // the finally{} block is called for cleanup. - throw e; - } // end catch - finally { - try { - oos.close(); - } catch (Exception ignored) { - } - try { - gzos.close(); - } catch (Exception e) { - } - try { - b64os.close(); - } catch (Exception e) { - } - try { - baos.close(); - } catch (Exception e) { - } - } // end finally - - // Return value according to relevant encoding. - try { - return new String(baos.toByteArray(), PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uue) { - // Fall back to some Java default - return new String(baos.toByteArray()); - } // end catch - - } // end encode - - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - * @param source The data to convert - * @return The data in Base64-encoded form - * @throws NullPointerException if source array is null - * @since 1.4 - */ - public static String encodeBytes(byte[] source) { - // Since we're not going to have the GZIP encoding turned on, - // we're not going to have an java.io.IOException thrown, so - // we should not force the user to have to catch it. - String encoded = null; - try { - encoded = encodeBytes(source, 0, source.length, NO_OPTIONS); - } catch (java.io.IOException ex) { - assert false : ex.getMessage(); - } // end catch - assert encoded != null; - return encoded; - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     *     Note: Technically, this makes your encoding non-compliant.
-     * 
- *

- * Example: encodeBytes( myData, Base64.GZIP ) or - *

- * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) - * - * - *

As of v 2.3, if there is an error with the GZIP stream, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @throws java.io.IOException if there is an error - * @throws NullPointerException if source array is null - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @since 2.0 - */ - public static String encodeBytes(byte[] source, int options) throws java.io.IOException { - return encodeBytes(source, 0, source.length, options); - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - * Does not GZip-compress data. - * - *

As of v 2.3, if there is an error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @return The Base64-encoded data as a String - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @since 1.4 - */ - public static String encodeBytes(byte[] source, int off, int len) { - // Since we're not going to have the GZIP encoding turned on, - // we're not going to have an java.io.IOException thrown, so - // we should not force the user to have to catch it. - String encoded = null; - try { - encoded = encodeBytes(source, off, len, NO_OPTIONS); - } catch (java.io.IOException ex) { - assert false : ex.getMessage(); - } // end catch - assert encoded != null; - return encoded; - } // end encodeBytes - - - /** - * Encodes a byte array into Base64 notation. - *

- * Example options:

-     *   GZIP: gzip-compresses object before encoding it.
-     *   DO_BREAK_LINES: break lines at 76 characters
-     *     Note: Technically, this makes your encoding non-compliant.
-     * 
- *

- * Example: encodeBytes( myData, Base64.GZIP ) or - *

- * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) - * - * - *

As of v 2.3, if there is an error with the GZIP stream, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned a null value, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @throws java.io.IOException if there is an error - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @since 2.0 - */ - public static String encodeBytes(byte[] source, int off, int len, int options) throws java.io.IOException { - byte[] encoded = encodeBytesToBytes(source, off, len, options); - - // Return value according to relevant encoding. - try { - return new String(encoded, PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uue) { - return new String(encoded); - } // end catch - - } // end encodeBytes - - - /** - * Similar to {@link #encodeBytes(byte[])} but returns - * a byte array instead of instantiating a String. This is more efficient - * if you're working with I/O streams and have large data sets to encode. - * - * @param source The data to convert - * @return The Base64-encoded data as a byte[] (of ASCII characters) - * @throws NullPointerException if source array is null - * @since 2.3.1 - */ - public static byte[] encodeBytesToBytes(byte[] source) { - byte[] encoded = null; - try { - encoded = encodeBytesToBytes(source, 0, source.length, Base64.NO_OPTIONS); - } catch (java.io.IOException ex) { - assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); - } - return encoded; - } - - - /** - * Similar to {@link #encodeBytes(byte[], int, int, int)} but returns - * a byte array instead of instantiating a String. This is more efficient - * if you're working with I/O streams and have large data sets to encode. - * - * @param source The data to convert - * @param off Offset in array where conversion should begin - * @param len Length of data to convert - * @param options Specified options - * @return The Base64-encoded data as a String - * @throws java.io.IOException if there is an error - * @throws NullPointerException if source array is null - * @throws IllegalArgumentException if source array, offset, or length are invalid - * @see Base64#GZIP - * @see Base64#DO_BREAK_LINES - * @since 2.3.1 - */ - public static byte[] encodeBytesToBytes(byte[] source, int off, int len, int options) throws java.io.IOException { - - if (source == null) { - throw new NullPointerException("Cannot serialize a null array."); - } // end if: null - - if (off < 0) { - throw new IllegalArgumentException("Cannot have negative offset: " + off); - } // end if: off < 0 - - if (len < 0) { - throw new IllegalArgumentException("Cannot have length offset: " + len); - } // end if: len < 0 - - if (off + len > source.length) { - throw new IllegalArgumentException( - String.format("Cannot have offset of %d and length of %d with array of length %d", off, len, source.length)); - } // end if: off < 0 - - - // Compress? - if ((options & GZIP) != 0) { - java.io.ByteArrayOutputStream baos = null; - java.util.zip.GZIPOutputStream gzos = null; - OutputStream b64os = null; - - try { - // GZip -> Base64 -> ByteArray - baos = new java.io.ByteArrayOutputStream(); - b64os = new OutputStream(baos, ENCODE | options); - gzos = new java.util.zip.GZIPOutputStream(b64os); - - gzos.write(source, off, len); - gzos.close(); - } // end try - catch (java.io.IOException e) { - // Catch it and then throw it immediately so that - // the finally{} block is called for cleanup. - throw e; - } // end catch - finally { - try { - gzos.close(); - } catch (Exception e) { - } - try { - b64os.close(); - } catch (Exception e) { - } - try { - baos.close(); - } catch (Exception e) { - } - } // end finally - - return baos.toByteArray(); - } // end if: compress - - // Else, don't compress. Better not to use streams at all then. - else { - boolean breakLines = (options & DO_BREAK_LINES) != 0; - - //int len43 = len * 4 / 3; - //byte[] outBuff = new byte[ ( len43 ) // Main 4:3 - // + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding - // + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines - // Try to determine more precisely how big the array needs to be. - // If we get it right, we don't have to do an array copy, and - // we save a bunch of memory. - int encLen = (len / 3) * 4 + (len % 3 > 0 ? 4 : 0); // Bytes needed for actual encoding - if (breakLines) { - encLen += encLen / MAX_LINE_LENGTH; // Plus extra newline characters - } - byte[] outBuff = new byte[encLen]; - - - int d = 0; - int e = 0; - int len2 = len - 2; - int lineLength = 0; - for (; d < len2; d += 3, e += 4) { - encode3to4(source, d + off, 3, outBuff, e, options); - - lineLength += 4; - if (breakLines && lineLength >= MAX_LINE_LENGTH) { - outBuff[e + 4] = NEW_LINE; - e++; - lineLength = 0; - } // end if: end of line - } // en dfor: each piece of array - - if (d < len) { - encode3to4(source, d + off, len - d, outBuff, e, options); - e += 4; - } // end if: some padding needed - - - // Only resize array if we didn't guess it right. - if (e <= outBuff.length - 1) { - // If breaking lines and the last byte falls right at - // the line length (76 bytes per line), there will be - // one extra byte, and the array will need to be resized. - // Not too bad of an estimate on array size, I'd say. - byte[] finalOut = new byte[e]; - System.arraycopy(outBuff, 0, finalOut, 0, e); - //System.err.println("Having to resize array from " + outBuff.length + " to " + e ); - return finalOut; - } else { - //System.err.println("No need to resize array."); - return outBuff; - } - - } // end else: don't compress - - } // end encodeBytesToBytes - - - - - - /* ******** D E C O D I N G M E T H O D S ******** */ - - - /** - * Decodes four bytes from array source - * and writes the resulting bytes (up to three of them) - * to destination. - * The source and destination arrays can be manipulated - * anywhere along their length by specifying - * srcOffset and destOffset. - * This method does not check to make sure your arrays - * are large enough to accomodate srcOffset + 4 for - * the source array or destOffset + 3 for - * the destination array. - * This method returns the actual number of bytes that - * were converted from the Base64 encoding. - *

This is the lowest level of the decoding methods with - * all possible parameters.

- * - * @param source the array to convert - * @param srcOffset the index where conversion begins - * @param destination the array to hold the conversion - * @param destOffset the index where output will be put - * @param options alphabet type is pulled from this (standard, url-safe, ordered) - * @return the number of decoded bytes converted - * @throws NullPointerException if source or destination arrays are null - * @throws IllegalArgumentException if srcOffset or destOffset are invalid - * or there is not enough room in the array. - * @since 1.3 - */ - private static int decode4to3( - byte[] source, int srcOffset, - byte[] destination, int destOffset, int options) { - - // Lots of error checking and exception throwing - if (source == null) { - throw new NullPointerException("Source array was null."); - } // end if - if (destination == null) { - throw new NullPointerException("Destination array was null."); - } // end if - if (srcOffset < 0 || srcOffset + 3 >= source.length) { - throw new IllegalArgumentException(String.format( - "Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset)); - } // end if - if (destOffset < 0 || destOffset + 2 >= destination.length) { - throw new IllegalArgumentException(String.format( - "Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset)); - } // end if - - - byte[] DECODABET = getDecodabet(options); - - // Example: Dk== - if (source[srcOffset + 2] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12); - - destination[destOffset] = (byte) (outBuff >>> 16); - return 1; - } - - // Example: DkL= - else if (source[srcOffset + 3] == EQUALS_SIGN) { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6); - - destination[destOffset] = (byte) (outBuff >>> 16); - destination[destOffset + 1] = (byte) (outBuff >>> 8); - return 2; - } - - // Example: DkLE - else { - // Two ways to do the same thing. Don't know which way I like best. - //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) - // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) - // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) - // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); - int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18) - | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12) - | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6) - | ((DECODABET[source[srcOffset + 3]] & 0xFF)); - - - destination[destOffset] = (byte) (outBuff >> 16); - destination[destOffset + 1] = (byte) (outBuff >> 8); - destination[destOffset + 2] = (byte) (outBuff); - - return 3; - } - } // end decodeToBytes - - - /** - * Low-level access to decoding ASCII characters in - * the form of a byte array. Ignores GUNZIP option, if - * it's set. This is not generally a recommended method, - * although it is used internally as part of the decoding process. - * Special case: if len = 0, an empty array is returned. Still, - * if you need more speed and reduced memory footprint (and aren't - * gzipping), consider this method. - * - * @param source The Base64 encoded data - * @return decoded data - * @since 2.3.1 - */ - public static byte[] decode(byte[] source) - throws java.io.IOException { - byte[] decoded = null; -// try { - decoded = decode(source, 0, source.length, Base64.NO_OPTIONS); -// } catch( java.io.IOException ex ) { -// assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); -// } - return decoded; - } - - - /** - * Low-level access to decoding ASCII characters in - * the form of a byte array. Ignores GUNZIP option, if - * it's set. This is not generally a recommended method, - * although it is used internally as part of the decoding process. - * Special case: if len = 0, an empty array is returned. Still, - * if you need more speed and reduced memory footprint (and aren't - * gzipping), consider this method. - * - * @param source The Base64 encoded data - * @param off The offset of where to begin decoding - * @param len The length of characters to decode - * @param options Can specify options such as alphabet type to use - * @return decoded data - * @throws java.io.IOException If bogus characters exist in source data - * @since 1.3 - */ - public static byte[] decode(byte[] source, int off, int len, int options) - throws java.io.IOException { - - // Lots of error checking and exception throwing - if (source == null) { - throw new NullPointerException("Cannot decode null source array."); - } // end if - if (off < 0 || off + len > source.length) { - throw new IllegalArgumentException(String.format( - "Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len)); - } // end if - - if (len == 0) { - return new byte[0]; - } else if (len < 4) { - throw new IllegalArgumentException( - "Base64-encoded string must have at least four characters, but length specified was " + len); - } // end if - - byte[] DECODABET = getDecodabet(options); - - int len34 = len * 3 / 4; // Estimate on array size - byte[] outBuff = new byte[len34]; // Upper limit on size of output - int outBuffPosn = 0; // Keep track of where we're writing - - byte[] b4 = new byte[4]; // Four byte buffer from source, eliminating white space - int b4Posn = 0; // Keep track of four byte input buffer - int i = 0; // Source array counter - byte sbiDecode = 0; // Special value from DECODABET - - for (i = off; i < off + len; i++) { // Loop through source - - sbiDecode = DECODABET[source[i] & 0xFF]; - - // White space, Equals sign, or legit Base64 character - // Note the values such as -5 and -9 in the - // DECODABETs at the top of the file. - if (sbiDecode >= WHITE_SPACE_ENC) { - if (sbiDecode >= EQUALS_SIGN_ENC) { - b4[b4Posn++] = source[i]; // Save non-whitespace - if (b4Posn > 3) { // Time to decode? - outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn, options); - b4Posn = 0; - - // If that was the equals sign, break out of 'for' loop - if (source[i] == EQUALS_SIGN) { - break; - } // end if: equals sign - } // end if: quartet built - } // end if: equals sign or better - } // end if: white space, equals sign or better - else { - // There's a bad input character in the Base64 stream. - throw new java.io.IOException(String.format( - "Bad Base64 input character decimal %d in array position %d", ((int) source[i]) & 0xFF, i)); - } // end else: - } // each input character - - byte[] out = new byte[outBuffPosn]; - System.arraycopy(outBuff, 0, out, 0, outBuffPosn); - return out; - } // end decode - - - /** - * Decodes data from Base64 notation, automatically - * detecting gzip-compressed data and decompressing it. - * - * @param s the string to decode - * @return the decoded data - * @throws java.io.IOException If there is a problem - * @since 1.4 - */ - public static byte[] decode(String s) throws java.io.IOException { - return decode(s, NO_OPTIONS); - } - - - /** - * Decodes data from Base64 notation, automatically - * detecting gzip-compressed data and decompressing it. - * - * @param s the string to decode - * @param options encode options such as URL_SAFE - * @return the decoded data - * @throws java.io.IOException if there is an error - * @throws NullPointerException if s is null - * @since 1.4 - */ - public static byte[] decode(String s, int options) throws java.io.IOException { - - if (s == null) { - throw new NullPointerException("Input string was null."); - } // end if - - byte[] bytes; - try { - bytes = s.getBytes(PREFERRED_ENCODING); - } // end try - catch (java.io.UnsupportedEncodingException uee) { - bytes = s.getBytes(); - } // end catch - // - - // Decode - bytes = decode(bytes, 0, bytes.length, options); - - // Check to see if it's gzip-compressed - // GZIP Magic Two-Byte Number: 0x8b1f (35615) - boolean dontGunzip = (options & DONT_GUNZIP) != 0; - if ((bytes != null) && (bytes.length >= 4) && (!dontGunzip)) { - - int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); - if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) { - java.io.ByteArrayInputStream bais = null; - java.util.zip.GZIPInputStream gzis = null; - java.io.ByteArrayOutputStream baos = null; - byte[] buffer = new byte[2048]; - int length = 0; - - try { - baos = new java.io.ByteArrayOutputStream(); - bais = new java.io.ByteArrayInputStream(bytes); - gzis = new java.util.zip.GZIPInputStream(bais); - - while ((length = gzis.read(buffer)) >= 0) { - baos.write(buffer, 0, length); - } // end while: reading input - - // No error? Get new bytes. - bytes = baos.toByteArray(); - - } // end try - catch (java.io.IOException e) { - e.printStackTrace(); - // Just return originally-decoded bytes - } // end catch - finally { - try { - baos.close(); - } catch (Exception e) { - } - try { - gzis.close(); - } catch (Exception e) { - } - try { - bais.close(); - } catch (Exception e) { - } - } // end finally - - } // end if: gzipped - } // end if: bytes.length >= 2 - - return bytes; - } // end decode - - - /** - * Attempts to decode Base64 data and deserialize a Java - * Object within. Returns null if there was an error. - * - * @param encodedObject The Base64 data to decode - * @return The decoded and deserialized object - * @throws NullPointerException if encodedObject is null - * @throws java.io.IOException if there is a general error - * @throws ClassNotFoundException if the decoded object is of a - * class that cannot be found by the JVM - * @since 1.5 - */ - public static Object decodeToObject(String encodedObject) - throws java.io.IOException, ClassNotFoundException { - return decodeToObject(encodedObject, NO_OPTIONS, null); - } - - - /** - * Attempts to decode Base64 data and deserialize a Java - * Object within. Returns null if there was an error. - * If loader is not null, it will be the class loader - * used when deserializing. - * - * @param encodedObject The Base64 data to decode - * @param options Various parameters related to decoding - * @param loader Optional class loader to use in deserializing classes. - * @return The decoded and deserialized object - * @throws NullPointerException if encodedObject is null - * @throws java.io.IOException if there is a general error - * @throws ClassNotFoundException if the decoded object is of a - * class that cannot be found by the JVM - * @since 2.3.4 - */ - public static Object decodeToObject( - String encodedObject, int options, final ClassLoader loader) - throws java.io.IOException, ClassNotFoundException { - - // Decode and gunzip if necessary - byte[] objBytes = decode(encodedObject, options); - - java.io.ByteArrayInputStream bais = null; - java.io.ObjectInputStream ois = null; - Object obj = null; - - try { - bais = new java.io.ByteArrayInputStream(objBytes); - - // If no custom class loader is provided, use Java's builtin OIS. - if (loader == null) { - ois = new java.io.ObjectInputStream(bais); - } // end if: no loader provided - - // Else make a customized object input stream that uses - // the provided class loader. - else { - ois = new java.io.ObjectInputStream(bais) { - @Override - public Class resolveClass(java.io.ObjectStreamClass streamClass) - throws java.io.IOException, ClassNotFoundException { - Class c = Class.forName(streamClass.getName(), false, loader); - if (c == null) { - return super.resolveClass(streamClass); - } else { - return c; // Class loader knows of this class. - } // end else: not null - } // end resolveClass - }; // end ois - } // end else: no custom class loader - - obj = ois.readObject(); - } // end try - catch (java.io.IOException e) { - throw e; // Catch and throw in order to execute finally{} - } // end catch - catch (ClassNotFoundException e) { - throw e; // Catch and throw in order to execute finally{} - } // end catch - finally { - try { - bais.close(); - } catch (Exception e) { - } - try { - ois.close(); - } catch (Exception e) { - } - } // end finally - - return obj; - } // end decodeObject - - - /** - * Convenience method for encoding data to a file. - * - *

As of v 2.3, if there is a error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param dataToEncode byte array of data to encode in base64 form - * @param filename Filename for saving encoded data - * @throws java.io.IOException if there is an error - * @throws NullPointerException if dataToEncode is null - * @since 2.1 - */ - public static void encodeToFile(byte[] dataToEncode, String filename) - throws java.io.IOException { - - if (dataToEncode == null) { - throw new NullPointerException("Data to encode was null."); - } // end iff - - OutputStream bos = null; - try { - bos = new OutputStream( - new java.io.FileOutputStream(filename), Base64.ENCODE); - bos.write(dataToEncode); - } // end try - catch (java.io.IOException e) { - throw e; // Catch and throw to execute finally{} block - } // end catch: java.io.IOException - finally { - try { - bos.close(); - } catch (Exception e) { - } - } // end finally - - } // end encodeToFile - - - /** - * Convenience method for decoding data to a file. - * - *

As of v 2.3, if there is a error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param dataToDecode Base64-encoded data as a string - * @param filename Filename for saving decoded data - * @throws java.io.IOException if there is an error - * @since 2.1 - */ - public static void decodeToFile(String dataToDecode, String filename) - throws java.io.IOException { - - OutputStream bos = null; - try { - bos = new OutputStream( - new java.io.FileOutputStream(filename), Base64.DECODE); - bos.write(dataToDecode.getBytes(PREFERRED_ENCODING)); - } // end try - catch (java.io.IOException e) { - throw e; // Catch and throw to execute finally{} block - } // end catch: java.io.IOException - finally { - try { - bos.close(); - } catch (Exception e) { - } - } // end finally - - } // end decodeToFile - - - /** - * Convenience method for reading a base64-encoded - * file and decoding it. - * - *

As of v 2.3, if there is a error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param filename Filename for reading encoded data - * @return decoded byte array - * @throws java.io.IOException if there is an error - * @since 2.1 - */ - public static byte[] decodeFromFile(String filename) - throws java.io.IOException { - - byte[] decodedData = null; - InputStream bis = null; - try { - // Set up some useful variables - java.io.File file = new java.io.File(filename); - byte[] buffer = null; - int length = 0; - int numBytes = 0; - - // Check for size of file - if (file.length() > Integer.MAX_VALUE) { - throw new java.io.IOException("File is too big for this convenience method (" + file.length() + " bytes)."); - } // end if: file too big for int index - buffer = new byte[(int) file.length()]; - - // Open a stream - bis = new InputStream( - new java.io.BufferedInputStream( - new java.io.FileInputStream(file)), Base64.DECODE); - - // Read until done - while ((numBytes = bis.read(buffer, length, 4096)) >= 0) { - length += numBytes; - } // end while - - // Save in a variable to return - decodedData = new byte[length]; - System.arraycopy(buffer, 0, decodedData, 0, length); - - } // end try - catch (java.io.IOException e) { - throw e; // Catch and release to execute finally{} - } // end catch: java.io.IOException - finally { - try { - bis.close(); - } catch (Exception e) { - } - } // end finally - - return decodedData; - } // end decodeFromFile - - - /** - * Convenience method for reading a binary file - * and base64-encoding it. - * - *

As of v 2.3, if there is a error, - * the method will throw an java.io.IOException. This is new to v2.3! - * In earlier versions, it just returned false, but - * in retrospect that's a pretty poor way to handle it.

- * - * @param filename Filename for reading binary data - * @return base64-encoded string - * @throws java.io.IOException if there is an error - * @since 2.1 - */ - public static String encodeFromFile(String filename) - throws java.io.IOException { - - String encodedData = null; - InputStream bis = null; - try { - // Set up some useful variables - java.io.File file = new java.io.File(filename); - byte[] buffer = new byte[Math.max((int) (file.length() * 1.4 + 1), 40)]; // Need max() for math on small files (v2.2.1); Need +1 for a few corner cases (v2.3.5) - int length = 0; - int numBytes = 0; - - // Open a stream - bis = new InputStream( - new java.io.BufferedInputStream( - new java.io.FileInputStream(file)), Base64.ENCODE); - - // Read until done - while ((numBytes = bis.read(buffer, length, 4096)) >= 0) { - length += numBytes; - } // end while - - // Save in a variable to return - encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING); - - } // end try - catch (java.io.IOException e) { - throw e; // Catch and release to execute finally{} - } // end catch: java.io.IOException - finally { - try { - bis.close(); - } catch (Exception e) { - } - } // end finally - - return encodedData; - } // end encodeFromFile - - /** - * Reads infile and encodes it to outfile. - * - * @param infile Input file - * @param outfile Output file - * @throws java.io.IOException if there is an error - * @since 2.2 - */ - public static void encodeFileToFile(String infile, String outfile) - throws java.io.IOException { - - String encoded = Base64.encodeFromFile(infile); - java.io.OutputStream out = null; - try { - out = new java.io.BufferedOutputStream( - new java.io.FileOutputStream(outfile)); - out.write(encoded.getBytes(StandardCharsets.US_ASCII)); // Strict, 7-bit output. - } // end try - catch (java.io.IOException e) { - throw e; // Catch and release to execute finally{} - } // end catch - finally { - try { - out.close(); - } catch (Exception ex) { - } - } // end finally - } // end encodeFileToFile - - - /** - * Reads infile and decodes it to outfile. - * - * @param infile Input file - * @param outfile Output file - * @throws java.io.IOException if there is an error - * @since 2.2 - */ - public static void decodeFileToFile(String infile, String outfile) - throws java.io.IOException { - - byte[] decoded = Base64.decodeFromFile(infile); - java.io.OutputStream out = null; - try { - out = new java.io.BufferedOutputStream( - new java.io.FileOutputStream(outfile)); - out.write(decoded); - } // end try - catch (java.io.IOException e) { - throw e; // Catch and release to execute finally{} - } // end catch - finally { - try { - out.close(); - } catch (Exception ex) { - } - } // end finally - } // end decodeFileToFile - - - /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ - - - /** - * A {@link InputStream} will read data from another - * java.io.InputStream, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @since 1.3 - */ - public static class InputStream extends java.io.FilterInputStream { - - private final boolean encode; // Encoding or decoding - private final byte[] buffer; // Small buffer holding converted data - private final int bufferLength; // Length of buffer (3 or 4) - private final boolean breakLines; // Break lines at less than 80 characters - private final int options; // Record options used to create the stream. - private final byte[] decodabet; // Local copies to avoid extra method calls - private int position; // Current position in the buffer - private int numSigBytes; // Number of meaningful bytes in the buffer - private int lineLength; - - - /** - * Constructs a {@link InputStream} in DECODE mode. - * - * @param in the java.io.InputStream from which to read data. - * @since 1.3 - */ - public InputStream(java.io.InputStream in) { - this(in, DECODE); - } // end constructor - - - /** - * Constructs a {@link InputStream} in - * either ENCODE or DECODE mode. - *

- * Valid options:

-         *   ENCODE or DECODE: Encode or Decode as data is read.
-         *   DO_BREAK_LINES: break lines at 76 characters
-         *     (only meaningful when encoding)
-         * 
- *

- * Example: new Base64.InputStream( in, Base64.DECODE ) - * - * @param in the java.io.InputStream from which to read data. - * @param options Specified options - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DO_BREAK_LINES - * @since 2.0 - */ - public InputStream(java.io.InputStream in, int options) { - - super(in); - this.options = options; // Record for later - this.breakLines = (options & DO_BREAK_LINES) > 0; - this.encode = (options & ENCODE) > 0; - this.bufferLength = encode ? 4 : 3; - this.buffer = new byte[bufferLength]; - this.position = -1; - this.lineLength = 0; - this.decodabet = getDecodabet(options); - } // end constructor - - /** - * Reads enough of the input stream to convert - * to/from Base64 and returns the next byte. - * - * @return next byte - * @since 1.3 - */ - @Override - public int read() throws java.io.IOException { - - // Do we need to get data? - if (position < 0) { - if (encode) { - byte[] b3 = new byte[3]; - int numBinaryBytes = 0; - for (int i = 0; i < 3; i++) { - int b = in.read(); - - // If end of stream, b is -1. - if (b >= 0) { - b3[i] = (byte) b; - numBinaryBytes++; - } else { - break; // out of for loop - } // end else: end of stream - - } // end for: each needed input byte - - if (numBinaryBytes > 0) { - encode3to4(b3, 0, numBinaryBytes, buffer, 0, options); - position = 0; - numSigBytes = 4; - } // end if: got data - else { - return -1; // Must be end of stream - } // end else - } // end if: encoding - - // Else decoding - else { - byte[] b4 = new byte[4]; - int i = 0; - for (i = 0; i < 4; i++) { - // Read four "meaningful" bytes: - int b = 0; - do { - b = in.read(); - } - while (b >= 0 && decodabet[b & 0x7f] <= WHITE_SPACE_ENC); - - if (b < 0) { - break; // Reads a -1 if end of stream - } // end if: end of stream - - b4[i] = (byte) b; - } // end for: each needed input byte - - if (i == 4) { - numSigBytes = decode4to3(b4, 0, buffer, 0, options); - position = 0; - } // end if: got four characters - else if (i == 0) { - return -1; - } // end else if: also padded correctly - else { - // Must have broken out from above. - throw new java.io.IOException("Improperly padded Base64 input."); - } // end - - } // end else: decode - } // end else: get data - - // Got data? - if (position >= 0) { - // End of relevant data? - if ( /*!encode &&*/ position >= numSigBytes) { - return -1; - } // end if: got data - - if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) { - lineLength = 0; - return '\n'; - } // end if - else { - lineLength++; // This isn't important when decoding - // but throwing an extra "if" seems - // just as wasteful. - - int b = buffer[position++]; - - if (position >= bufferLength) { - position = -1; - } // end if: end - - return b & 0xFF; // This is how you "cast" a byte that's - // intended to be unsigned. - } // end else - } // end if: position >= 0 - - // Else error - else { - throw new java.io.IOException("Error in Base64 code reading stream."); - } // end else - } // end read - - - /** - * Calls {@link #read()} repeatedly until the end of stream - * is reached or len bytes are read. - * Returns number of bytes read into array or -1 if - * end of stream is encountered. - * - * @param dest array to hold values - * @param off offset for array - * @param len max number of bytes to read into array - * @return bytes read into array or -1 if end of stream is encountered. - * @since 1.3 - */ - @Override - public int read(byte[] dest, int off, int len) - throws java.io.IOException { - int i; - int b; - for (i = 0; i < len; i++) { - b = read(); - - if (b >= 0) { - dest[off + i] = (byte) b; - } else if (i == 0) { - return -1; - } else { - break; // Out of 'for' loop - } // Out of 'for' loop - } // end for: each byte read - return i; - } // end read - - } // end inner class InputStream - - - - - - - /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ - - - /** - * A {@link OutputStream} will write data to another - * java.io.OutputStream, given in the constructor, - * and encode/decode to/from Base64 notation on the fly. - * - * @see Base64 - * @since 1.3 - */ - public static class OutputStream extends java.io.FilterOutputStream { - - private final boolean encode; - private final int bufferLength; - private final boolean breakLines; - private final byte[] b4; // Scratch used in a few places - private final int options; // Record for later - private final byte[] decodabet; // Local copies to avoid extra method calls - private int position; - private boolean suspendEncoding; - private byte[] buffer; - private int lineLength; - - /** - * Constructs a {@link OutputStream} in ENCODE mode. - * - * @param out the java.io.OutputStream to which data will be written. - * @since 1.3 - */ - public OutputStream(java.io.OutputStream out) { - this(out, ENCODE); - } // end constructor - - - /** - * Constructs a {@link OutputStream} in - * either ENCODE or DECODE mode. - *

- * Valid options:

-         *   ENCODE or DECODE: Encode or Decode as data is read.
-         *   DO_BREAK_LINES: don't break lines at 76 characters
-         *     (only meaningful when encoding)
-         * 
- *

- * Example: new Base64.OutputStream( out, Base64.ENCODE ) - * - * @param out the java.io.OutputStream to which data will be written. - * @param options Specified options. - * @see Base64#ENCODE - * @see Base64#DECODE - * @see Base64#DO_BREAK_LINES - * @since 1.3 - */ - public OutputStream(java.io.OutputStream out, int options) { - super(out); - this.breakLines = (options & DO_BREAK_LINES) != 0; - this.encode = (options & ENCODE) != 0; - this.bufferLength = encode ? 3 : 4; - this.buffer = new byte[bufferLength]; - this.position = 0; - this.lineLength = 0; - this.suspendEncoding = false; - this.b4 = new byte[4]; - this.options = options; - this.decodabet = getDecodabet(options); - } // end constructor - - - /** - * Writes the byte to the output stream after - * converting to/from Base64 notation. - * When encoding, bytes are buffered three - * at a time before the output stream actually - * gets a write() call. - * When decoding, bytes are buffered four - * at a time. - * - * @param theByte the byte to write - * @since 1.3 - */ - @Override - public void write(int theByte) - throws java.io.IOException { - // Encoding suspended? - if (suspendEncoding) { - this.out.write(theByte); - return; - } // end if: supsended - - // Encode? - if (encode) { - buffer[position++] = (byte) theByte; - if (position >= bufferLength) { // Enough to encode. - - this.out.write(encode3to4(b4, buffer, bufferLength, options)); - - lineLength += 4; - if (breakLines && lineLength >= MAX_LINE_LENGTH) { - this.out.write(NEW_LINE); - lineLength = 0; - } // end if: end of line - - position = 0; - } // end if: enough to output - } // end if: encoding - - // Else, Decoding - else { - // Meaningful Base64 character? - if (decodabet[theByte & 0x7f] > WHITE_SPACE_ENC) { - buffer[position++] = (byte) theByte; - if (position >= bufferLength) { // Enough to output. - - int len = Base64.decode4to3(buffer, 0, b4, 0, options); - out.write(b4, 0, len); - position = 0; - } // end if: enough to output - } // end if: meaningful base64 character - else if (decodabet[theByte & 0x7f] != WHITE_SPACE_ENC) { - throw new java.io.IOException("Invalid character in Base64 data."); - } // end else: not white space either - } // end else: decoding - } // end write - - - /** - * Calls {@link #write(int)} repeatedly until len - * bytes are written. - * - * @param theBytes array from which to read bytes - * @param off offset for array - * @param len max number of bytes to read into array - * @since 1.3 - */ - @Override - public void write(byte[] theBytes, int off, int len) - throws java.io.IOException { - // Encoding suspended? - if (suspendEncoding) { - this.out.write(theBytes, off, len); - return; - } // end if: supsended - - for (int i = 0; i < len; i++) { - write(theBytes[off + i]); - } // end for: each byte written - - } // end write - - - /** - * Method added by PHIL. [Thanks, PHIL. -Rob] - * This pads the buffer without closing the stream. - * - * @throws java.io.IOException if there's an error. - */ - public void flushBase64() throws java.io.IOException { - if (position > 0) { - if (encode) { - out.write(encode3to4(b4, buffer, position, options)); - position = 0; - } // end if: encoding - else { - throw new java.io.IOException("Base64 input not properly padded."); - } // end else: decoding - } // end if: buffer partially full - - } // end flush - - - /** - * Flushes and closes (I think, in the superclass) the stream. - * - * @since 1.3 - */ - @Override - public void close() throws java.io.IOException { - // 1. Ensure that pending characters are written - flushBase64(); - - // 2. Actually close the stream - // Base class both flushes and closes. - super.close(); - - buffer = null; - out = null; - } // end close - - - /** - * Suspends encoding of the stream. - * May be helpful if you need to embed a piece of - * base64-encoded data in a stream. - * - * @throws java.io.IOException if there's an error flushing - * @since 1.5.1 - */ - public void suspendEncoding() throws java.io.IOException { - flushBase64(); - this.suspendEncoding = true; - } // end suspendEncoding - - - /** - * Resumes encoding of the stream. - * May be helpful if you need to embed a piece of - * base64-encoded data in a stream. - * - * @since 1.5.1 - */ - public void resumeEncoding() { - this.suspendEncoding = false; - } // end resumeEncoding - - - } // end inner class OutputStream - - -} // end class Base64 \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/types/ECPointArithmetic.java b/core/src/main/java/com/web3auth/core/types/ECPointArithmetic.java deleted file mode 100644 index 7dc91b0..0000000 --- a/core/src/main/java/com/web3auth/core/types/ECPointArithmetic.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.web3auth.core.types; - -import java.math.BigInteger; -import java.security.spec.ECFieldFp; -import java.security.spec.EllipticCurve; - -// http://stackoverflow.com/questions/11190860/point-multiplication-in-elliptic-curvves -public class ECPointArithmetic { - EllipticCurve ec; - ECFieldFp ef; - private final BigInteger x; - private final BigInteger y; - private final BigInteger z; - private BigInteger zinv; - private final BigInteger one = BigInteger.ONE; - private final BigInteger zero = BigInteger.ZERO; - private boolean infinity; - - public ECPointArithmetic(EllipticCurve ec, BigInteger x, BigInteger y, BigInteger z) { - this.ec = ec; - this.x = x; - this.y = y; - this.ef = (ECFieldFp) ec.getField(); - - // Projective coordinates: either zinv == null or z * zinv == 1 - // z and zinv are just BigIntegers, not fieldElements - if (z == null) { - this.z = BigInteger.ONE; - } else { - this.z = z; - } - this.zinv = null; - infinity = false; - } - - public BigInteger getX() { - if (this.zinv == null) { - this.zinv = this.z.modInverse(this.ef.getP()); - } - return this.x.multiply(this.zinv).mod(this.ef.getP()); - } - - public BigInteger getY() { - if (this.zinv == null) { - this.zinv = this.z.modInverse(this.ef.getP()); - } - return this.y.multiply(this.zinv).mod(this.ef.getP()); - } - - public boolean pointEquals(ECPointArithmetic other) { - if (other == this) { - return true; - } - if (this.isInfinity()) { - return other.isInfinity(); - } - if (other.isInfinity()) { - return this.isInfinity(); - } - BigInteger u, v; - // u = Y2 * Z1 - Y1 * Z2 - u = other.y.multiply(this.z).subtract(this.y.multiply(other.z)).mod(this.ef.getP()); - if (!u.equals(BigInteger.ZERO)) { - return false; - } - // v = X2 * Z1 - X1 * Z2 - v = other.x.multiply(this.z).subtract(this.x.multiply(other.z)).mod(this.ef.getP()); - return v.equals(BigInteger.ZERO); - } - - public boolean isInfinity() { - - if ((this.x == zero) && (this.y == zero)) { - return true; - } - return this.z.equals(BigInteger.ZERO) && !this.y.equals(BigInteger.ZERO); - - } - - public ECPointArithmetic negate() { - return new ECPointArithmetic(this.ec, this.x, this.y.negate(), this.z); - } - - public ECPointArithmetic add(ECPointArithmetic b) { - if (this.isInfinity()) { - return b; - } - if (b.isInfinity()) { - return this; - } - ECPointArithmetic R = new ECPointArithmetic(this.ec, zero, zero, null); - // u = Y2 * Z1 - Y1 * Z2 - BigInteger u = b.y.multiply(this.z).subtract(this.y.multiply(b.z)).mod(this.ef.getP()); - // v = X2 * Z1 - X1 * Z2 - BigInteger v = b.x.multiply(this.z).subtract(this.x.multiply(b.z)).mod(this.ef.getP()); - - if (BigInteger.ZERO.equals(v)) { - if (BigInteger.ZERO.equals(u)) { - return this.twice(); // this == b, so double - } - - infinity = true; // this = -b, so infinity - return R; - } - - BigInteger THREE = new BigInteger("3"); - BigInteger x1 = this.x; - BigInteger y1 = this.y; - BigInteger x2 = b.x; - BigInteger y2 = b.y; - - BigInteger v2 = v.pow(2); - BigInteger v3 = v2.multiply(v); - BigInteger x1v2 = x1.multiply(v2); - BigInteger zu2 = u.pow(2).multiply(this.z); - - // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) - BigInteger x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.ef.getP()); - - // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 - BigInteger y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.ef.getP()); - - // z3 = v^3 * z1 * z2 - BigInteger z3 = v3.multiply(this.z).multiply(b.z).mod(this.ef.getP()); - - return new ECPointArithmetic(this.ec, x3, y3, z3); - } - - public ECPointArithmetic twice() { - if (this.isInfinity()) { - return this; - } - ECPointArithmetic R = new ECPointArithmetic(this.ec, zero, zero, null); - if (this.y.signum() == 0) { - infinity = true; - return R; - } - - BigInteger THREE = new BigInteger("3"); - BigInteger x1 = this.x; - BigInteger y1 = this.y; - - BigInteger y1z1 = y1.multiply(this.z); - BigInteger y1sqz1 = y1z1.multiply(y1).mod(this.ef.getP()); - BigInteger a = this.ec.getA(); - - // w = 3 * x1^2 + a * z1^2 - BigInteger w = x1.pow(2).multiply(THREE); - - if (!BigInteger.ZERO.equals(a)) { - w = w.add(this.z.pow(2).multiply(a)); - } - - w = w.mod(this.ef.getP()); - - // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) - BigInteger x3 = w.pow(2).subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.ef.getP()); - - // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 - BigInteger y3 = (w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1))).shiftLeft(2).multiply(y1sqz1).subtract(w.pow(2).multiply(w)).mod(this.ef.getP()); - - // z3 = 8 * (y1 * z1)^3 - BigInteger z3 = y1z1.pow(2).multiply(y1z1).shiftLeft(3).mod(this.ef.getP()); - - return new ECPointArithmetic(this.ec, x3, y3, z3); - } - - public ECPointArithmetic multiply(BigInteger k) { - if (this.isInfinity()) { - return this; - } - - ECPointArithmetic R = new ECPointArithmetic(this.ec, zero, zero, null); - if (k.signum() == 0) { - infinity = true; - return R; - } - - BigInteger e = k; - BigInteger h = e.multiply(new BigInteger("3")); - - ECPointArithmetic neg = this.negate(); - R = this; - - int i; - for (i = h.bitLength() - 2; i > 0; --i) { - R = R.twice(); - boolean hBit = h.testBit(i); - boolean eBit = e.testBit(i); - - if (hBit != eBit) { - R = R.add(hBit ? this : neg); - } - } - - return R; - } -} \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/types/SHA512.java b/core/src/main/java/com/web3auth/core/types/SHA512.java deleted file mode 100644 index 31f8efb..0000000 --- a/core/src/main/java/com/web3auth/core/types/SHA512.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.web3auth.core.types; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class SHA512 { - public static byte[] digest(byte[] buf) throws NoSuchAlgorithmException { - MessageDigest digest = MessageDigest.getInstance("SHA-512"); - digest.update(buf); - return digest.digest(); - } -} diff --git a/core/src/main/java/com/web3auth/core/types/ShareMetadata.kt b/core/src/main/java/com/web3auth/core/types/ShareMetadata.kt deleted file mode 100644 index 6ddbb4e..0000000 --- a/core/src/main/java/com/web3auth/core/types/ShareMetadata.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.web3auth.core.types - -import androidx.annotation.Keep - -@Keep -data class ShareMetadata( - val iv: String? = null, - val ephemPublicKey: String? = null, - val ciphertext: String? = null, - val mac: String? = null -) \ No newline at end of file diff --git a/core/src/main/java/com/web3auth/core/types/TorusException.kt b/core/src/main/java/com/web3auth/core/types/TorusException.kt deleted file mode 100644 index f3fd7f3..0000000 --- a/core/src/main/java/com/web3auth/core/types/TorusException.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.web3auth.core.types - -class TorusException : Exception { - constructor(msg: String?) : super(msg) - constructor(msg: String?, err: Throwable?) : super(msg, err) -} \ No newline at end of file From e9d5f35dede96d1b2e2c43c3624d390bb07e632c Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Wed, 10 May 2023 08:28:54 +0530 Subject: [PATCH 3/8] code cleaning. Signed-off-by: Gaurav Goel --- .../main/java/com/web3auth/core/Web3Auth.kt | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/com/web3auth/core/Web3Auth.kt b/core/src/main/java/com/web3auth/core/Web3Auth.kt index ebc6633..49f4525 100644 --- a/core/src/main/java/com/web3auth/core/Web3Auth.kt +++ b/core/src/main/java/com/web3auth/core/Web3Auth.kt @@ -2,10 +2,7 @@ package com.web3auth.core import android.content.Intent import android.net.Uri -import android.os.Handler -import android.os.Looper import androidx.browser.customtabs.CustomTabsIntent -import androidx.core.os.postDelayed import com.google.gson.GsonBuilder import com.web3auth.core.api.ApiHelper import com.web3auth.core.keystore.KeyStoreManagerUtils @@ -183,27 +180,21 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) { web3AuthResponse = gson.fromJson(tempJson.toString(), Web3AuthResponse::class.java) if (web3AuthResponse.error?.isNotBlank() == true) { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.completeExceptionally( - UnKnownException( - web3AuthResponse.error ?: Web3AuthError.getError( - ErrorCode.SOMETHING_WENT_WRONG - ) + sessionCompletableFuture.completeExceptionally( + UnKnownException( + web3AuthResponse.error ?: Web3AuthError.getError( + ErrorCode.SOMETHING_WENT_WRONG ) ) - } + ) } else if (web3AuthResponse.privKey.isNullOrBlank()) { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.completeExceptionally( - Exception( - Web3AuthError.getError(ErrorCode.SOMETHING_WENT_WRONG) - ) + sessionCompletableFuture.completeExceptionally( + Exception( + Web3AuthError.getError(ErrorCode.SOMETHING_WENT_WRONG) ) - } + ) } else { - Handler(Looper.getMainLooper()).postDelayed(10) { - sessionCompletableFuture.complete(web3AuthResponse) - } + sessionCompletableFuture.complete(web3AuthResponse) } } else { sessionCompletableFuture.completeExceptionally( From 10c05d90c7371073416b5be9ffa4e42211e162ed Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Tue, 16 May 2023 14:14:31 +0530 Subject: [PATCH 4/8] Updated android library deps Signed-off-by: Gaurav Goel --- core/build.gradle | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 51d8cea..ada0b32 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -47,24 +47,24 @@ dependencies { api 'net.sourceforge.streamsupport:streamsupport-cfuture:1.7.4' // Custom Tabs - implementation 'androidx.browser:browser:1.4.0' + implementation 'androidx.browser:browser:1.5.0' // Encoding - implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.google.code.gson:gson:2.9.1' // retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' - implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0' + implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0' // Gson implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // coroutine - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' // android security - implementation 'androidx.security:security-crypto:1.1.0-alpha05' + implementation 'androidx.security:security-crypto:1.1.0-alpha06' implementation 'org.web3j:core:4.8.8-android' //session-manager-sdk @@ -72,8 +72,8 @@ dependencies { // Test testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } project.afterEvaluate { From 3f77ffff0108346e1654949beeb6ca0929c35a2b Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Tue, 16 May 2023 14:25:38 +0530 Subject: [PATCH 5/8] Modified sharedpreferences initialization code Signed-off-by: Gaurav Goel --- .../web3auth/core/keystore/KeyStoreManagerUtils.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt b/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt index 0417781..6417252 100644 --- a/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt +++ b/core/src/main/java/com/web3auth/core/keystore/KeyStoreManagerUtils.kt @@ -4,7 +4,7 @@ import android.content.Context import android.security.keystore.KeyGenParameterSpec import android.security.keystore.KeyProperties import androidx.security.crypto.EncryptedSharedPreferences -import androidx.security.crypto.MasterKeys +import androidx.security.crypto.MasterKey import java.security.KeyStore import javax.crypto.Cipher import javax.crypto.KeyGenerator @@ -18,16 +18,17 @@ object KeyStoreManagerUtils { private const val Android_KEY_STORE = "AndroidKeyStore" private const val WEB3AUTH = "Web3Auth" private lateinit var encryptedPairData: Pair - - private val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) private lateinit var sharedPreferences: EncryptedSharedPreferences fun initializePreferences(context: Context) { try { + val keyGenParameterSpec = MasterKey.Builder(context) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build() sharedPreferences = EncryptedSharedPreferences.create( - "Web3Auth", - masterKeyAlias, context, + "Web3Auth", + keyGenParameterSpec, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) as EncryptedSharedPreferences From 6333dcf21783a1c0847d6e453003269cb9e68832 Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Wed, 17 May 2023 15:09:03 +0530 Subject: [PATCH 6/8] Modified sharedpreferences initialization code Signed-off-by: Gaurav Goel --- app/src/main/java/com/web3auth/app/MainActivity.kt | 11 ++++++++--- core/build.gradle | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/web3auth/app/MainActivity.kt b/app/src/main/java/com/web3auth/app/MainActivity.kt index 2b113e9..b7516d6 100644 --- a/app/src/main/java/com/web3auth/app/MainActivity.kt +++ b/app/src/main/java/com/web3auth/app/MainActivity.kt @@ -17,10 +17,10 @@ import java8.util.concurrent.CompletableFuture import org.json.JSONObject import java.util.concurrent.atomic.AtomicBoolean - class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener { private lateinit var web3Auth: Web3Auth private val isLoginCompleted = AtomicBoolean(false) + private var count = 0 private val verifierList: List = listOf( LoginVerifier("Google", Provider.GOOGLE), @@ -55,7 +55,6 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener { LoginParams(selectedLoginProvider, extraLoginOptions = extraLoginOptions) ) loginCompletableFuture.whenComplete { _, error -> - isLoginCompleted.set(true) if (error == null) { reRender() println("PrivKey: " + web3Auth.getPrivkey()) @@ -173,14 +172,20 @@ class MainActivity : AppCompatActivity(), AdapterView.OnItemClickListener { override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) web3Auth.setResultUrl(intent?.data) + isLoginCompleted.set(true) } override fun onResume() { super.onResume() if (isLoginCompleted.get()) { isLoginCompleted.set(false) + count = 0 } else { - println("User closed the browser.") + if (count > 0) { + Toast.makeText(this, "User closed the browser.", Toast.LENGTH_SHORT).show() + web3Auth.setResultUrl(null) + } + count++ } } diff --git a/core/build.gradle b/core/build.gradle index ada0b32..36e8ae8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation 'org.web3j:core:4.8.8-android' //session-manager-sdk - implementation 'com.github.grvgoel81:session-manager-android:0.0.1' + implementation 'com.github.Web3Auth:session-manager-android:0.0.1' // Test testImplementation 'junit:junit:4.+' From c011feda65c9c69666567091505e0be1002aebbc Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Wed, 17 May 2023 16:01:38 +0530 Subject: [PATCH 7/8] README.md updated Signed-off-by: Gaurav Goel --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a04727b..b56109b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Checkout the official [Web3Auth Documentation](https://web3auth.io/docs) and [SD ## ⏪ Requirements -- Android API version 21 or newer is required. +- Android API version 24 or newer is required. ## ⚡ Installation From 618b876b04432c73afa89f43c9ce64dec7d85602 Mon Sep 17 00:00:00 2001 From: Gaurav Goel Date: Mon, 22 May 2023 12:31:36 +0530 Subject: [PATCH 8/8] bump session-manager-android sdk version Signed-off-by: Gaurav Goel --- core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/build.gradle b/core/build.gradle index 36e8ae8..146ed85 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -68,7 +68,7 @@ dependencies { implementation 'org.web3j:core:4.8.8-android' //session-manager-sdk - implementation 'com.github.Web3Auth:session-manager-android:0.0.1' + implementation 'com.github.Web3Auth:session-manager-android:0.0.2' // Test testImplementation 'junit:junit:4.+'