Is it a problem, that the start of a crypt ciphertext can be easily guessed?
That happens by design for excellent encryption systems, e.g. because every ciphertext starts with a version and key identifier. But in the case at hand, that's the symptom of a devastating error: AES-CTR is being used for different records with the same constant IV, therefore the cipher degenerates to XOR with a constant bitstring, which is very poor encryption.
AES-CTR mode is designed to be used as follows:
- At encryption of each cryptogram, it's chosen a fresh IV, usually 8-bytes, by some process than makes it very unlikely that the same IV will be chosen again for a given key. An incremental counter might do, if there's no way it can be reset†.
- That IV is put as the first bytes of the ciphertext. These bytes are used at decryption to get the IV.
- That IV is extended to 128-bit, typically internally to the implementation of the CTR-mode cipher.
I need the output to be unintelligible and unalterable.
Then do not use AES-CTR. It aims only at confidentiality of the data, not integrity, which typically is also an operational requirement, and one we read in "unalterable". For this we have authenticated encryption, e.g. AES-GCM, and variants of that which make nonce (aka IV) reuse a lesser disaster, e.g. AES-GCM-SIV.
Caution: defining the operational requirement of cryptography in database applications is hard. For example, when encrypting the answer to a secret question used for user authentication purpose, authenticated encryption of that data in isolation is not enough (because it still allows substituting the unknown answer with a known one). One solution to that is to enter the identification of the cell encrypted as GCM Additional Authenticated Data.
† It's often difficult to keep track of which IVs have been used. One strategy then is to generate the IVs at random: probability of two identical $b$-bit IVs after $n$ are drawn is no more than $n(n-1)/2^{b+1}$ if a working true random number generator is used. Up to $n$ in millions, that's fine for the usual $b=64$. Above that, an option is to use $b=80$ or $b=96$, noting that no more than $2^{132-b}$ bytes should be encrypted with the same IV.
Are you reusing the same IV for multiple encryptions?
Yes. If it were random, how would the decrypting function know it ahead of time for each messsage? Is that a design problem for me to solve?
In the youtube videos the guy mentioned lots of internet traffic still use 128bit. But oke i can switch to 256. And i did also find GCM mode and am gonna try that next. The Node.js std "crypto" lib is built on OpenSSL, and i dont really want extra dependencies, but tnx for the info.
– Rolands Laucis Dec 29 '22 at 16:17