We are using the security hardware key to encrypt/decrypt FOR E2EE within the Angular client-side.
For that we are using
CryptoJS.AES.encrypt(data, key).toString();
to encrypt
and
CryptoJS.AES.decrypt(data, key).toString(CryptoJS.enc.Utf8);
to decrypt.
After registration of the hardware key, we receive the public key credentials, then we applied
navigator.credentials.create({ publicKey: publicKeyOptions })
to create key pair in the device in order to apply the symmetric encryption with the public and private key.
Now, my plan is to save the credential.id encrypted by the public key provided in the DB and I am wondering how can I decrypt the data back on the client side, and how can we get the private key for that.
Correct us if our path is wrong, we are open to discussion.
I'm not familiar with CryptoJS but the documentation appears to suggest that the default behaviour for
AES.encrypt
is to use CBC mode with PKCS#7 padding. That however is not a safe way to encrypt data by itself because it doesn't include any authentication. CBC mode also requires a random IV for every message and the CryptoJS documentation isn't clear on whether it's doing that, nor where the IV is stored.If you take care of the issue with IVs, you could combine that CBC encryption with an authentication scheme, for example by using HMAC to authenticate the IV and ciphertext. However, that's getting a bit complex.
Browsers themselves provide an encryption interface. That interface supports AES-GCM, which is a mode that combines encryption and authentication in a reasonable way. You must pass in a unique none for every message, but that's less fraught than building your own construction with CryptoJS.
Thus I would recommend either finding a high-level library that builds on top of WebCrypto, or else carefully using AES-GCM from WebCrypto for performing encryption.
Another issue is that WebAuthn does not currently provide any symmetric key that can be used for encryption. You mention using the private key, but the private key in WebAuthn never leaves the authenticator and thus cannot be used for encryption in the browser.
There is a WebAuthn extension to provide symmetric keys that would work for you purpose, but it is still experimental. You would need to download Chrome Canary and set chrome://flags/#enable-experimental-web-platform-features in order to access it.