kean / Nuke

Image loading system
https://kean.blog/nuke
MIT License
7.94k stars 519 forks source link

What would be the most elegant way to decrypt image data before it is sent to the pipeline? #794

Open tkrajacic opened 1 week ago

tkrajacic commented 1 week ago

Suppose I have images that are encrypted on the server and whenever I fetch them I have a key (per image) that I need to decrypt the Data with.

I could basically copy all of the regular DataLoader implementation, pass the key as fragment in the image URL, so it will never be sent, but the loader could then use it from the request to decode the Data. This seems doable but requires copying most of the implementation of the URLSession based loading.

It would be nicer if there was a way to just intercept the data in the pipeline. Maybe there is and I just haven't found it. Image processors would be in the right place of the pipeline I think, but they already assume valid image data iiuc.

Ideally I think I want to create an image request that I can use in SwiftUI like

LazyImage(request: .decryptingRequest(for: urlRequest, key: key))
kean commented 1 week ago

The decoding happens using ImageDecoding objects. I suggest adding the decryption step during that stage, and then invoking the built-in decoders. See https://kean-docs.github.io/nuke/documentation/nuke/image-decoding for more information.

tkrajacic commented 1 week ago

Ah, that sounds promising!

Thanks for making such a great library. It is amazing!

Edit: I can use the userInfo dictionary for the key I suppose!

ImagePipeline.shared = ImagePipeline {
   $0.makeImageDecoder = { context in
      if let key = context.request.userInfo["key"] as? Data {
         var copy = context
         copy.data = try! decrypt(data: context.data, using: key)
         return ImageDecoderRegistry.shared.decoder(for: copy)
      }
      return ImageDecoderRegistry.shared.decoder(for: context)
   }
}

When creating the image pipeline, I set the makeImageDecoder closure to check for a given key and then decode the data. The data is properly decoded, but the image state says Failed to decode image data using decoder Nuke.ImageDecoders.Default even though I can check with the debugger that the default decoder can in fact decode the image.

kean commented 3 days ago

Failed to decode image data using decoder Nuke.ImageDecoders.Default even though I can check with the debugger that the default decoder can in fact decode the image.

The code that you provided looks good.

Btw, makeImageDecoder is called on the pipeline's background queue, so I think it's an OK trade-off performance-wise to put it there.