Warning when decrypting secret with openssl
I'm trying to write a script to do the decryption of the secret. When calling openssl to decrypt it give me a warning :
$ curl https://ots.fyi/api/get/525bbb9a-7786-437f-b99e-35e8db135054
{"secret":"U2FsdGVkX1/n+zfF2RYRzmUG9WsgJlasBrzt0lUaseY=\n","success":true}
$ echo "U2FsdGVkX1/n+zfF2RYRzmUG9WsgJlasBrzt0lUaseY=" | openssl aes-256-cbc -base64 -pass "pass:w31xcdfbhpl" -md md5 -d
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
test secret
Perhaps this is nothing but it doesn't feel good for a non expert.
The reason for this is simple: With v1.1.1 OpenSSL introduced the possibility to use PBKDF2 key derivation for the encryption secret. The Javascript library used for encrypting the secrets sadly does not support SHA256 key derivation (introduced in v1.1.0c) nor any newer method of key derivation.
Sadly I can't switch to WASM for encryption as Go WASM currently is unusable on mobile clients. (Also I would need to implement PBKDF2 key derivation in my library too.)
The impact of this is as follows:
- A random password is generated on-the-fly when encrypting the secret
- This password is derived into a key having 32 characters (or 256 byte) in order to be usable for an AES256bit encryption
With the current state MD5 is used for the key derivation (for the technical detail how this exactly happens see here: openssl.go#L226-L238). My library would be able to use SHA256 hashes for this task. OpenSSL version v1.1.1 and above encourage the user to use PBKDF2 to calculate the key from the password.
While this is far from being optimal there is currently nothing I can do to solve it as I would need to implement an OpenSSL compliant Javascript library with support for PBKDF2 key derivation and encryption.
For my library this is on the list of things I need to do and as soon as Go WASM is usable in mobile clients (and therefore is supported in all browsers OTS is supporting) I will replace that Javascript library with a WASM compiled version of my library.
I will keep this issue open until this is solved and the Javascript library is replaced as a reminder and documentation about the reason why in OpenSSL v1.1.1 and above there is a warning.
I've been trying to solve this today.
The CryptoJS library has support for PBKDF2, there's also a wrapper for use in Vue.
However, it looks like it's not an easy replacement for the current crypto. For PBKDF2 we need to specify the key size and number of iterations. We also need to know the initialisation vector when decrypting. OpenSSL uses defaults that are pretty slow when executed in CryptoJS.
OpenSSL creates the IV based on the password, but that's undocumented and may change in future versions. So either we have to create the exact same code (and risk breakage when OpenSSL updates) or we have to specify everything (key size, iterations, iv) manually when using OpenSSL to encode/decode. Some information on this Stack Overflow answer. I would expect there to be a standard way to embed this information in the cyphertext, allowing us to decrypt it with only the password. It looks like OpenSSL doesn't do that. :disappointed: (I may be wrong here, but I failed to use js/openssl on the same data without passing it the extra details.)
I noticed that the library OTS is currently using for AES is deprecated.
Is compatibility with OpenSSL a hard requirement? I think it is possible to increase security by using newer crypto, and an OTS-specific encoding for "ciphertext+metadata" may make it possible to use PBKDF2 but break compatibility with OpenSSL.
There is another option that does specify all this required metadata in the ciphertext: GPG in symmetric mode. OpenPGP.js can encrypt/decrypt data in symmetric mode and is compatible with the GPG command line tools. But that may be a bigger change than what's needed.
I'm willing to spend more time figuring this one out if there's a clear path forward. :smile:
Well my path would be to keep compatibility with OpenSSL by using the wasm-openssl implementation instead of switching to something breaking everything users built against OTS and possibly preventing them fully to use OTS to share secrets without a special implementation of some CLI tool for automatic purposes.
The go-openssl library has support up to OpenSSL <3.0.0 (not sure about 3.0.0, haven't read the docs) and my last test resulted in usability on every device except iOS devices though it should be able to run on iOS too. (My example does run on iOS.)
I need to have a look into that and debug it further as far as I can without having a proper iOS debugging environment (needs a Mac, don't have one)…