hi, I need to encrypt the file with start download on the fly and when finished download decrypt the file and use it in my app, how to encrypt the file in fetch?
Yes I wanted to know how to implement this. Usually I do this with an HTTPUrlConnection which streams the data into a buffer and then I encrypt the buffer and keep writing it into the file on the fly. But I wonder if there is any way to do such with fetch2 or if you can add such feature into the library that would be so great. @tonyofrancis
By the way you may ask where does such feature applies in a real world app, as of me I use encryption on the fly in my video streaming app. So when users download a video they can't just get it out of the phone and spread it to the world.
Thank you for your time and efforts.
Or is there a way to access the byte stream of the file which is getting downloaded? @tonyofrancis
we resolved this! @tonyofrancis thank you so much for your excellent library
we resolved this! @tonyofrancis thank you so much for your excellent library
bebinam che jori halesh kardi mohandes?
@NotNotMarshall you can set StorageResolver for your fetch and get the getRequestOutputResourceWrapper method!
@NotNotMarshall you can set StorageResolver for your fetch and get the getRequestOutputResourceWrapper method!
Can you share a code example? I am overriding the methods in StorageResolver but don't know what to do in getRequestOutputResourceWrapper(). There is just a writeByte() and write() method which seems not to help much.
@NotNotMarshall for encryption on a fly you need to use the cipher algorithm. when you using StorageResolver and getRequestOutputResourceWrapper method giving you the output by the stream and you can be encrypted as a byte.
following this road :
1- instance cipher before per download and keep (key and Ivparamete)r in your storage (sharedpreferences or file)
2- passing cipher to custom getRequestOutputResourceWrapper method as parameter
3- per byte, you must update cipher in getRequestOutputResourceWrapper
override fun write(byteArray: ByteArray, offSet: Int, length: Int) {
val output = cipher.update(byteArray, offSet, length)
this.randomAccessFile.write(output)
}
Kheyli mamnoooooon!
@NotNotMarshall for encryption on a fly you need to use the cipher algorithm. when you using StorageResolver and getRequestOutputResourceWrapper method giving you the output by the stream and you can be encrypted as a byte.
following this road :
1- instance cipher before per download and keep (key and Ivparamete)r in your storage (sharedpreferences or file)
2- passing cipher to custom getRequestOutputResourceWrapper method as parameter
3- per byte, you must update cipher in getRequestOutputResourceWrapperoverride fun write(byteArray: ByteArray, offSet: Int, length: Int) { val output = cipher.update(byteArray, offSet, length) this.randomAccessFile.write(output) }
Salaam dash, I have implemented it and everything works fine except the resume part. Whenever I resume a download I get an UNKNOWN_IO error.
Can you give an example of how to resume the download?
I am appending to the FileOutputStream in the custom StorageResolver when there is a resume but it keeps giving me an UNKNOWN_IO error.
@NotNotMarshall hey bro
yes this problem saw on the resume or reopening application again
resolve description: you must be calculated block offset on your resume and seek cipher to the current point
how to do that :
1- you must have keys and iv
2- override setWriteOffset method on getOutputResourceWrapper
3- the first step you must calculate skip like this :
val AES_BLOCK_SIZE = 16
val skip = (offset % AES_BLOCK_SIZE).toInt()
4- the step two you must calculate current block like this :
val blockOffset = offset - skip
5- in the third step you need to know how many blocks you have like this :
val numberOfBlocks = blockOffset / AES_BLOCK_SIZE
6- in the fourth step you must have calculate iv for current position like this :
val ivForOffsetAsBigInteger = BigInteger(1, iv.getIV()).add(BigInteger.valueOf(numberOfBlocks))
val ivForOffsetByteArray = ivForOffsetAsBigInteger.toByteArray()
val computedIvParameterSpecForOffset: IvParameterSpec
if (ivForOffsetByteArray.size < AES_BLOCK_SIZE) {
val resizedIvForOffsetByteArray = ByteArray(AES_BLOCK_SIZE)
System.arraycopy(ivForOffsetByteArray, 0, resizedIvForOffsetByteArray, AES_BLOCK_SIZE - ivForOffsetByteArray.size, ivForOffsetByteArray.size)
computedIvParameterSpecForOffset = IvParameterSpec(resizedIvForOffsetByteArray)
} else {
computedIvParameterSpecForOffset = IvParameterSpec(ivForOffsetByteArray, ivForOffsetByteArray.size - AES_BLOCK_SIZE, AES_BLOCK_SIZE)
}
7- in the last step you must init cipher agian and seek your resume to current position
cipher.init(Cipher.ENCRYPT_MODE, key, computedIvParameterSpecForOffset)
val skipBuffer = ByteArray(skip)
cipher.update(skipBuffer, 0, skip, skipBuffer)
this.randomAccessFile.seek(offset)
good luck
Can you help with this #597 related issue with your provided example code?