Added 59 hashing algorithms from bouncycastle api

This commit is contained in:
T8RIN
2025-01-03 02:36:40 +03:00
parent 00287011cc
commit 3473af873d
9 changed files with 570 additions and 58 deletions

View File

@ -86,11 +86,12 @@ android {
pickFirsts.add("lib/*/libcoder.so") pickFirsts.add("lib/*/libcoder.so")
} }
resources { resources {
excludes += "META-INF/" excludes += "META-INF/*"
excludes += "kotlin/" excludes += "kotlin/*"
excludes += "org/" excludes += "org/*"
excludes += ".properties" excludes += "*.properties"
excludes += ".bin" excludes += "*.bin"
excludes += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
} }
} }
@ -104,6 +105,8 @@ dependencies {
implementation(projects.feature.root) implementation(projects.feature.root)
implementation(projects.feature.mediaPicker) implementation(projects.feature.mediaPicker)
implementation(projects.feature.quickTiles) implementation(projects.feature.quickTiles)
implementation(libs.bouncycastle.pkix)
implementation(libs.bouncycastle.provider)
} }

View File

@ -50,3 +50,6 @@
-dontwarn org.openjsse.net.ssl.OpenJSSE -dontwarn org.openjsse.net.ssl.OpenJSSE
-keep class org.beyka.tiffbitmapfactory.**{ *; } -keep class org.beyka.tiffbitmapfactory.**{ *; }
-keep class org.bouncycastle.jcajce.provider.** { *; }
-keep class org.bouncycastle.jce.provider.** { *; }

View File

