1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-11-26 03:58:44 +00:00

complete preview tools for passport

This commit is contained in:
InsanusMokrassar 2021-01-28 22:03:14 +06:00
parent 15066c9d63
commit fbe91a6321
23 changed files with 222 additions and 185 deletions

View File

@ -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
)

View File

@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class DecryptedCredentials( data class DecryptedCredentials(
@SerialName(secureDataField) @SerialName(secureDataField)
val secureData: List<SecureData>, val secureData: SecureData,
@SerialName(nonceField) @SerialName(nonceField)
val nonce: String val nonce: String
) )

View File

@ -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()

View File

@ -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
)

View File

@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.dataField import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials 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 dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -10,4 +11,6 @@ import kotlinx.serialization.Serializable
data class AddressSecureValue( data class AddressSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials override val data: DataCredentials
) : SecureValueWithData ) : SecureValueWithData {
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@ -1,39 +1,41 @@
package dev.inmo.tgbotapi.types.passport.decrypted package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials import dev.inmo.tgbotapi.types.passport.credentials.*
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.* import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@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 @Serializable
data class DriverLicenseSecureValue( data class DriverLicenseSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials, override val data: DataCredentials? = null,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: FileCredentials, override val frontSide: FileCredentials? = null,
@SerialName(reverseSideField) @SerialName(reverseSideField)
override val reverseSide: FileCredentials, override val reverseSide: FileCredentials? = null,
@SerialName(selfieField) @SerialName(selfieField)
override val selfie: FileCredentials, override val selfie: FileCredentials? = null,
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials> override val translation: List<FileCredentials> = emptyList()
) : IdentityWithReverseSideSecureValue() ) : IdentityWithReverseSideSecureValue()
@Serializable @Serializable
data class IdentityCardSecureValue( data class IdentityCardSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials, override val data: DataCredentials? = null,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: FileCredentials, override val frontSide: FileCredentials? = null,
@SerialName(reverseSideField) @SerialName(reverseSideField)
override val reverseSide: FileCredentials, override val reverseSide: FileCredentials? = null,
@SerialName(selfieField) @SerialName(selfieField)
override val selfie: FileCredentials, override val selfie: FileCredentials? = null,
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials> override val translation: List<FileCredentials> = emptyList()
) : IdentityWithReverseSideSecureValue() ) : IdentityWithReverseSideSecureValue()

View File

@ -1,6 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.filesField 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.credentials.FileCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithFiles import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithFiles
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithTranslations import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithTranslations
@ -9,44 +10,47 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
sealed class OtherDocumentsSecureValue : SecureValueWithTranslations, SecureValueWithFiles sealed class OtherDocumentsSecureValue : SecureValueWithTranslations, SecureValueWithFiles {
override val credentials: List<EndDataCredentials>
get() = translation + files
}
@Serializable @Serializable
data class UtilityBillSecureValue( data class UtilityBillSecureValue(
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials>, override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField) @SerialName(filesField)
override val files: List<FileCredentials> override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue() ) : OtherDocumentsSecureValue()
@Serializable @Serializable
data class BankStatementSecureValue( data class BankStatementSecureValue(
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials>, override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField) @SerialName(filesField)
override val files: List<FileCredentials> override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue() ) : OtherDocumentsSecureValue()
@Serializable @Serializable
data class RentalAgreementSecureValue( data class RentalAgreementSecureValue(
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials>, override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField) @SerialName(filesField)
override val files: List<FileCredentials> override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue() ) : OtherDocumentsSecureValue()
@Serializable @Serializable
data class PassportRegistrationSecureValue( data class PassportRegistrationSecureValue(
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials>, override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField) @SerialName(filesField)
override val files: List<FileCredentials> override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue() ) : OtherDocumentsSecureValue()
@Serializable @Serializable
data class TemporalRegistrationSecureValue( data class TemporalRegistrationSecureValue(
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials>, override val translation: List<FileCredentials> = emptyList(),
@SerialName(filesField) @SerialName(filesField)
override val files: List<FileCredentials> override val files: List<FileCredentials> = emptyList()
) : OtherDocumentsSecureValue() ) : OtherDocumentsSecureValue()

View File

