1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2024-12-22 16:47:13 +00:00

complete tools for handling of encrypted data

This commit is contained in:
InsanusMokrassar 2021-01-23 20:50:40 +06:00
parent d34deade0d
commit 4d63e3a17d
7 changed files with 22 additions and 104 deletions

View File

@ -16,8 +16,6 @@ micro_utils_version=0.4.21
javax_activation_version=1.1.1
crypto_version=1.0.1
library_group=dev.inmo
library_version=0.32.0

View File

@ -71,11 +71,6 @@ kotlin {
api "javax.activation:activation:$javax_activation_version"
}
}
jsMain {
dependencies {
api npm("crypto", "${crypto_version}")
}
}
jvmTest {
dependencies {
implementation kotlin('test-junit')

View File

@ -4,14 +4,15 @@ 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.encrypted_data.PassportFile
import dev.inmo.tgbotapi.types.passport.encrypted_data.abstracts.WithData
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.json.JsonObject
expect class DecryptionContext(
key: String
) {
interface Decryptor {
fun ByteArray.decrypt(): ByteArray
}
suspend fun DecryptionContext.decrypt(
suspend fun Decryptor.decrypt(
file: PassportFile,
bot: TelegramBot
): ByteArray {
@ -23,3 +24,9 @@ suspend fun DecryptionContext.decrypt(
)
).decrypt()
}
fun Decryptor.decryptData(
data: WithData
) = nonstrictJsonFormat.decodeFromString(
JsonObject.serializer(),
data.data.encodeToByteArray().decrypt().decodeToString()
)

View File

@ -1,50 +0,0 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.common.toArrayBuffer
import dev.inmo.micro_utils.common.toByteArray
import dev.inmo.micro_utils.crypto.encodeBase64
import dev.inmo.micro_utils.crypto.encodeBase64String
import org.khronos.webgl.ArrayBuffer
import kotlin.js.Json
import kotlin.js.json
private external interface InternalBuffer {
val buffer: ArrayBuffer
}
private external object Buffer {
fun from(data: String): InternalBuffer
}
private external interface CryptoConstants {
val RSA_PKCS1_OAEP_PADDING: Any
}
private external interface Crypto {
val constants: CryptoConstants
fun privateDecrypt(
key: Json,
data: InternalBuffer
): InternalBuffer
fun privateEncrypt(
key: Json,
data: InternalBuffer
) : InternalBuffer
}
@JsModule("crypto")
@JsNonModule
private external val crypto: Crypto
actual class DecryptionContext actual constructor(key: String) {
private val key = json(
"key" to key,
"padding" to crypto.constants.RSA_PKCS1_OAEP_PADDING
)
actual fun ByteArray.decrypt(): ByteArray {
return crypto.privateDecrypt(
key,
Buffer.from(encodeBase64String())
).buffer.toByteArray()
}
}

View File

@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.decodeBase64
import sun.security.rsa.RSAPublicKeyImpl
import java.security.KeyFactory
import java.security.interfaces.RSAPrivateKey
import java.security.spec.PKCS8EncodedKeySpec
@ -9,21 +8,16 @@ import javax.crypto.Cipher
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")
private fun String.adaptKey() {
val replaced = replace(regexToRemoveFromKey, "")
}
/**
* @param key PKCS8
*/
actual class DecryptionContext actual constructor(key: String) {
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
actual fun ByteArray.decrypt(): ByteArray {
override fun ByteArray.decrypt(): ByteArray {
return Cipher.getInstance("RSA/ECB/PKCS1Padding").run {
init(Cipher.DECRYPT_MODE, privateKey)
(0 until size step chunkSize).flatMap {
@ -37,4 +31,9 @@ actual class DecryptionContext actual constructor(key: String) {
}.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

@ -1,8 +1,8 @@
package dev.inmo.tgbotapi.passport
import dev.inmo.micro_utils.crypto.decodeBase64
import dev.inmo.tgbotapi.types.passport.EncryptedAndBase64EncodedData
import dev.inmo.tgbotapi.utils.passport.DecryptionContext
import dev.inmo.tgbotapi.utils.passport.Decryptor
import dev.inmo.tgbotapi.utils.passport.doWithDecryptor
import kotlin.test.Test
import kotlin.test.assertEquals
@ -44,7 +44,7 @@ class DecryptionTest {
@Test
fun testThatDecryptionIsWorkingCorrectly() {
DecryptionContext(privateKey).apply {
doWithDecryptor(privateKey) {
val decrypted = encryptedLoremIpsum.decodeBase64().decrypt().decodeToString()
assertEquals(inputText, decrypted)
}

View File

@ -1,31 +0,0 @@
package dev.inmo.tgbotapi.passport
//actual 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-----"""
//actual val encryptedLoremIpsum = "KeuPVezTbMW4MvOGJFTAt34PRaL9iepGb1g4QEi5EQYjKXeXo7RytFOCVx6pW9O/uoMWhl+cX32kNqJVWyK7a22kuhnNT2+aiXqEpuh+madx+LK1zUvGDR1A1Mrf3fFOugcnadCQKICiqvl9cFdqsBkJQOFEs9qj5wiu1F57kekuHLWI7ZnHOojkRNq7l1aCHL0DxcLCfZW5CtWAi8g/zUE5WnGd+vUZ+hqc1vnehDul8JE8YUQbAiIxetzba9XoWouTHYZRZcNCztDbrRBYnq2UCcI5adEwQ3VNcES0lIjRuwn1BBWpvk7VOjqh+4c2tSebDX5AkqrO8XwQYwo8OwvZF+hUXFRK6QLHd4B1JQIdygCaEODG0X353upiEKJXDBqv/ZMXR9KqYZBZEfu48ZM/J6heNjVSOP4TSDrXywJgIOieu8mrQ4d7Or7Twnsu/B+bqS37PvVlfU4wHLl7ehXFj4Kusat6cIrb0R4F/Y3fL4+FcfEsk4ioEAndYBFrc1S11vo/TkcuFnXtqrr181gC5JD5LtsUH6sst36vE/JdL/UwTGqhu+rDUcgvr7FiunkasWBnzCtFs58JJrRycUKPzyKINS16GkY8yYtp7xJXBGPYOFM+J7npcKW7P41j1KceDaUArjph2yIELEXCr8qUZzWXZdrw96Te8gLi99c="