@ -21,11 +21,23 @@ import android.app.Application
import com.arkivanov.decompose.DecomposeExperimentFlags import com.arkivanov.decompose.DecomposeExperimentFlags
import com.arkivanov.decompose.ExperimentalDecomposeApi import com.arkivanov.decompose.ExperimentalDecomposeApi
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import org.bouncycastle.jce.provider.BouncyCastleProvider
import ru.tech.imageresizershrinker.core.domain.model.ChecksumType
import java.security.Security
@HiltAndroidApp @HiltAndroidApp
class ImageToolboxApplication : Application() { class ImageToolboxApplication : Application() {
init {
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME)
Security.addProvider(BouncyCastleProvider())
ChecksumType.registerSecurityMessageDigests(
Security.getAlgorithms("MessageDigest")
.filterNotNull()
)
}
@OptIn(ExperimentalDecomposeApi::class) @OptIn(ExperimentalDecomposeApi::class)
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()

View File

@ -17,11 +17,11 @@
package ru.tech.imageresizershrinker.core.domain.model package ru.tech.imageresizershrinker.core.domain.model
class ChecksumType private constructor( @ConsistentCopyVisibility
val digest: String data class ChecksumType private constructor(
val digest: String,
val name: String = digest
) { ) {
override fun toString(): String = "ChecksumType($digest)"
companion object { companion object {
val MD5 = ChecksumType("MD5") val MD5 = ChecksumType("MD5")
val SHA_1 = ChecksumType("SHA-1") val SHA_1 = ChecksumType("SHA-1")
@ -30,7 +30,29 @@ class ChecksumType private constructor(
val SHA_384 = ChecksumType("SHA-384") val SHA_384 = ChecksumType("SHA-384")
val SHA_512 = ChecksumType("SHA-512") val SHA_512 = ChecksumType("SHA-512")
private var securityMessageDigests: List<String>? = null
fun registerSecurityMessageDigests(digests: List<String>) {
if (!securityMessageDigests.isNullOrEmpty()) {
throw IllegalArgumentException("SecurityMessageDigests already registered")
}
securityMessageDigests = digests.distinctBy { it.replace("OID.", "") }
}
val entries: List<ChecksumType> by lazy { val entries: List<ChecksumType> 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( listOf(
MD5, MD5,
SHA_1, SHA_1,
@ -38,7 +60,9 @@ class ChecksumType private constructor(
SHA_256, SHA_256,
SHA_384, SHA_384,
SHA_512, SHA_512,
) ).let {
it + available
}.distinctBy { it.name.replace("-", "") }
} }
fun fromString( fun fromString(

View File

@ -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 <http://www.apache.org/licenses/LICENSE-2.0>.
*/
@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<String>
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)
}
}
}

View File

@ -1533,4 +1533,5 @@
<string name="checksum_as_filename_sub">Output images will have name corresponding to their data checksum</string> <string name="checksum_as_filename_sub">Output images will have name corresponding to their data checksum</string>
<string name="free_software_partner">Free Software (Partner)</string> <string name="free_software_partner">Free Software (Partner)</string>
<string name="free_software_partner_sub">More useful software in the partner channel of Android applications</string> <string name="free_software_partner_sub">More useful software in the partner channel of Android applications</string>
<string name="algorithms">Algorithm</string>
</resources> </resources>

View File

@ -23,6 +23,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding 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.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.KeyboardArrowDown import androidx.compose.material.icons.rounded.KeyboardArrowDown
import androidx.compose.material3.Badge
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -41,6 +43,7 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment 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.Shape
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp 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.EnhancedChip
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton 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.container
import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges 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 import ru.tech.imageresizershrinker.core.ui.widget.text.TitleItem
@Composable @Composable
@ -66,6 +72,7 @@ fun <T : Any> DataSelector(
itemContentText: @Composable (T) -> String, itemContentText: @Composable (T) -> String,
spanCount: Int = 3, spanCount: Int = 3,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
badgeContent: (@Composable RowScope.() -> Unit)? = null,
shape: Shape = RoundedCornerShape(20.dp), shape: Shape = RoundedCornerShape(20.dp),
color: Color = MaterialTheme.colorScheme.surface, color: Color = MaterialTheme.colorScheme.surface,
selectedItemColor: Color = MaterialTheme.colorScheme.tertiary selectedItemColor: Color = MaterialTheme.colorScheme.tertiary
@ -79,13 +86,39 @@ fun <T : Any> DataSelector(
var expanded by rememberSaveable { mutableStateOf(false) } var expanded by rememberSaveable { mutableStateOf(false) }
Row { Row {
val rotation by animateFloatAsState(if (expanded) 180f else 0f) val rotation by animateFloatAsState(if (expanded) 180f else 0f)
Row(
modifier = Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically
) {
TitleItem( TitleItem(
text = title, text = title,
icon = titleIcon, icon = titleIcon,
modifier = Modifier modifier = Modifier
.padding(top = 12.dp, start = 12.dp, bottom = 8.dp) .padding(top = 12.dp, start = 12.dp, bottom = 8.dp)
.weight(1f) .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( EnhancedIconButton(
containerColor = Color.Transparent, containerColor = Color.Transparent,
onClick = { expanded = !expanded } onClick = { expanded = !expanded }

View File

@ -18,21 +18,14 @@
package ru.tech.imageresizershrinker.feature.settings.presentation.components package ru.tech.imageresizershrinker.feature.settings.presentation.components
import androidx.compose.animation.AnimatedVisibility 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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Tag import androidx.compose.material.icons.rounded.Tag
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember 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.domain.model.ChecksumType
import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.R
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState 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.ContainerShapeDefaults
import ru.tech.imageresizershrinker.core.ui.widget.modifier.fadingEdges
import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceRowSwitch import ru.tech.imageresizershrinker.core.ui.widget.preferences.PreferenceRowSwitch
@Composable @Composable
@ -85,40 +77,24 @@ fun ChecksumAsFilenameSettingItem(
visible = checkedState, visible = checkedState,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
val state = rememberScrollState() DataSelector(
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier modifier = Modifier
.padding(top = 16.dp) .padding(top = 16.dp),
.fadingEdges(state) value = settingsState.checksumTypeForFilename ?: ChecksumType.entries.first(),
.horizontalScroll(state) onValueChange = onValueChange,
) { entries = ChecksumType.entries,
ChecksumType.entries.forEach { type -> color = MaterialTheme.colorScheme.surfaceContainerLowest,
val selected by remember(type, settingsState.checksumTypeForFilename) { shape = shape,
derivedStateOf { title = stringResource(R.string.algorithms),
settingsState.checksumTypeForFilename == type titleIcon = null,
} badgeContent = {
} Text(ChecksumType.entries.size.toString())
EnhancedChip(
selected = selected,
onClick = {
onValueChange(type)
}, },
selectedColor = MaterialTheme.colorScheme.tertiary, itemContentText = {
contentPadding = PaddingValues( it.name
horizontal = 12.dp, }
vertical = 8.dp
),
modifier = Modifier.height(36.dp)
) {
Text(
text = type.digest
) )
} }
} }
}
}
}
) )
} }

View File

@ -76,6 +76,7 @@ capturable = "3.0.1"
moshi = "1.15.2" moshi = "1.15.2"
aboutlibraries = "11.2.3" aboutlibraries = "11.2.3"
junit = "4.13.2" junit = "4.13.2"
bouncycastle = "1.79"
[libraries] [libraries]
aboutlibraries-m3 = { module = "com.mikepenz:aboutlibraries-compose-m3", version.ref = "aboutlibraries" } 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" } benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "androidxMacroBenchmark" }
tesseract = { module = "cz.adaptech.tesseract4android:tesseract4android-openmp", version.ref = "tesseract" } 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" } 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" } 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" } kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }