Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.pubnub.internal.vendor.FileEncryptionUtil.kt Maven / Gradle / Ivy
package com.pubnub.internal.vendor
import com.pubnub.api.PubNubException
import com.pubnub.internal.PubNubCore
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.UnsupportedEncodingException
import java.security.InvalidAlgorithmParameterException
import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException
import java.security.SecureRandom
import java.security.spec.AlgorithmParameterSpec
import java.util.Locale
import javax.crypto.BadPaddingException
import javax.crypto.Cipher
import javax.crypto.IllegalBlockSizeException
import javax.crypto.NoSuchPaddingException
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
object FileEncryptionUtil {
private const val IV_SIZE_BYTES = 16
const val ENCODING_UTF_8 = "UTF-8"
const val CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding"
/**
* @see [PubNubCore.encryptInputStream]
*/
@Throws(PubNubException::class)
fun encrypt(
inputStream: InputStream,
cipherKey: String,
): InputStream {
return encryptToBytes(inputStream.readBytes(), cipherKey).inputStream()
}
/**
* @see [PubNubCore.decryptInputStream]
*/
@Throws(PubNubException::class)
fun decrypt(
inputStream: InputStream,
cipherKey: String,
): InputStream {
return try {
val keyBytes = keyBytes(cipherKey)
val (ivBytes, dataToDecrypt) = loadIvAndDataFromInputStream(inputStream)
val decryptionCipher = decryptionCipher(keyBytes, ivBytes)
val decryptedBytes = decryptionCipher.doFinal(dataToDecrypt)
ByteArrayInputStream(decryptedBytes)
} catch (e: Exception) {
when (e) {
is NoSuchAlgorithmException,
is InvalidAlgorithmParameterException,
is NoSuchPaddingException,
is InvalidKeyException,
is IOException,
is IllegalBlockSizeException,
is BadPaddingException,
-> {
throw PubNubException(errorMessage = e.message)
}
else -> throw e
}
}
}
@Throws(PubNubException::class)
internal fun encryptToBytes(
bytesToEncrypt: ByteArray,
cipherKey: String,
): ByteArray {
try {
ByteArrayOutputStream().use { byteArrayOutputStream ->
val randomIvBytes = randomIv()
byteArrayOutputStream.write(randomIvBytes)
val keyBytes = keyBytes(cipherKey)
val encryptionCipher = encryptionCipher(keyBytes, randomIvBytes)
byteArrayOutputStream.write(encryptionCipher.doFinal(bytesToEncrypt))
return byteArrayOutputStream.toByteArray()
}
} catch (e: Exception) {
when (e) {
is NoSuchAlgorithmException,
is InvalidAlgorithmParameterException,
is NoSuchPaddingException,
is InvalidKeyException,
is IOException,
is BadPaddingException,
is IllegalBlockSizeException,
-> {
throw PubNubException(errorMessage = e.message)
}
else -> throw e
}
}
}
@Throws(IOException::class)
private fun loadIvAndDataFromInputStream(inputStreamToEncrypt: InputStream): Pair {
val ivBytes = ByteArray(IV_SIZE_BYTES)
inputStreamToEncrypt.read(ivBytes, 0, IV_SIZE_BYTES)
return ivBytes to inputStreamToEncrypt.readBytes()
}
@Throws(
NoSuchAlgorithmException::class,
NoSuchPaddingException::class,
InvalidKeyException::class,
InvalidAlgorithmParameterException::class,
)
private fun encryptionCipher(
keyBytes: ByteArray,
ivBytes: ByteArray,
): Cipher {
return cipher(keyBytes, ivBytes, Cipher.ENCRYPT_MODE)
}
@Throws(
NoSuchAlgorithmException::class,
NoSuchPaddingException::class,
InvalidKeyException::class,
InvalidAlgorithmParameterException::class,
)
private fun decryptionCipher(
keyBytes: ByteArray,
ivBytes: ByteArray,
): Cipher {
return cipher(keyBytes, ivBytes, Cipher.DECRYPT_MODE)
}
@Throws(
NoSuchAlgorithmException::class,
NoSuchPaddingException::class,
InvalidKeyException::class,
InvalidAlgorithmParameterException::class,
)
private fun cipher(
keyBytes: ByteArray,
ivBytes: ByteArray,
mode: Int,
): Cipher {
val cipher = Cipher.getInstance(CIPHER_TRANSFORMATION)
val iv: AlgorithmParameterSpec = IvParameterSpec(ivBytes)
val key = SecretKeySpec(keyBytes, "AES")
cipher.init(mode, key, iv)
return cipher
}
@Throws(UnsupportedEncodingException::class, PubNubException::class)
private fun keyBytes(cipherKey: String): ByteArray {
return String(
com.pubnub.internal.vendor.Crypto.hexEncode(
com.pubnub.internal.vendor.Crypto.sha256(
cipherKey.toByteArray(
charset(ENCODING_UTF_8),
),
),
),
charset(ENCODING_UTF_8),
)
.substring(0, 32)
.lowercase(Locale.getDefault()).toByteArray(charset(ENCODING_UTF_8))
}
@Throws(NoSuchAlgorithmException::class)
private fun randomIv(): ByteArray {
val randomIv = ByteArray(IV_SIZE_BYTES)
SecureRandom.getInstance("SHA1PRNG").nextBytes(randomIv)
return randomIv
}
}