[FFmpeg-devel] Would a crypto file be acceptable?

Michael Niedermayer michael at niedermayer.cc
Fri Dec 30 00:34:01 EET 2022


On Thu, Dec 29, 2022 at 03:51:24PM +0100, Mark Gaiser wrote:
> On Wed, Dec 28, 2022 at 10:02 PM Michael Niedermayer <michael at niedermayer.cc>
> wrote:
> 
> > Hi
> >
> > On Tue, Dec 27, 2022 at 11:46:38PM +0100, Mark Gaiser wrote:
> > > On Tue, Dec 27, 2022 at 10:40 PM Michael Niedermayer <
> > michael at niedermayer.cc>
> > > wrote:
> > >
> > > > On Wed, Dec 21, 2022 at 04:44:59PM +0100, Mark Gaiser wrote:
> > > > > Hi,
> > > > >
> > > > > The ffmpeg crypto protocol handler [1] allows one to play encrypted
> > > > media.
> > > > >
> > > > > The great thing here is that it allows playback of any media format
> > that
> > > > > ffmpeg supports!
> > > > > Have a container format like mkv as an encrypted blob, no problem
> > for the
> > > > > crypto plugin!
> > > > >
> > > > > I'm explicitly mentioning mkv (though there's many more) here because
> > > > that
> > > > > isn't possible in HLS/MPD. While those streaming formats handle
> > > > encryption
> > > > > too, they are very limited in terms of supported codecs and
> > containers.
> > > > >
> > > > > Playback of encrypted data works like this:
> > > > > ffplay encrypted_file -decryption_key $AES_KEY -decryption_iv $AES_IV
> > > > >
> > > > > While this works just fine, it's limited in use because the
> > cryptography
> > > > > details have to be passed on the command line. Applications that
> > might
> > > > well
> > > > > support much of ffmpeg functionality can't easily hook into the
> > crypto
> > > > > functionality. Take KODI for example, it allows playback of many of
> > the
> > > > > formats ffmpeg supports but anything with crypto just isn't
> > possible. In
> > > > > fact, anything that requires custom command line arguments isn't
> > > > possible.
> > > > > [2]
> > > > >
> > > > > My idea is to make a new file format that would be implemented and
> > > > specced
> > > > > within [1]. My proposed format would be:
> > > > >
> > > > > ---
> > > > > CRYPTO-VERSION:1
> > > > > CRYPTO-KEY:URI:.....
> > > > > CRYPTO-IV:URI:.....
> > > > > encrypted_file
> > > > > ---
> > > > >
> > > > > The URI would be a format type identifier where you can choose
> > between
> > > > URI
> > > > > (to pass a URL to a key blob), BASE64URL (key encoded as base64url)
> > or
> > > > HEX.
> > > > >
> > > > > The above proposed format should be stored in a file with ".crypto"
> > as
> > > > > extension. The crypto plugin [1] would then handle that file. The
> > > > arguments
> > > > > would be filled based on the "properties" in the file. So for
> > example the
> > > > > `decryption_key` argument would be populated with the blob returned
> > from
> > > > > CRYPTO-KEY:URI:<url>. Or with one of the other types.
> > > > >
> > > > > The "encrypted_file" would just be passed through ffmpeg's
> > > > > "ffurl_open_whitelist" like the crypto plugin currently does. Meaning
> > > > that
> > > > > the file could be anything ffmpeg supports.
> > > > >
> > > > > Playing encrypted media would be as simple as:
> > > > > ffplay file.crypto
> > > > >
> > > > > With this mail I'm looking for a confirmation if the above concept
> > would
> > > > be
> > > > > allowed as a patch for ffmpeg? And if not, how can I achieve the same
> > > > > results in a way that would be acceptable? [3]
> > > >
> > > > I understand what you are trying to do but not what the use case for
> > this
> > > > is ?
> > > >
> > > > Encryption has the goal to let one party access data and not another.
> > > > Who are these 2 parties and where does the encrypted media come from?
> > > >
> > > > You mention decentralization, I see nothing related to decentralization
> > > > in this. Or do you suggest that, everytime someone succeeds decrypting
> > a
> > > > file its key would be automatically be published in a decentralized
> > > > public database, so teh next user can safe herself teh troubble from
> > > > finding the key?
> > > >
> > > > If not iam confused why you store keys plainly in files, because this
> > is
> > > > not very secure, so maybe the goal never is to keep the key safe ?
> > > > Or it doesnt matter that someone with physical access in the future
> > would
> > > > also possibly have access to the key. Again you didnt explain the use
> > case
> > > > and who the intended user and adversery is ...
> > > >
> > >
> > > How do you privately want to share a video with someone else? Say A (you)
> > > and B (the other)
> > > Currently you probably use one of the following options or something
> > > similar:
> > > - A uploads it you youtube as unlisted and share that link with B
> > > - A adds it to google photos/drive and share that link B
> > > - A adds it to cloud storage and shares that link with B
> > > etc..
> >
> > I would encrypt it with gpg with Bs public key then send it to B by a
> > secure way, the way depends on what i know of from B
> > * physically give him a usb stick or send that by snail mail
> > * upload it somewhere through tor browser, B then could download it too
> >   using tor browser.
> >
> > If the material is of value to some state actor (hello CIA/NSA/FSB/Mosad)
> > then additional precautions are probably a good idea. (seperate computers,
> > use of
> > internet connections not associated with either A or B and so forth) ive
> > not yet
> > had the need to do this so i have not really thought about it
> >
> > I somewhat avoid all these "paid by giving your data away to advertisers"
> > companies even for things 100% intended to be public. At least when its
> > easy to avoid them.
> > But i dont want to slide too far off topic here, just replying ...
> >
> >
> > >
> > > The common denominator in all those examples is where and how it's
> > stored.
> > > The data is stored in supposedly private storage.
> > > You trust that storage to be private and trust the link to be between you
> > > and the intended target.tended party.
> > >
> > > In this setup your video, that is not intended to be public, is shared.
> > > This works and is the "web2" way of doing things.
> > >
> > > Now enter web3.
> > > Storage now is publicly available to everyone in the distributed world of
> > > web3.
> > > I know, or can know, what you host and vice versa.
> > > If I were to follow the above sharing model the video - which you had
> > > intended to be private - is now very publicly available.
> > >
> > > That's what I'm trying to fix (and am nearly there)!
> > > How I'm fixing this is as follows (this is a bit outside the scope of the
> > > initial question but its context might help you frame the question
> > > properly):
> > > - A has a public and private key pair. So does B.
> > > - A knows the public key of B and vice versa.
> > > - Both A and B have data which is encrypted on their end with keys
> > > unrelated to their own public and private keys
> > > - (this is the important bit!) Wrapped around their private data is a
> > > "metadata" file where their own private key serves to encrypt/decrypt
> > that
> > > file
> > > - A can now re-encrypt the metadata to the public key of B and share that
> > > metadata with B.
> > > - B can now play the file backed by the metadata that A intended to
> > share.
> > > - The result being file sharing where you can access it if:
> > >  -- you have access to the distributed storage
> > >  -- you have the keys to decrypt the metadata
> > > ---- This all works already, right here and now on my pc! ----
> > >
> > > The tricky part here is for anyone using this scheme to play this file.
> > > Right now i'm doing this with a command line like:
> > > ffplay crypto://encrypted_file -decryption_key $AES_KEY -decryption_iv
> > > $AES_IV
> > >
> > > For brevity's sake, consider the "metadata" file named above to be the
> > > _encrypted_ version of the ".crypto" file i'm proposing.
> > > For B to play it, B must decrypt that file (now it's like the proposed
> > > .crypto file) and can now happily play this file in ffmpeg-backed players
> > > that allow the proposed crypto file.
> >
> > iam not against the idea in principle.
> > Some maybe technical detail here is that the unencrypted  .crypto file
> > should never be stored on disk. Because its leaking the AES key and anyone
> > with physical access to the machine later could potentially obtain that
> > key.
> > A better solution may be to only store the .crypto file encrypted with gpg
> > so when libavformat accesses it, gpg (agent) would look in it and check if
> > it has a matching private key. if so it would decrypt it in accordance to
> > its configuration.
> > From the user side the user could get a popup asking if the file should be
> > decrypted and if needed for the users password protecting the private key.
> > This is the same you would get today when you use gpg and have it
> > configured
> > accordingly.
> > The main goal here is to never have the decrypted .crypto file on disk,
> > just
> > to pass the encrypted one through gpg and use that to then decrypt teh main
> > multimedia material.
> >
> > of course something else than gpg can be used but iam thinking that it
> > wouldnt hurt if more people had gpg setup properly and knew how to use
> > it in this world of mass surveliance. So having gpg as an option could be
> > interresting.
> >
> 
> I see!
> What you're describing here is a much more interesting approach for sure!
> 
> To be frank, I don't think I can implement that. I have some crypto
> knowledge and get the concept but implementing that in code is a lot more
> difficult.
> I can probably implement my suggested file format :)
> 

> Say, for the sake of the workflow in user applications, that one would
> implement your suggestion.
> The .crypto file would only ever exist in encrypted form on disc.
> Now how would the flow go from opening that file to a user interaction?
> The way I see it is that "some callback" needs to happen from ffmpeg to the
> user.
> But as far as I'm aware, no such interaction scheme exists in the ffmpeg
> context?
> 
> Could you paint me a workflow example of how this can be implemented?
> Ideally with no changes on applications using ffmpeg.

Ive not implemented this so i may be slightly wrong but the way i
understand it is
you call gpg to ask it to decrypt the data piped into it or by some other
means like gpgme. Gpg then looks if a gpg-agent is running (this may be even on a
different machiene if you run "ffmpeg -> gpg" through a ssh session)
that gpg-agent then looks into itself to see if it has a 
private key / password that it can use, if it needs a password it will
run the configured pinentry program to ask the user for the password of her
private key. That can be cached depending on configuration. There are
also different pinentry programs, to match different GUI and text mode
environments.). These pinentry programs could in principle itself have
some sort of database and rules to cache passphrases.
once gpg-agent has everything it will securely decrypt the
data for you while none of the keys ever get stored on disk, and the
private keys stay on the user system even if the decryption happens
on a remote sytem. Thats at least how i understand it.

libavformat should not really need to do anything beyond asking gpgme
to decrypt it i think if gpg and gpg-agent are setup correctly
If that ffmpeg program is run by the user she may get a popup for her
private key password.
If she wants to run this in a script without her interaction she only
has to make sure the gpg-agent has key/passphrase cached. (which is
a bit iffy security wise, so would be better to use a seperate private
key for automated decryption)

Note: while i used gpg many times as a user, i have never used gpgme
as a developer, so i am not the right one to really ask about it :)

PS: before you spend alot of time on implementing this, try to make sure
people who had objections in this thread are ok with this too.

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

You can kill me, but you cannot change the truth.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20221229/e18029b5/attachment.sig>


More information about the ffmpeg-devel mailing list