mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-23 00:57:13 +00:00
complete preview tools for passport
This commit is contained in:
parent
15066c9d63
commit
fbe91a6321
@ -1,14 +0,0 @@
|
||||
package dev.inmo.tgbotapi.types.passport.credentials
|
||||
|
||||
import dev.inmo.tgbotapi.types.dataHashField
|
||||
import dev.inmo.tgbotapi.types.secretField
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class DataCredentials(
|
||||
@SerialName(dataHashField)
|
||||
val dataHash: String,
|
||||
@SerialName(secretField)
|
||||
val secret: String
|
||||
)
|
@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
data class DecryptedCredentials(
|
||||
@SerialName(secureDataField)
|
||||
val secureData: List<SecureData>,
|
||||
val secureData: SecureData,
|
||||
@SerialName(nonceField)
|
||||
val nonce: String
|
||||
)
|
||||
|
@ -0,0 +1,35 @@
|
||||
package dev.inmo.tgbotapi.types.passport.credentials
|
||||
|
||||
import dev.inmo.micro_utils.crypto.SourceBytes
|
||||
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class EndDataCredentials {
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
abstract val hash: SourceBytes
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
abstract val secret: SourceBytes
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class DataCredentials(
|
||||
@SerialName(dataHashField)
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
override val hash: SourceBytes,
|
||||
@SerialName(secretField)
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
override val secret: SourceBytes
|
||||
) : EndDataCredentials()
|
||||
|
||||
@Serializable
|
||||
data class FileCredentials(
|
||||
@SerialName(fileHashField)
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
override val hash: SourceBytes,
|
||||
@SerialName(secretField)
|
||||
@Serializable(Base64BytesToFromStringSerializer::class)
|
||||
override val secret: SourceBytes
|
||||
) : EndDataCredentials()
|
@ -1,13 +0,0 @@
|
||||
package dev.inmo.tgbotapi.types.passport.credentials
|
||||
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class FileCredentials(
|
||||
@SerialName(fileHashField)
|
||||
val fileHash: String,
|
||||
@SerialName(secretField)
|
||||
val secret: String
|
||||
)
|
@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.passport.decrypted
|
||||
|
||||
import dev.inmo.tgbotapi.types.dataField
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -10,4 +11,6 @@ import kotlinx.serialization.Serializable
|
||||
data class AddressSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials
|
||||
) : SecureValueWithData
|
||||
) : SecureValueWithData {
|
||||
override val credentials: List<EndDataCredentials> = listOf(data)
|
||||
}
|
@ -1,39 +1,41 @@
|
||||
package dev.inmo.tgbotapi.types.passport.decrypted
|
||||
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.*
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class IdentityWithReverseSideSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations, SecureValueWithReverseSide
|
||||
sealed class IdentityWithReverseSideSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations, SecureValueWithReverseSide {
|
||||
override val credentials: List<EndDataCredentials>
|
||||
get() = listOfNotNull(data, frontSide, reverseSide, selfie) + translation
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class DriverLicenseSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials,
|
||||
override val data: DataCredentials? = null,
|
||||
@SerialName(frontSideField)
|
||||
override val frontSide: FileCredentials,
|
||||
override val frontSide: FileCredentials? = null,
|
||||
@SerialName(reverseSideField)
|
||||
override val reverseSide: FileCredentials,
|
||||
override val reverseSide: FileCredentials? = null,
|
||||
@SerialName(selfieField)
|
||||
override val selfie: FileCredentials,
|
||||
override val selfie: FileCredentials? = null,
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>
|
||||
override val translation: List<FileCredentials> = emptyList()
|
||||
) : IdentityWithReverseSideSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class IdentityCardSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials,
|
||||
override val data: DataCredentials? = null,
|
||||
@SerialName(frontSideField)
|
||||
override val frontSide: FileCredentials,
|
||||
override val frontSide: FileCredentials? = null,
|
||||
@SerialName(reverseSideField)
|
||||
override val reverseSide: FileCredentials,
|
||||
override val reverseSide: FileCredentials? = null,
|
||||
@SerialName(selfieField)
|
||||
override val selfie: FileCredentials,
|
||||
override val selfie: FileCredentials? = null,
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>
|
||||
override val translation: List<FileCredentials> = emptyList()
|
||||
) : IdentityWithReverseSideSecureValue()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dev.inmo.tgbotapi.types.passport.decrypted
|
||||
|
||||
import dev.inmo.tgbotapi.types.filesField
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithFiles
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithTranslations
|
||||
@ -9,44 +10,47 @@ import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class OtherDocumentsSecureValue : SecureValueWithTranslations, SecureValueWithFiles
|
||||
sealed class OtherDocumentsSecureValue : SecureValueWithTranslations, SecureValueWithFiles {
|
||||
override val credentials: List<EndDataCredentials>
|
||||
get() = translation + files
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class UtilityBillSecureValue(
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>,
|
||||
override val translation: List<FileCredentials> = emptyList(),
|
||||
@SerialName(filesField)
|
||||
override val files: List<FileCredentials>
|
||||
override val files: List<FileCredentials> = emptyList()
|
||||
) : OtherDocumentsSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class BankStatementSecureValue(
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>,
|
||||
override val translation: List<FileCredentials> = emptyList(),
|
||||
@SerialName(filesField)
|
||||
override val files: List<FileCredentials>
|
||||
override val files: List<FileCredentials> = emptyList()
|
||||
) : OtherDocumentsSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class RentalAgreementSecureValue(
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>,
|
||||
override val translation: List<FileCredentials> = emptyList(),
|
||||
@SerialName(filesField)
|
||||
override val files: List<FileCredentials>
|
||||
override val files: List<FileCredentials> = emptyList()
|
||||
) : OtherDocumentsSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class PassportRegistrationSecureValue(
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>,
|
||||
override val translation: List<FileCredentials> = emptyList(),
|
||||
@SerialName(filesField)
|
||||
override val files: List<FileCredentials>
|
||||
override val files: List<FileCredentials> = emptyList()
|
||||
) : OtherDocumentsSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class TemporalRegistrationSecureValue(
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>,
|
||||
override val translation: List<FileCredentials> = emptyList(),
|
||||
@SerialName(filesField)
|
||||
override val files: List<FileCredentials>
|
||||
override val files: List<FileCredentials> = emptyList()
|
||||
) : OtherDocumentsSecureValue()
|
||||
|
@ -1,36 +1,38 @@
|
||||
package dev.inmo.tgbotapi.types.passport.decrypted
|
||||
|
||||
import dev.inmo.tgbotapi.types.*
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.*
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed class PassportSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations
|
||||
sealed class PassportSecureValue : SecureValueIdentity, SecureValueWithData, SecureValueWithTranslations {
|
||||
override val credentials: List<EndDataCredentials>
|
||||
get() = listOfNotNull(data, frontSide, selfie) + translation
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class CommonPassportSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials,
|
||||
override val data: DataCredentials? = null,
|
||||
@SerialName(frontSideField)
|
||||
override val frontSide: FileCredentials,
|
||||
override val frontSide: FileCredentials? = null,
|
||||
@SerialName(selfieField)
|
||||
override val selfie: FileCredentials,
|
||||
override val selfie: FileCredentials? = null,
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>
|
||||
override val translation: List<FileCredentials> = emptyList()
|
||||
) : PassportSecureValue()
|
||||
|
||||
@Serializable
|
||||
data class InternalPassportSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials,
|
||||
override val data: DataCredentials? = null,
|
||||
@SerialName(frontSideField)
|
||||
override val frontSide: FileCredentials,
|
||||
override val frontSide: FileCredentials? = null,
|
||||
@SerialName(selfieField)
|
||||
override val selfie: FileCredentials,
|
||||
override val selfie: FileCredentials? = null,
|
||||
@SerialName(translationField)
|
||||
override val translation: List<FileCredentials>
|
||||
override val translation: List<FileCredentials> = emptyList()
|
||||
) : PassportSecureValue()
|
||||
|
||||
|
@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.passport.decrypted
|
||||
|
||||
import dev.inmo.tgbotapi.types.dataField
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -10,4 +11,6 @@ import kotlinx.serialization.Serializable
|
||||
data class PersonalDetailsSecureValue(
|
||||
@SerialName(dataField)
|
||||
override val data: DataCredentials
|
||||
) : SecureValueWithData
|
||||
) : SecureValueWithData {
|
||||
override val credentials: List<EndDataCredentials> = listOf(data)
|
||||
}
|
@ -9,7 +9,7 @@ data class SecureData(
|
||||
@SerialName(personalDetailsField)
|
||||
val personalDetails: PersonalDetailsSecureValue? = null,
|
||||
@SerialName(passportField)
|
||||
val passport: PassportSecureValue? = null,
|
||||
val passport: CommonPassportSecureValue? = null,
|
||||
@SerialName(internalPassportField)
|
||||
val internalPassport: InternalPassportSecureValue? = null,
|
||||
@SerialName(driverLicenseField)
|
||||
@ -26,4 +26,17 @@ data class SecureData(
|
||||
val passportRegistration: PassportRegistrationSecureValue? = null,
|
||||
@SerialName(temporaryRegistrationField)
|
||||
val temporaryRegistration: TemporalRegistrationSecureValue? = null,
|
||||
)
|
||||
) {
|
||||
val allCredentials by lazy {
|
||||
(personalDetails ?.credentials ?: emptyList()) +
|
||||
(passport ?.credentials ?: emptyList()) +
|
||||
(internalPassport ?.credentials ?: emptyList()) +
|
||||
(driverLicense ?.credentials ?: emptyList()) +
|
||||
(identityCard ?.credentials ?: emptyList()) +
|
||||
(utilityBill ?.credentials ?: emptyList()) +
|
||||
(bankStatement ?.credentials ?: emptyList()) +
|
||||
(rentalAgreement ?.credentials ?: emptyList()) +
|
||||
(passportRegistration ?.credentials ?: emptyList()) +
|
||||
(temporaryRegistration ?.credentials ?: emptyList())
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,7 @@
|
||||
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
|
||||
|
||||
interface SecureValue
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
|
||||
|
||||
interface SecureValue {
|
||||
val credentials: List<EndDataCredentials>
|
||||
}
|
||||
|
@ -3,6 +3,6 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
|
||||
|
||||
interface SecureValueIdentity : SecureValue {
|
||||
val frontSide: FileCredentials
|
||||
val selfie: FileCredentials
|
||||
val frontSide: FileCredentials?
|
||||
val selfie: FileCredentials?
|
||||
}
|
@ -3,5 +3,5 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
|
||||
|
||||
interface SecureValueWithData : SecureValue {
|
||||
val data: DataCredentials
|
||||
val data: DataCredentials?
|
||||
}
|
@ -3,5 +3,5 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
|
||||
|
||||
interface SecureValueWithReverseSide : SecureValue {
|
||||
val reverseSide: FileCredentials
|
||||
val reverseSide: FileCredentials?
|
||||
}
|
@ -1,32 +1,15 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.SourceBytes
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.requests.DownloadFile
|
||||
import dev.inmo.tgbotapi.requests.get.GetFile
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
|
||||
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
|
||||
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
interface Decryptor {
|
||||
fun ByteArray.decrypt(): ByteArray
|
||||
fun decrypt(data: EncryptedData): SourceBytes
|
||||
}
|
||||
|
||||
suspend fun Decryptor.decrypt(
|
||||
file: PassportFile,
|
||||
bot: TelegramBot
|
||||
): ByteArray {
|
||||
return bot.execute(
|
||||
DownloadFile(
|
||||
bot.execute(
|
||||
GetFile(file.fileId)
|
||||
).filePath
|
||||
)
|
||||
).decrypt()
|
||||
}
|
||||
fun Decryptor.decryptData(
|
||||
data: EncryptedCredentials
|
||||
) = nonstrictJsonFormat.decodeFromString(
|
||||
JsonObject.serializer(),
|
||||
data.data.decrypt().decodeToString()
|
||||
)
|
||||
|
@ -0,0 +1,21 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.SourceBytes
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class AESDecryptor(key: SourceBytes, private val iv: ByteArray) : Decryptor {
|
||||
private val key = SecretKeySpec(key, "AES");
|
||||
|
||||
override fun decrypt(data: EncryptedData): SourceBytes {
|
||||
return Cipher.getInstance("AES/CBC/NOPADDING").run {
|
||||
init(Cipher.DECRYPT_MODE, key, IvParameterSpec(this@AESDecryptor.iv))
|
||||
val decryptedCredentials = doFinal(data)
|
||||
|
||||
val padding = decryptedCredentials.first()
|
||||
decryptedCredentials.copyOfRange(padding.toInt(), decryptedCredentials.size)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.decodeBase64
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.DecryptedCredentials
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
|
||||
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
||||
import java.security.*
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")
|
||||
|
||||
fun EncryptedCredentials.decryptWithPKCS8PrivateKey(privateKey: PrivateKey): DecryptedCredentials {
|
||||
val decrypted = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding").run {
|
||||
init(Cipher.DECRYPT_MODE, privateKey)
|
||||
doFinal(secret)
|
||||
}
|
||||
val dataDecryptor = (decrypted to hash).createDecryptor()
|
||||
val decryptedCredentials = dataDecryptor.decrypt(data).decodeToString()
|
||||
return nonstrictJsonFormat.decodeFromString(DecryptedCredentials.serializer(), decryptedCredentials)
|
||||
}
|
||||
|
||||
fun EncryptedCredentials.decryptWithPKCS8PrivateKey(key: String) = decryptWithPKCS8PrivateKey(
|
||||
KeyFactory.getInstance("RSA").generatePrivate(
|
||||
PKCS8EncodedKeySpec(key.replace(regexToRemoveFromKey, "").decodeBase64())
|
||||
)
|
||||
)
|
@ -1,2 +0,0 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
@ -0,0 +1,28 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.SourceBytes
|
||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||
import dev.inmo.tgbotapi.requests.DownloadFile
|
||||
import dev.inmo.tgbotapi.requests.get.GetFile
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.*
|
||||
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
|
||||
|
||||
fun EndDataCredentials.decryptData(
|
||||
bytes: EncryptedData
|
||||
): SourceBytes {
|
||||
return createDecryptor().decrypt(bytes)
|
||||
}
|
||||
|
||||
fun FileCredentials.decryptFile(
|
||||
fileBytes: ByteArray
|
||||
): SourceBytes {
|
||||
return createDecryptor().decrypt(fileBytes)
|
||||
}
|
||||
suspend fun FileCredentials.decryptFile(
|
||||
bot: TelegramBot,
|
||||
passportFile: PassportFile
|
||||
): SourceBytes {
|
||||
val pathedFile = bot.execute(GetFile(passportFile.fileId))
|
||||
val bytes = bot.execute(DownloadFile(pathedFile.filePath))
|
||||
return decryptFile(bytes)
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.SourceBytes
|
||||
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
|
||||
import java.security.MessageDigest
|
||||
|
||||
fun Pair<SourceBytes, SourceBytes>.createDecryptor(): Decryptor {
|
||||
val secretHash = MessageDigest.getInstance("SHA-512").digest(first + second)
|
||||
val key = secretHash.copyOf(32)
|
||||
val iv = secretHash.copyOfRange(32, 48)
|
||||
|
||||
return AESDecryptor(key, iv)
|
||||
}
|
||||
|
||||
fun EndDataCredentials.createDecryptor() = (secret to hash).createDecryptor()
|
@ -1,39 +0,0 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.decodeBase64
|
||||
import java.security.KeyFactory
|
||||
import java.security.interfaces.RSAPrivateKey
|
||||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import javax.crypto.Cipher
|
||||
|
||||
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")
|
||||
|
||||
/**
|
||||
* @param key PKCS8
|
||||
*/
|
||||
class PKCS8Decryptor (key: String): Decryptor {
|
||||
private val privateKey: RSAPrivateKey = KeyFactory.getInstance("RSA").generatePrivate(
|
||||
PKCS8EncodedKeySpec(key.replace(regexToRemoveFromKey, "").decodeBase64())
|
||||
) as RSAPrivateKey
|
||||
private val chunkSize: Int = privateKey.modulus.bitLength() / 8
|
||||
|
||||
override fun ByteArray.decrypt(): ByteArray {
|
||||
return Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING").run {
|
||||
init(Cipher.DECRYPT_MODE, privateKey)
|
||||
(0 until size step chunkSize).flatMap {
|
||||
val firstIndex = it
|
||||
val lastIndexExclusive = if (it + chunkSize > size) {
|
||||
size
|
||||
} else {
|
||||
it + chunkSize
|
||||
}
|
||||
doFinal(copyOfRange(firstIndex, lastIndexExclusive)).toList()
|
||||
}.toByteArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Decryptor(key: String) = PKCS8Decryptor(key)
|
||||
|
||||
inline fun <T> doWithDecryptor(decryptor: Decryptor, crossinline block: Decryptor.() -> T) = decryptor.run(block)
|
||||
inline fun <T> doWithDecryptor(key: String, crossinline block: Decryptor.() -> T) = doWithDecryptor(Decryptor(key), block)
|
@ -0,0 +1,15 @@
|
||||
package dev.inmo.tgbotapi.utils.passport
|
||||
|
||||
import dev.inmo.tgbotapi.types.passport.PassportData
|
||||
import dev.inmo.tgbotapi.types.passport.decrypted.SecureData
|
||||
import java.security.PrivateKey
|
||||
|
||||
inline fun <T> PassportData.doInDecryptionContextWithPKCS8Key(
|
||||
pkcs8Key: PrivateKey,
|
||||
expectedNonce: String? = null,
|
||||
crossinline block: SecureData.() -> T
|
||||
): T {
|
||||
val decryptedCredentials = credentials.decryptWithPKCS8PrivateKey(pkcs8Key)
|
||||
expectedNonce ?.let { require(expectedNonce == decryptedCredentials.nonce) }
|
||||
return decryptedCredentials.secureData.run(block)
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package dev.inmo.tgbotapi.passport
|
||||
|
||||
import dev.inmo.micro_utils.crypto.decodeBase64
|
||||
import dev.inmo.tgbotapi.utils.passport.Decryptor
|
||||
import dev.inmo.tgbotapi.utils.passport.doWithDecryptor
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
//expect val privateKey: String
|
||||
//expect val encryptedLoremIpsum: EncryptedAndBase64EncodedData
|
||||
val privateKey: String = """-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaaMFkmMBi6Vl5
|
||||
vzy7wQjoZNLN+e9e6Lb/WBekJxfbNMt+EN9Zv7xT9xzfY68DX7v0uGoLcAqS5Mh5
|
||||
8ELiJbzg4O8dbxkggt0G+kxcbT+a3ofm1Aqhr+LkpsFh5qbLqbAHSQJAF0HPqrAc
|
||||
5c6MoQVTZlWGU/j3enCcUFo7Jpsi8La6MqYboF5xGwGEZ9tOA6rMDSekr5Rdm637
|
||||
D/w4h284UX7VnqPdpZ/943VK2qvmPjm8HkFSxkSAB8RHlFyjazzm9FNOcVRGLynv
|
||||
/cq7mWgyxt5nqiCG7w+lFNAFNQNvAO0rfeiTJbEzubquu4Mg31QrvLIuz+fUbsGk
|
||||
ipfpN1czAgMBAAECggEAPlAoO8CpY0FoqolSqTKttZt6t0U2JMclksaqQ8TDC+Oy
|
||||
e52zhTSre/ct37kK2AG6iHgj05nTqpRJk2wykbFJGDeuR+Kd8VDeggJg7qvoD0fe
|
||||
8HiCEd45Yq0pPaknhulj8Iy2K8c29+eaSw8y2+3fiFi0CxG4V6dB6tNClrxtvxtl
|
||||
IE85Utzmk4PLTCs010zxNVm+FwrvqlpjjhspljzleUuWE1KuldO9tNSlwUUfBr4i
|
||||
BJJn4jDkQMloXoM/ArZEp7mn57N9+ZuEgVjRMCpRGEAbQI+aLCznBB1kCOY7WL8S
|
||||
CwkP++SvcptaUpOjoXZZyuGU4CgBnu0+40ORbNchgQKBgQDLIbB9+WHDcZAn1g6M
|
||||
8jaNDRU4HGu5vJSajFQK8Uaczg87hAxmk6R1GF0LOyoadaVmD5ax93mQxWSE/4hT
|
||||
wyAPaQOFl7A/i1k/Dx/kURjRwF1sLWDFdMo/8t5bXumzrzb1bHYnHPS7S0lBAU+X
|
||||
SrbIw+hv69aKawcQqdd54S1OBwKBgQDCmMarwMVn4xnOh+DOuLS4IQzPT84WgzH+
|
||||
wKw55hZGMqZ4S3JRVv256daweEbKAeR5NCccPmir0H86jwUW6WFAtxqfPWF4piVi
|
||||
UD6DrUt0gWwzMGy3kbAp0hLBtsQRp/41mKuAXkvMVQ2ysInn6lmHhZvjduK8lvKh
|
||||
fMRDMjxidQKBgFiciK5blI86wgTutwg7PRrI40HH/CJZJoZIwvzHBeOvbCutTe+N
|
||||
ZoeCKkyU8af7PDzKfhWCfHBv+4qdIi5QB3NRfyzO4B7IPhVpFqN10RrnDJn9LaLV
|
||||
cMj2vJMlU1OEErh7KQuk8QmnLPyDguHfwN7Rv1rbiYp2Z+2X+Zx8Y1QPAoGBAJIf
|
||||
nq/CJXoJMou/xLP2Rt4tEy1pQ9vr0FL341vmxrsXtaGHJeSmagh861XAO4fdO+83
|
||||
llbDFl5ORft3Ad9eiETMOhVxRgwO1uuoTgkazBpERTd7GWgO4jXFJYiI8VpAx8b/
|
||||
SWkvZcOd6pdPsX6Qn4IAdjqsPz5WKwPQaJ/8zRMxAoGAGaOuyXaFZNl8IeTGYMDL
|
||||
OEg9BHa+Du8jSv0vL/fCN2s/2TcvSa9uEnv8KHz59JHevvxoDNbQYlN8Ge8adFv4
|
||||
xZYQ3h/qh2ohnTUfrG4hcFUVBuv5HBdwgWhVFm5v98KQsqVzGfKorN2DemEv3/au
|
||||
PFGkuu4lCPeDqu5u0dBojoA=
|
||||
-----END PRIVATE KEY-----"""
|
||||
val encryptedLoremIpsum = "F57wnFj3PTQ+xNgDFLCNRIHVf8Kp7YiaQdYOOEpuWMuICFBvVDrTst82jxhRuKj8w9qDZ0ys9pQ30QjnmCP0h/d8HhmLcG3sYY9fnDgd4hegY0D917Xhc0F5KwheFxNgHFn5uRuTdAoyBVUeAzclpR7XoEO8Zp+kYvNty7eOpLVC2jXBTiTBClXmxM15M48Pw7ClZr2lvjFf7r+4Bh8UAYM8IIKctV/Vk1iR7SIilHOw/GNhgBB1zy0SYlwSuvPEIPfZnEPL4zS9VqDN4Di53Zt7ZLhySBMDi1qA4V6OnjSoF6nexCrytMqIsLHrTbfin5ni20F+vIITFxa7kJU2+AVQFTsYrquL5zN9ms56kkLd3HMv/fdrz9Ry19vSaIjyajipoWPM6BvzNccYk2xnZx+5qzpZUQjsh+Xr+HD7GcpdGwavcz7WqGlx9qKBPwU0rq0+QCRpDz/hnl2gdChk+bjTAfuRWJDoUUetVV283BG8UY5SENH7EjOhtaMsEgog6VI2yyiei6azxZ+MTqkREnHWmjefsBHmbAbf2EEZag+nSjIZhNT62FkhWq5jBghjduoKixS5OUvWniY3wSx0RSXsJPVg9C80EyeO8wyOop7x0wN5zxKoXrniX6AGruEt74SJt9RZamniog2X5CJ27D94HvoF2qXSv9QeqK+qUj9XxGhn0AtqFnvg/yU/jUp6z4yGQ7CkIMHEMbq4ylRA87ydhu3HbqdrW3q8aRXtvo+VFQ8jmsOq+ssj2q7y2WegBMNCBMRjn197S/eBW4EweIqh9+3VsDRoabfUUuCDXBlA+qFOAYEB44TGiaXqneHjUwhDahKlui8556ILcUP4yNnFNA6wx/tgRiW40cEa6vs4CF4UPtzKrVgWwS8/hRd7OBaK/jU3KnMGKZej9AtV28ErDmBTcixMzpflPmUFQABwH7IhUzJMVlqDifZuVjthGZ3FWuPaFOcesQoScQ1q93pohz1vjwtyT5fU36JzyhYpEpmN6h3GiAFV6qT0VDiE"
|
||||
|
||||
|
||||
class DecryptionTest {
|
||||
val inputText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||
|
||||
@Test
|
||||
fun testThatDecryptionIsWorkingCorrectly() {
|
||||
doWithDecryptor(privateKey) {
|
||||
val decrypted = encryptedLoremIpsum.decodeBase64().decrypt().decodeToString()
|
||||
assertEquals(inputText, decrypted)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user