From 3473af873d17aed1ee76ec9abef5a5623b73acd1 Mon Sep 17 00:00:00 2001 From: T8RIN Date: Fri, 3 Jan 2025 02:36:40 +0300 Subject: [PATCH] Added 59 hashing algorithms from bouncycastle api --- app/build.gradle.kts | 13 +- app/proguard-rules.pro | 5 +- .../components/ImageToolboxApplication.kt | 12 + .../core/domain/model/ChecksumType.kt | 34 +- .../core/domain/model/KnownOIDs.kt | 456 ++++++++++++++++++ .../resources/src/main/res/values/strings.xml | 1 + .../widget/controls/selection/DataSelector.kt | 47 +- .../ChecksumAsFilenameSettingItem.kt | 56 +-- gradle/libs.versions.toml | 4 + 9 files changed, 570 insertions(+), 58 deletions(-) create mode 100644 core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/KnownOIDs.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 976c987ae..f9ef2111c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -86,11 +86,12 @@ android { pickFirsts.add("lib/*/libcoder.so") } resources { - excludes += "META-INF/" - excludes += "kotlin/" - excludes += "org/" - excludes += ".properties" - excludes += ".bin" + excludes += "META-INF/*" + excludes += "kotlin/*" + excludes += "org/*" + excludes += "*.properties" + excludes += "*.bin" + excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF" } } @@ -104,6 +105,8 @@ dependencies { implementation(projects.feature.root) implementation(projects.feature.mediaPicker) implementation(projects.feature.quickTiles) + implementation(libs.bouncycastle.pkix) + implementation(libs.bouncycastle.provider) } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index e4aa0efae..7fbc16388 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -49,4 +49,7 @@ -dontwarn org.openjsse.javax.net.ssl.SSLSocket -dontwarn org.openjsse.net.ssl.OpenJSSE --keep class org.beyka.tiffbitmapfactory.**{ *; } \ No newline at end of file +-keep class org.beyka.tiffbitmapfactory.**{ *; } + +-keep class org.bouncycastle.jcajce.provider.** { *; } +-keep class org.bouncycastle.jce.provider.** { *; } \ No newline at end of file diff --git a/app/src/main/java/ru/tech/imageresizershrinker/app/presentation/components/ImageToolboxApplication.kt b/app/src/main/java/ru/tech/imageresizershrinker/app/presentation/components/ImageToolboxApplication.kt index ea3b3b800..b32831324 100644 --- a/app/src/main/java/ru/tech/imageresizershrinker/app/presentation/components/ImageToolboxApplication.kt +++ b/app/src/main/java/ru/tech/imageresizershrinker/app/presentation/components/ImageToolboxApplication.kt @@ -21,11 +21,23 @@ import android.app.Application import com.arkivanov.decompose.DecomposeExperimentFlags import com.arkivanov.decompose.ExperimentalDecomposeApi import dagger.hilt.android.HiltAndroidApp +import org.bouncycastle.jce.provider.BouncyCastleProvider +import ru.tech.imageresizershrinker.core.domain.model.ChecksumType +import java.security.Security @HiltAndroidApp class ImageToolboxApplication : Application() { + init { + Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME) + Security.addProvider(BouncyCastleProvider()) + ChecksumType.registerSecurityMessageDigests( + Security.getAlgorithms("MessageDigest") + .filterNotNull() + ) + } + @OptIn(ExperimentalDecomposeApi::class) override fun onCreate() { super.onCreate() diff --git a/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/ChecksumType.kt b/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/ChecksumType.kt index f32465d71..b67559a41 100644 --- a/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/ChecksumType.kt +++ b/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/ChecksumType.kt @@ -17,11 +17,11 @@ package ru.tech.imageresizershrinker.core.domain.model -class ChecksumType private constructor( - val digest: String +@ConsistentCopyVisibility +data class ChecksumType private constructor( + val digest: String, + val name: String = digest ) { - override fun toString(): String = "ChecksumType($digest)" - companion object { val MD5 = ChecksumType("MD5") val SHA_1 = ChecksumType("SHA-1") @@ -30,7 +30,29 @@ class ChecksumType private constructor( val SHA_384 = ChecksumType("SHA-384") val SHA_512 = ChecksumType("SHA-512") + private var securityMessageDigests: List? = null + + fun registerSecurityMessageDigests(digests: List) { + if (!securityMessageDigests.isNullOrEmpty()) { + throw IllegalArgumentException("SecurityMessageDigests already registered") + } + securityMessageDigests = digests.distinctBy { it.replace("OID.", "") } + } + val entries: List by lazy { + val available = securityMessageDigests?.mapNotNull { messageDigest -> + if (messageDigest.isEmpty()) null + else { + val digest = messageDigest.replace("OID.", "") + KnownOIDs.findMatch(digest)?.let { oid -> + ChecksumType( + digest = messageDigest, + name = oid.stdName + ) + } ?: ChecksumType(digest = messageDigest) + } + }?.sortedBy { it.digest } ?: emptyList() + listOf( MD5, SHA_1, @@ -38,7 +60,9 @@ class ChecksumType private constructor( SHA_256, SHA_384, SHA_512, - ) + ).let { + it + available + }.distinctBy { it.name.replace("-", "") } } fun fromString( diff --git a/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/KnownOIDs.kt b/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/KnownOIDs.kt new file mode 100644 index 000000000..e0c5b4398 --- /dev/null +++ b/core/domain/src/main/kotlin/ru/tech/imageresizershrinker/core/domain/model/KnownOIDs.kt @@ -0,0 +1,456 @@ +/* + * ImageToolbox is an image editor for android + * Copyright (c) 2025 T8RIN (Malik Mukhametzyanov) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * You should have received a copy of the Apache License + * along with this program. If not, see . + */ +@file:Suppress("EnumEntryName", "unused") + +package ru.tech.imageresizershrinker.core.domain.model + +/** + * This utility class maps algorithm name to the corresponding oid strings. + * NOTE: for 100% backward compatibility, the standard name for the enum + * is determined by existing usage and may be in lowercase/uppercase in + * order to match existing output. + */ +enum class KnownOIDs { + // X.500 Attributes 2.5.4.* + CommonName("2.5.4.3"), + Surname("2.5.4.4"), + SerialNumber("2.5.4.5"), + CountryName("2.5.4.6"), + LocalityName("2.5.4.7"), + StateName("2.5.4.8"), + StreetAddress("2.5.4.9"), + OrgName("2.5.4.10"), + OrgUnitName("2.5.4.11"), + Title("2.5.4.12"), + GivenName("2.5.4.42"), + Initials("2.5.4.43"), + GenerationQualifier("2.5.4.44"), + DNQualifier("2.5.4.46"), + + // Certificate Extension 2.5.29.* + SubjectDirectoryAttributes("2.5.29.9"), + SubjectKeyID("2.5.29.14"), + KeyUsage("2.5.29.15"), + PrivateKeyUsage("2.5.29.16"), + SubjectAlternativeName("2.5.29.17"), + IssuerAlternativeName("2.5.29.18"), + BasicConstraints("2.5.29.19"), + CRLNumber("2.5.29.20"), + ReasonCode("2.5.29.21"), + HoldInstructionCode("2.5.29.23"), + InvalidityDate("2.5.29.24"), + DeltaCRLIndicator("2.5.29.27"), + IssuingDistributionPoint("2.5.29.28"), + CertificateIssuer("2.5.29.29"), + NameConstraints("2.5.29.30"), + CRLDistributionPoints("2.5.29.31"), + CertificatePolicies("2.5.29.32"), + CE_CERT_POLICIES_ANY("2.5.29.32.0"), + PolicyMappings("2.5.29.33"), + AuthorityKeyID("2.5.29.35"), + PolicyConstraints("2.5.29.36"), + extendedKeyUsage("2.5.29.37"), + anyExtendedKeyUsage("2.5.29.37.0"), + FreshestCRL("2.5.29.46"), + InhibitAnyPolicy("2.5.29.54"), + + // PKIX 1.3.6.1.5.5.7. + AuthInfoAccess("1.3.6.1.5.5.7.1.1"), + SubjectInfoAccess("1.3.6.1.5.5.7.1.11"), + + // key usage purposes - PKIX.3.* + serverAuth("1.3.6.1.5.5.7.3.1"), + clientAuth("1.3.6.1.5.5.7.3.2"), + codeSigning("1.3.6.1.5.5.7.3.3"), + emailProtection("1.3.6.1.5.5.7.3.4"), + ipsecEndSystem("1.3.6.1.5.5.7.3.5"), + ipsecTunnel("1.3.6.1.5.5.7.3.6"), + ipsecUser("1.3.6.1.5.5.7.3.7"), + KP_TimeStamping("1.3.6.1.5.5.7.3.8", "timeStamping"), + OCSPSigning("1.3.6.1.5.5.7.3.9"), + + // access descriptors - PKIX.48.* + OCSP("1.3.6.1.5.5.7.48.1"), + OCSPBasicResponse("1.3.6.1.5.5.7.48.1.1"), + OCSPNonceExt("1.3.6.1.5.5.7.48.1.2"), + OCSPNoCheck("1.3.6.1.5.5.7.48.1.5"), + caIssuers("1.3.6.1.5.5.7.48.2"), + AD_TimeStamping("1.3.6.1.5.5.7.48.3", "timeStamping"), + caRepository("1.3.6.1.5.5.7.48.5", "caRepository"), + + // NIST -- + // AES 2.16.840.1.101.3.4.1.* + AES("2.16.840.1.101.3.4.1"), + AES_128_ECB_NoPadding("2.16.840.1.101.3.4.1.1", "AES_128/ECB/NoPadding"), + AES_128_CBC_NoPadding("2.16.840.1.101.3.4.1.2", "AES_128/CBC/NoPadding"), + AES_128_OFB_NoPadding("2.16.840.1.101.3.4.1.3", "AES_128/OFB/NoPadding"), + AES_128_CFB_NoPadding("2.16.840.1.101.3.4.1.4", "AES_128/CFB/NoPadding"), + AES_128_KW_NoPadding( + "2.16.840.1.101.3.4.1.5", "AES_128/KW/NoPadding", + "AESWrap_128" + ), + AES_128_GCM_NoPadding("2.16.840.1.101.3.4.1.6", "AES_128/GCM/NoPadding"), + AES_128_KWP_NoPadding( + "2.16.840.1.101.3.4.1.8", "AES_128/KWP/NoPadding", + "AESWrapPad_128" + ), + + AES_192_ECB_NoPadding("2.16.840.1.101.3.4.1.21", "AES_192/ECB/NoPadding"), + AES_192_CBC_NoPadding("2.16.840.1.101.3.4.1.22", "AES_192/CBC/NoPadding"), + AES_192_OFB_NoPadding("2.16.840.1.101.3.4.1.23", "AES_192/OFB/NoPadding"), + AES_192_CFB_NoPadding("2.16.840.1.101.3.4.1.24", "AES_192/CFB/NoPadding"), + AES_192_KW_NoPadding( + "2.16.840.1.101.3.4.1.25", "AES_192/KW/NoPadding", + "AESWrap_192" + ), + AES_192_GCM_NoPadding("2.16.840.1.101.3.4.1.26", "AES_192/GCM/NoPadding"), + AES_192_KWP_NoPadding( + "2.16.840.1.101.3.4.1.28", "AES_192/KWP/NoPadding", + "AESWrapPad_192" + ), + + AES_256_ECB_NoPadding("2.16.840.1.101.3.4.1.41", "AES_256/ECB/NoPadding"), + AES_256_CBC_NoPadding("2.16.840.1.101.3.4.1.42", "AES_256/CBC/NoPadding"), + AES_256_OFB_NoPadding("2.16.840.1.101.3.4.1.43", "AES_256/OFB/NoPadding"), + AES_256_CFB_NoPadding("2.16.840.1.101.3.4.1.44", "AES_256/CFB/NoPadding"), + AES_256_KW_NoPadding( + "2.16.840.1.101.3.4.1.45", "AES_256/KW/NoPadding", + "AESWrap_256" + ), + AES_256_GCM_NoPadding("2.16.840.1.101.3.4.1.46", "AES_256/GCM/NoPadding"), + AES_256_KWP_NoPadding( + "2.16.840.1.101.3.4.1.48", "AES_256/KWP/NoPadding", + "AESWrapPad_256" + ), + + // hashAlgs 2.16.840.1.101.3.4.2.* + SHA_256("2.16.840.1.101.3.4.2.1", "SHA-256", "SHA256"), + SHA_384("2.16.840.1.101.3.4.2.2", "SHA-384", "SHA384"), + SHA_512("2.16.840.1.101.3.4.2.3", "SHA-512", "SHA512"), + SHA_224("2.16.840.1.101.3.4.2.4", "SHA-224", "SHA224"), + SHA_512_224("2.16.840.1.101.3.4.2.5", "SHA-512/224", "SHA512/224"), + SHA_512_256("2.16.840.1.101.3.4.2.6", "SHA-512/256", "SHA512/256"), + SHA3_224("2.16.840.1.101.3.4.2.7", "SHA3-224"), + SHA3_256("2.16.840.1.101.3.4.2.8", "SHA3-256"), + SHA3_384("2.16.840.1.101.3.4.2.9", "SHA3-384"), + SHA3_512("2.16.840.1.101.3.4.2.10", "SHA3-512"), + SHAKE128("2.16.840.1.101.3.4.2.11"), + SHAKE256("2.16.840.1.101.3.4.2.12"), + HmacSHA3_224("2.16.840.1.101.3.4.2.13", "HmacSHA3-224"), + HmacSHA3_256("2.16.840.1.101.3.4.2.14", "HmacSHA3-256"), + HmacSHA3_384("2.16.840.1.101.3.4.2.15", "HmacSHA3-384"), + HmacSHA3_512("2.16.840.1.101.3.4.2.16", "HmacSHA3-512"), + SHAKE128_LEN("2.16.840.1.101.3.4.2.17", "SHAKE128-LEN"), + SHAKE256_LEN("2.16.840.1.101.3.4.2.18", "SHAKE256-LEN"), + SHA512_224("1.0.10118.3.0.55", "SHA-512/224"), + SHA512_256("2.16.840.1.101.3.4.2.12", "SHA-512/256"), + SHA384("2.16.840.1.101.3.4.2.11", "SHA-384"), + SHA512("2.16.840.1.101.3.4.2.10", "SHA-512"), + DSTU7564_256("1.2.804.2.1.1.1.1.2.2.3", "DSTU-7564-256"), + DSTU7564_384("1.2.804.2.1.1.1.1.2.2.2", "DSTU-7564-384"), + DSTU7564_512("1.2.804.2.1.1.1.1.2.2.1", "DSTU-7564-512"), + SHA224("2.16.840.1.101.3.4.2.9", "SHA-224"), + SHA256("2.16.840.1.101.3.4.2.8", "SHA-256"), + SHA1("2.16.840.1.101.3.4.2.7", "SHA-1"), + + // sigAlgs 2.16.840.1.101.3.4.3.* + SHA224withDSA("2.16.840.1.101.3.4.3.1"), + SHA256withDSA("2.16.840.1.101.3.4.3.2"), + SHA384withDSA("2.16.840.1.101.3.4.3.3"), + SHA512withDSA("2.16.840.1.101.3.4.3.4"), + SHA3_224withDSA("2.16.840.1.101.3.4.3.5", "SHA3-224withDSA"), + SHA3_256withDSA("2.16.840.1.101.3.4.3.6", "SHA3-256withDSA"), + SHA3_384withDSA("2.16.840.1.101.3.4.3.7", "SHA3-384withDSA"), + SHA3_512withDSA("2.16.840.1.101.3.4.3.8", "SHA3-512withDSA"), + SHA3_224withECDSA("2.16.840.1.101.3.4.3.9", "SHA3-224withECDSA"), + SHA3_256withECDSA("2.16.840.1.101.3.4.3.10", "SHA3-256withECDSA"), + SHA3_384withECDSA("2.16.840.1.101.3.4.3.11", "SHA3-384withECDSA"), + SHA3_512withECDSA("2.16.840.1.101.3.4.3.12", "SHA3-512withECDSA"), + SHA3_224withRSA("2.16.840.1.101.3.4.3.13", "SHA3-224withRSA"), + SHA3_256withRSA("2.16.840.1.101.3.4.3.14", "SHA3-256withRSA"), + SHA3_384withRSA("2.16.840.1.101.3.4.3.15", "SHA3-384withRSA"), + SHA3_512withRSA("2.16.840.1.101.3.4.3.16", "SHA3-512withRSA"), + ML_DSA_44("2.16.840.1.101.3.4.3.17", "ML-DSA-44"), + ML_DSA_65("2.16.840.1.101.3.4.3.18", "ML-DSA-65"), + ML_DSA_87("2.16.840.1.101.3.4.3.19", "ML-DSA-87"), + + // kems 2.16.840.1.101.3.4.4.* + ML_KEM_512("2.16.840.1.101.3.4.4.1", "ML-KEM-512"), + ML_KEM_768("2.16.840.1.101.3.4.4.2", "ML-KEM-768"), + ML_KEM_1024("2.16.840.1.101.3.4.4.3", "ML-KEM-1024"), + + // RSASecurity + // PKCS1 1.2.840.113549.1.1.* + PKCS1("1.2.840.113549.1.1", "RSA"), + RSA("1.2.840.113549.1.1.1"), // RSA encryption + + MD2withRSA("1.2.840.113549.1.1.2"), + MD5withRSA("1.2.840.113549.1.1.4"), + SHA1withRSA("1.2.840.113549.1.1.5"), + OAEP("1.2.840.113549.1.1.7"), + MGF1("1.2.840.113549.1.1.8"), + PSpecified("1.2.840.113549.1.1.9"), + RSASSA_PSS("1.2.840.113549.1.1.10", "RSASSA-PSS", "PSS"), + SHA256withRSA("1.2.840.113549.1.1.11"), + SHA384withRSA("1.2.840.113549.1.1.12"), + SHA512withRSA("1.2.840.113549.1.1.13"), + SHA224withRSA("1.2.840.113549.1.1.14"), + SHA512_224withRSA("1.2.840.113549.1.1.15", "SHA512/224withRSA"), + SHA512_256withRSA("1.2.840.113549.1.1.16", "SHA512/256withRSA"), + + // PKCS3 1.2.840.113549.1.3.* + DiffieHellman("1.2.840.113549.1.3.1", "DiffieHellman", "DH"), + + // PKCS5 1.2.840.113549.1.5.* + PBEWithMD5AndDES("1.2.840.113549.1.5.3"), + PBEWithMD5AndRC2("1.2.840.113549.1.5.6"), + PBEWithSHA1AndDES("1.2.840.113549.1.5.10"), + PBEWithSHA1AndRC2("1.2.840.113549.1.5.11"), + PBKDF2WithHmacSHA1("1.2.840.113549.1.5.12"), + PBES2("1.2.840.113549.1.5.13"), + + // PKCS7 1.2.840.113549.1.7.* + PKCS7("1.2.840.113549.1.7"), + Data("1.2.840.113549.1.7.1"), + SignedData("1.2.840.113549.1.7.2"), + JDK_OLD_Data("1.2.840.1113549.1.7.1"), // extra 1 in 4th component + JDK_OLD_SignedData("1.2.840.1113549.1.7.2"), + EnvelopedData("1.2.840.113549.1.7.3"), + SignedAndEnvelopedData("1.2.840.113549.1.7.4"), + DigestedData("1.2.840.113549.1.7.5"), + EncryptedData("1.2.840.113549.1.7.6"), + + // PKCS9 1.2.840.113549.1.9.* + EmailAddress("1.2.840.113549.1.9.1"), + UnstructuredName("1.2.840.113549.1.9.2"), + ContentType("1.2.840.113549.1.9.3"), + MessageDigest("1.2.840.113549.1.9.4"), + SigningTime("1.2.840.113549.1.9.5"), + CounterSignature("1.2.840.113549.1.9.6"), + ChallengePassword("1.2.840.113549.1.9.7"), + UnstructuredAddress("1.2.840.113549.1.9.8"), + ExtendedCertificateAttributes("1.2.840.113549.1.9.9"), + IssuerAndSerialNumber("1.2.840.113549.1.9.10"), + ExtensionRequest("1.2.840.113549.1.9.14"), + SMIMECapability("1.2.840.113549.1.9.15"), + TimeStampTokenInfo("1.2.840.113549.1.9.16.1.4"), + SigningCertificate("1.2.840.113549.1.9.16.2.12"), + SignatureTimestampToken("1.2.840.113549.1.9.16.2.14"), + HSSLMS("1.2.840.113549.1.9.16.3.17", "HSS/LMS"), + CHACHA20_POLY1305("1.2.840.113549.1.9.16.3.18", "CHACHA20-POLY1305"), + FriendlyName("1.2.840.113549.1.9.20"), + LocalKeyID("1.2.840.113549.1.9.21"), + CertTypeX509("1.2.840.113549.1.9.22.1"), + CMSAlgorithmProtection("1.2.840.113549.1.9.52"), + + // PKCS12 1.2.840.113549.1.12.* + PBEWithSHA1AndRC4_128("1.2.840.113549.1.12.1.1"), + PBEWithSHA1AndRC4_40("1.2.840.113549.1.12.1.2"), + PBEWithSHA1AndDESede("1.2.840.113549.1.12.1.3"), + PBEWithSHA1AndRC2_128("1.2.840.113549.1.12.1.5"), + PBEWithSHA1AndRC2_40("1.2.840.113549.1.12.1.6"), + PKCS8ShroudedKeyBag("1.2.840.113549.1.12.10.1.2"), + CertBag("1.2.840.113549.1.12.10.1.3"), + SecretBag("1.2.840.113549.1.12.10.1.5"), + + // digestAlgs 1.2.840.113549.2.* + MD2("1.2.840.113549.2.2"), + MD5("1.2.840.113549.2.5"), + HmacSHA1("1.2.840.113549.2.7"), + HmacSHA224("1.2.840.113549.2.8"), + HmacSHA256("1.2.840.113549.2.9"), + HmacSHA384("1.2.840.113549.2.10"), + HmacSHA512("1.2.840.113549.2.11"), + HmacSHA512_224("1.2.840.113549.2.12", "HmacSHA512/224"), + HmacSHA512_256("1.2.840.113549.2.13", "HmacSHA512/256"), + + // encryptionAlgs 1.2.840.113549.3.* + RC2_CBC_PKCS5Padding("1.2.840.113549.3.2", "RC2/CBC/PKCS5Padding", "RC2"), + ARCFOUR("1.2.840.113549.3.4", "ARCFOUR", "RC4"), + DESede_CBC_NoPadding("1.2.840.113549.3.7", "DESede/CBC/NoPadding"), + RC5_CBC_PKCS5Padding("1.2.840.113549.3.9", "RC5/CBC/PKCS5Padding"), + + // ANSI -- + // X9 1.2.840.10040.4.* + DSA("1.2.840.10040.4.1"), + SHA1withDSA("1.2.840.10040.4.3", "SHA1withDSA", "DSS"), + + // X9.62 1.2.840.10045.* + EC("1.2.840.10045.2.1"), + + //c2pnb163v1("1.2.840.10045.3.0.1", "X9.62 c2pnb163v1"), + //c2pnb163v2("1.2.840.10045.3.0.2", "X9.62 c2pnb163v2"), + //c2pnb163v3("1.2.840.10045.3.0.3", "X9.62 c2pnb163v3"), + //c2pnb176w1("1.2.840.10045.3.0.4", "X9.62 c2pnb176w1"), + c2tnb191v1("1.2.840.10045.3.0.5", "X9.62 c2tnb191v1"), + c2tnb191v2("1.2.840.10045.3.0.6", "X9.62 c2tnb191v2"), + c2tnb191v3("1.2.840.10045.3.0.7", "X9.62 c2tnb191v3"), + + //c2pnb208w1("1.2.840.10045.3.0.10", "X9.62 c2pnb208w1"), + c2tnb239v1("1.2.840.10045.3.0.11", "X9.62 c2tnb239v1"), + c2tnb239v2("1.2.840.10045.3.0.12", "X9.62 c2tnb239v2"), + c2tnb239v3("1.2.840.10045.3.0.13", "X9.62 c2tnb239v3"), + + //c2pnb272w1("1.2.840.10045.3.0.16", "X9.62 c2pnb272w1"), + //c2pnb304w1("1.2.840.10045.3.0.17", "X9.62 c2pnb304w1"), + c2tnb359v1("1.2.840.10045.3.0.18", "X9.62 c2tnb359v1"), + + //c2pnb368w1("1.2.840.10045.3.0.19", "X9.62 c2pnb368w1"), + c2tnb431r1("1.2.840.10045.3.0.20", "X9.62 c2tnb431r1"), + + secp192r1( + "1.2.840.10045.3.1.1", + "secp192r1", "NIST P-192", "X9.62 prime192v1" + ), + prime192v2("1.2.840.10045.3.1.2", "X9.62 prime192v2"), + prime192v3("1.2.840.10045.3.1.3", "X9.62 prime192v3"), + prime239v1("1.2.840.10045.3.1.4", "X9.62 prime239v1"), + prime239v2("1.2.840.10045.3.1.5", "X9.62 prime239v2"), + prime239v3("1.2.840.10045.3.1.6", "X9.62 prime239v3"), + secp256r1( + "1.2.840.10045.3.1.7", + "secp256r1", "NIST P-256", "X9.62 prime256v1" + ), + SHA1withECDSA("1.2.840.10045.4.1"), + SHA224withECDSA("1.2.840.10045.4.3.1"), + SHA256withECDSA("1.2.840.10045.4.3.2"), + SHA384withECDSA("1.2.840.10045.4.3.3"), + SHA512withECDSA("1.2.840.10045.4.3.4"), + SpecifiedSHA2withECDSA("1.2.840.10045.4.3"), + + // X9.42 1.2.840.10046.2.* + X942_DH("1.2.840.10046.2.1", "DiffieHellman"), + + // Teletrust 1.3.36.* + brainpoolP160r1("1.3.36.3.3.2.8.1.1.1"), + brainpoolP192r1("1.3.36.3.3.2.8.1.1.3"), + brainpoolP224r1("1.3.36.3.3.2.8.1.1.5"), + brainpoolP256r1("1.3.36.3.3.2.8.1.1.7"), + brainpoolP320r1("1.3.36.3.3.2.8.1.1.9"), + brainpoolP384r1("1.3.36.3.3.2.8.1.1.11"), + brainpoolP512r1("1.3.36.3.3.2.8.1.1.13"), + + // Certicom 1.3.132.* + sect163k1("1.3.132.0.1", "sect163k1", "NIST K-163"), + sect163r1("1.3.132.0.2"), + sect239k1("1.3.132.0.3"), + sect113r1("1.3.132.0.4"), + sect113r2("1.3.132.0.5"), + secp112r1("1.3.132.0.6"), + secp112r2("1.3.132.0.7"), + secp160r1("1.3.132.0.8"), + secp160k1("1.3.132.0.9"), + secp256k1("1.3.132.0.10"), + sect163r2("1.3.132.0.15", "sect163r2", "NIST B-163"), + sect283k1("1.3.132.0.16", "sect283k1", "NIST K-283"), + sect283r1("1.3.132.0.17", "sect283r1", "NIST B-283"), + + sect131r1("1.3.132.0.22"), + sect131r2("1.3.132.0.23"), + sect193r1("1.3.132.0.24"), + sect193r2("1.3.132.0.25"), + sect233k1("1.3.132.0.26", "sect233k1", "NIST K-233"), + sect233r1("1.3.132.0.27", "sect233r1", "NIST B-233"), + secp128r1("1.3.132.0.28"), + secp128r2("1.3.132.0.29"), + secp160r2("1.3.132.0.30"), + secp192k1("1.3.132.0.31"), + secp224k1("1.3.132.0.32"), + secp224r1("1.3.132.0.33", "secp224r1", "NIST P-224"), + secp384r1("1.3.132.0.34", "secp384r1", "NIST P-384"), + secp521r1("1.3.132.0.35", "secp521r1", "NIST P-521"), + sect409k1("1.3.132.0.36", "sect409k1", "NIST K-409"), + sect409r1("1.3.132.0.37", "sect409r1", "NIST B-409"), + sect571k1("1.3.132.0.38", "sect571k1", "NIST K-571"), + sect571r1("1.3.132.0.39", "sect571r1", "NIST B-571"), + + ECDH("1.3.132.1.12"), + + // OIW secsig 1.3.14.3.* + OIW_DES_CBC("1.3.14.3.2.7", "DES/CBC", "DES"), + + OIW_DSA("1.3.14.3.2.12", "DSA"), + + OIW_JDK_SHA1withDSA("1.3.14.3.2.13", "SHA1withDSA"), + + OIW_SHA1withRSA_Odd("1.3.14.3.2.15", "SHA1withRSA"), + + DESede("1.3.14.3.2.17", "DESede"), + + SHA_1("1.3.14.3.2.26", "SHA-1", "SHA", "SHA1"), + + OIW_SHA1withDSA("1.3.14.3.2.27", "SHA1withDSA"), + + OIW_SHA1withRSA("1.3.14.3.2.29", "SHA1withRSA"), + + // Thawte 1.3.101.* + X25519("1.3.101.110"), + X448("1.3.101.111"), + Ed25519("1.3.101.112"), + Ed448("1.3.101.113"), + + // University College London (UCL) 0.9.2342.19200300.* + UCL_UserID("0.9.2342.19200300.100.1.1"), + UCL_DomainComponent("0.9.2342.19200300.100.1.25"), + + // Netscape 2.16.840.1.113730.* + NETSCAPE_CertType("2.16.840.1.113730.1.1"), + NETSCAPE_CertSequence("2.16.840.1.113730.2.5"), + NETSCAPE_ExportApproved("2.16.840.1.113730.4.1"), + + // Oracle 2.16.840.1.113894.* + ORACLE_TrustedKeyUsage("2.16.840.1.113894.746875.1.1"), // Miscellaneous oids below which are legacy, and not well known + // Consider removing them in future releases when their usage + // have died out + + ITUX509_RSA("2.5.8.1.1", "RSA"), + + SkipIPAddress("1.3.6.1.4.1.42.2.11.2.1"), + JAVASOFT_JDKKeyProtector("1.3.6.1.4.1.42.2.17.1.1"), + JAVASOFT_JCEKeyProtector("1.3.6.1.4.1.42.2.19.1"), + MICROSOFT_ExportApproved("1.3.6.1.4.1.311.10.3.3"), + + Blowfish("1.3.6.1.4.1.3029.1.1.2"); + + val stdName: String + val oid: String + val aliases: Array + + constructor(oid: String) { + this.oid = oid + this.stdName = name // defaults to enum name + this.aliases = arrayOf() + } + + constructor( + oid: String, + stdName: String, + vararg aliases: String + ) { + this.oid = oid + this.stdName = stdName + this.aliases = aliases.toList().toTypedArray() + } + + companion object { + fun findMatch( + s: String + ): KnownOIDs? = KnownOIDs.entries.find { + it.oid == s || it.stdName == s || it.aliases.contains(s) + } + } +} diff --git a/core/resources/src/main/res/values/strings.xml b/core/resources/src/main/res/values/strings.xml index 99d75f456..5388a79c0 100644 --- a/core/resources/src/main/res/values/strings.xml +++ b/core/resources/src/main/res/values/strings.xml @@ -1533,4 +1533,5 @@ Output images will have name corresponding to their data checksum Free Software (Partner) More useful software in the partner channel of Android applications + Algorithm \ No newline at end of file diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/controls/selection/DataSelector.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/controls/selection/DataSelector.kt index aa28df550..20f4ab424 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/controls/selection/DataSelector.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/controls/selection/DataSelector.kt @@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding @@ -33,6 +34,7 @@ import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridS import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.KeyboardArrowDown +import androidx.compose.material3.Badge import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -41,6 +43,7 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -50,10 +53,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch +import ru.tech.imageresizershrinker.core.ui.utils.confetti.LocalConfettiHostState import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedChip import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton import ru.tech.imageresizershrinker.core.ui.widget.modifier.container import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges +import ru.tech.imageresizershrinker.core.ui.widget.modifier.scaleOnTap import ru.tech.imageresizershrinker.core.ui.widget.text.TitleItem @Composable @@ -66,6 +72,7 @@ fun DataSelector( itemContentText: @Composable (T) -> String, spanCount: Int = 3, modifier: Modifier = Modifier, + badgeContent: (@Composable RowScope.() -> Unit)? = null, shape: Shape = RoundedCornerShape(20.dp), color: Color = MaterialTheme.colorScheme.surface, selectedItemColor: Color = MaterialTheme.colorScheme.tertiary @@ -79,13 +86,39 @@ fun DataSelector( var expanded by rememberSaveable { mutableStateOf(false) } Row { val rotation by animateFloatAsState(if (expanded) 180f else 0f) - TitleItem( - text = title, - icon = titleIcon, - modifier = Modifier - .padding(top = 12.dp, start = 12.dp, bottom = 8.dp) - .weight(1f) - ) + Row( + modifier = Modifier.weight(1f), + verticalAlignment = Alignment.CenterVertically + ) { + TitleItem( + text = title, + icon = titleIcon, + modifier = Modifier + .padding(top = 12.dp, start = 12.dp, bottom = 8.dp) + .weight(1f, false) + ) + badgeContent?.let { + val scope = rememberCoroutineScope() + val confettiHostState = LocalConfettiHostState.current + val showConfetti: () -> Unit = { + scope.launch { + confettiHostState.showConfetti() + } + } + Badge( + content = badgeContent, + containerColor = MaterialTheme.colorScheme.tertiary, + contentColor = MaterialTheme.colorScheme.onTertiary, + modifier = Modifier + .padding(horizontal = 2.dp) + .padding(bottom = 12.dp) + .scaleOnTap { + showConfetti() + } + ) + } + } + EnhancedIconButton( containerColor = Color.Transparent, onClick = { expanded = !expanded } diff --git a/feature/settings/src/main/java/ru/tech/imageresizershrinker/feature/settings/presentation/components/ChecksumAsFilenameSettingItem.kt b/feature/settings/src/main/java/ru/tech/imageresizershrinker/feature/settings/presentation/components/ChecksumAsFilenameSettingItem.kt index 7dc1b896e..3d5cb1f91 100644 --- a/feature/settings/src/main/java/ru/tech/imageresizershrinker/feature/settings/presentation/components/ChecksumAsFilenameSettingItem.kt +++ b/feature/settings/src/main/java/ru/tech/imageresizershrinker/feature/settings/presentation/components/ChecksumAsFilenameSettingItem.kt @@ -18,21 +18,14 @@ package ru.tech.imageresizershrinker.feature.settings.presentation.components import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.horizontalScroll -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Tag import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -44,9 +37,8 @@ import androidx.compose.ui.unit.dp import ru.tech.imageresizershrinker.core.domain.model.ChecksumType import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState -import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedChip +import ru.tech.imageresizershrinker.core.ui.widget.controls.selection.DataSelector import ru.tech.imageresizershrinker.core.ui.widget.modifier.ContainerShapeDefaults -import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceRowSwitch @Composable @@ -85,39 +77,23 @@ fun ChecksumAsFilenameSettingItem( visible = checkedState, modifier = Modifier.fillMaxWidth() ) { - val state = rememberScrollState() - Row( - horizontalArrangement = Arrangement.spacedBy(8.dp), + DataSelector( modifier = Modifier - .padding(top = 16.dp) - .fadingEdges(state) - .horizontalScroll(state) - ) { - ChecksumType.entries.forEach { type -> - val selected by remember(type, settingsState.checksumTypeForFilename) { - derivedStateOf { - settingsState.checksumTypeForFilename == type - } - } - - EnhancedChip( - selected = selected, - onClick = { - onValueChange(type) - }, - selectedColor = MaterialTheme.colorScheme.tertiary, - contentPadding = PaddingValues( - horizontal = 12.dp, - vertical = 8.dp - ), - modifier = Modifier.height(36.dp) - ) { - Text( - text = type.digest - ) - } + .padding(top = 16.dp), + value = settingsState.checksumTypeForFilename ?: ChecksumType.entries.first(), + onValueChange = onValueChange, + entries = ChecksumType.entries, + color = MaterialTheme.colorScheme.surfaceContainerLowest, + shape = shape, + title = stringResource(R.string.algorithms), + titleIcon = null, + badgeContent = { + Text(ChecksumType.entries.size.toString()) + }, + itemContentText = { + it.name } - } + ) } } ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 30f6158e9..383e4ce70 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -76,6 +76,7 @@ capturable = "3.0.1" moshi = "1.15.2" aboutlibraries = "11.2.3" junit = "4.13.2" +bouncycastle = "1.79" [libraries] aboutlibraries-m3 = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "aboutlibraries" } @@ -170,6 +171,9 @@ uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", versi benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" } tesseract = { module = "cz.adaptech.tesseract4android:tesseract4android-openmp", version.ref = "tesseract" } +bouncycastle-pkix = { module = "org.bouncycastle:bcpkix-jdk18on", version.ref = "bouncycastle" } +bouncycastle-provider = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "bouncycastle" } + firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsGradle" } baselineprofile-gradle = { group = "androidx.benchmark", name = "benchmark-baseline-profile-gradle-plugin", version.ref = "androidxMacroBenchmark" } kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }