Interpause/auto-sd-krita

Encrypt data sent thru network

Closed this issue · 8 comments

Edit - look #32 (comment) for solution

Is your feature request related to a problem? Please describe.
If I understand correctly - currently all data send as plain text on HTTP

Describe the solution you'd like
Maybe HTTPS or something less complicated, anything that will work, python has many simple options.

For example pycrypto https://pypi.org/project/pycrypto/

Basic encryption - generate "random key" for every server start, encrypt key with client-known key and sent to client, and then encrypt messages by this "random key". (this is obviously can be easily unencrypted, but its enough to protect from HTTP bot-spyware)

Krita uses the system Python on Linux, and bundles its own Python on Windows. In either case, installing third-party dependencies requires extra complexity for the user. So any method of obfuscation would have to be done with Python included libraries alone.

HTTPS isn't exactly easy either, the program would have to auto-sign a certificate, and then instruct the user on how to trust it, which would also open the user up to impersonation attacks since the root certificate would have to be included with the program in order to auto-sign.

Possible solutions are to hijack upstream's ngrok support: https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/eb007e5884c23fbc38d7e9d1dd3669625270ca27/modules/ui.py#L68

Alternatively, allow the user to provide their own certificate (that said, signing certs is a real pain).

For now, I suggest just using a VPN.

installing third-party dependencies requires extra complexity for the user

yes I forgot about it, you right

For now, I suggest just using a VPN.

well, I can make some "basic simple hand-made encription"

my idea is simple:

  1. key on server and client in python files (set by user, or by default used default key)
  2. and this key known to server and client used to encrypt http data
  3. backward compatibility (with current client and servers) - client sent get request to server like "is_pc_supported" if server has it request not return 404, same on server - server will enable encription only after client send "is_pc_supported" request

user can change key if they want to, so people who need unique key can do it, and it will not allow "internet spyware" to de-encrypt it because user key will be unique and not sent thru network, it only known to server/lient.

I can make it today, I think, if you are not going to do it il make it then @Interpause

Oh I see what you mean. That could work, and it could even be asymetric.

So it could be like:

  • server generates and saves an (gitignored) AES keypair
  • server prints the public key in the console
  • under krita plugin config tab, paste the public key which krita uses to encrypt requests
  • server decrypts incoming request with private key
  • server encrypts respone with private key
  • client krita plugin decrypts response with public key

And because the user can use some other secure channel to send the public key to the client plugin, its safe.

A few more ideas:

  • it can be opt in; i.e. if the user doesnt provide a public key in the plugin, it will send plaintext instead of encrypting
  • no need to do is "is_pc_supported", server can detect if incoming message is encrypted or plaintext & respond likewise
  • whether the server or krita plugin generates the keypair depends on which is more userfriendly. if its server, the client has to locate the public key in the console output and copy it. If its client, the server has to pause and prompt for the key, or the user has to create a file with the key in it, or paste it into krita_config.yaml...

As for how it could be done:

Small update - I just started making it, I mean I still on it, will finish making something.

Current solution I'm making - simple xor encoding for images and prompts (in client.py modifying post, and on server in utils.py methots to/from_b64 and parse_prompt, super simple).
As I saw it way too complicated to make full encoding on server side. (and solution for ngrok encryption is way more complicated)

I not sure about making "backward compatibility" because it may make "unexpected behaviors" when user thin it encripted when its not (old Krita plugin in Krita, and new server), I skip it for now, I think its better to force user to update plugin+server anyway.

Final solution for this plugin:

auto-sd-krita_enc_mod.zip - there are two files krita_plugin/krita_diff/utils.py and krita_server/utils.py

Instruction:

  1. Copy folders from zip archive above krita_plugin and krita_server to location of auto-sd-krita your server, with replacing two utils.py in its location.
  2. Remember to copy krita_plugin folder to your Krita plugin location.
  3. Open (in text editor) krita_plugin/krita_diff/utils.py in your plugin location (or before copying) and edit
    test_key = "test_encryption_key" - set your_text_key (any text key)
    use_encryption = False - set to True
  4. in folder auto-sd-krita/krita_server/ create file xor_pass.txt with your_text_key - same as in plugin above (at krita_config.yaml file location, top level)
  5. Launch everything - it should work.

As result, to be sure "encryption works", youl see in terminal output: (after starting image generation)
1

Prompt will look like this, instead of "your prompt_as_text same as in Krita"

Encrypted data:

  1. Negative and Positive prompts (from Client to Server)
  2. images - from Client to Server and on the Server before sending back to Client.

Colab note:
On Colab after cloning this repository - replace only krita_server/utils.py and create text file in auto-sd-krita location: echo "test_pass" > xor_pass.txt
And do par 3. above in Instruction - in Krita plugin enable encryption.

@Interpause if you want you can copy this solution to this current version of your plugin. (by default there will be no encryption, so it not broke anything)
(and since you work on new-new version, you can keep it as it is, and just closing this issue)

I post it here just as instruction if someone need it for current version of plugin, il add link to my post above to my Colab script, if someone needs they can apply it.

(there just minimal changes as I described above - in client and server in utils.py methods to/from_b64 and fix_prompt/parse_prompt, super simple)

This can be closed.

Okay, would you be willing to do it as a pull request? That way, your changes are properly credited in the commit history. I will subsequently merge it into the new extension-based version.