@ -1,36 +1,38 @@
package dev.inmo.tgbotapi.types.passport.decrypted package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials import dev.inmo.tgbotapi.types.passport.credentials.*
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.* import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@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 @Serializable
data class CommonPassportSecureValue( data class CommonPassportSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials, override val data: DataCredentials? = null,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: FileCredentials, override val frontSide: FileCredentials? = null,
@SerialName(selfieField) @SerialName(selfieField)
override val selfie: FileCredentials, override val selfie: FileCredentials? = null,
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials> override val translation: List<FileCredentials> = emptyList()
) : PassportSecureValue() ) : PassportSecureValue()
@Serializable @Serializable
data class InternalPassportSecureValue( data class InternalPassportSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials, override val data: DataCredentials? = null,
@SerialName(frontSideField) @SerialName(frontSideField)
override val frontSide: FileCredentials, override val frontSide: FileCredentials? = null,
@SerialName(selfieField) @SerialName(selfieField)
override val selfie: FileCredentials, override val selfie: FileCredentials? = null,
@SerialName(translationField) @SerialName(translationField)
override val translation: List<FileCredentials> override val translation: List<FileCredentials> = emptyList()
) : PassportSecureValue() ) : PassportSecureValue()

View File

@ -2,6 +2,7 @@ package dev.inmo.tgbotapi.types.passport.decrypted
import dev.inmo.tgbotapi.types.dataField import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials 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 dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -10,4 +11,6 @@ import kotlinx.serialization.Serializable
data class PersonalDetailsSecureValue( data class PersonalDetailsSecureValue(
@SerialName(dataField) @SerialName(dataField)
override val data: DataCredentials override val data: DataCredentials
) : SecureValueWithData ) : SecureValueWithData {
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@ -9,7 +9,7 @@ data class SecureData(
@SerialName(personalDetailsField) @SerialName(personalDetailsField)
val personalDetails: PersonalDetailsSecureValue? = null, val personalDetails: PersonalDetailsSecureValue? = null,
@SerialName(passportField) @SerialName(passportField)
val passport: PassportSecureValue? = null, val passport: CommonPassportSecureValue? = null,
@SerialName(internalPassportField) @SerialName(internalPassportField)
val internalPassport: InternalPassportSecureValue? = null, val internalPassport: InternalPassportSecureValue? = null,
@SerialName(driverLicenseField) @SerialName(driverLicenseField)
@ -26,4 +26,17 @@ data class SecureData(
val passportRegistration: PassportRegistrationSecureValue? = null, val passportRegistration: PassportRegistrationSecureValue? = null,
@SerialName(temporaryRegistrationField) @SerialName(temporaryRegistrationField)
val temporaryRegistration: TemporalRegistrationSecureValue? = null, 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())
}
}

View File

@ -1,3 +1,7 @@
package dev.inmo.tgbotapi.types.passport.decrypted.abstracts package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
interface SecureValue import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
interface SecureValue {
val credentials: List<EndDataCredentials>
}

View File

@ -3,6 +3,6 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueIdentity : SecureValue { interface SecureValueIdentity : SecureValue {
val frontSide: FileCredentials val frontSide: FileCredentials?
val selfie: FileCredentials val selfie: FileCredentials?
} }

View File

@ -3,5 +3,5 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
interface SecureValueWithData : SecureValue { interface SecureValueWithData : SecureValue {
val data: DataCredentials val data: DataCredentials?
} }

View File

@ -3,5 +3,5 @@ package dev.inmo.tgbotapi.types.passport.decrypted.abstracts
import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials import dev.inmo.tgbotapi.types.passport.credentials.FileCredentials
interface SecureValueWithReverseSide : SecureValue { interface SecureValueWithReverseSide : SecureValue {
val reverseSide: FileCredentials val reverseSide: FileCredentials?
} }

View File

@ -1,32 +1,15 @@
package dev.inmo.tgbotapi.utils.passport package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFile import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.get.GetFile import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials 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.types.passport.encrypted.PassportFile
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
interface Decryptor { 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()
)

View File

@ -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)
}
}
}

View File

@ -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())
)
)

View File

@ -1,2 +0,0 @@
package dev.inmo.tgbotapi.utils.passport

View File

@ -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)
}

View File

@ -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()

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}
}
}