I know there's little reason to still use ENCRYPT()
nowadays, what with bcrypt
being almost ubiquitous and MySQL providing better hashes such as SHA1
.
But while dabbling with ENCRYPT()
on MySQL 5.6.12 (OpenSuSE 13.1, x64), I noticed an anomaly with its output that I at first attributed to the entropy pool being depleted (it could have been), and then possibly to the salt being leaked between connections.
Upon verification, it turned out not to be the case.
Rather, the salt is derived from the UNIX timestamp. So two calls to ENCRYPT()
within the same second will yield identical salts, and the salt repeats itself exactly every one hour, 12 minutes, 16 seconds.
while(true); do \
echo "SELECT NOW(),ENCRYPT('test');" \
| mysql test | grep -v ENCRYPT; \
done | uniq -c
54 2014-05-14 00:13:16 w5kVzeZkJCcqM
148 2014-05-14 00:13:17 x5/h3KfsBkEYk
150 2014-05-14 00:13:18 y5thvRDxwJgM6
145 2014-05-14 00:13:19 z5RL9IZ0..XH6
141 2014-05-14 00:13:20 .6asQOJRqB1i2
130 2014-05-14 00:13:21 /6J1nHNWbi6Ac
124 2014-05-14 00:13:22 06NT9j.EegRJs
Of course I can supply my own salt and get it from a random source - TO_BASE64(CONCAT(CHAR(RAND()*256),CHAR(RAND()*256)))
or something, which should get the same character range as the original salt in its first two bytes, so ENCRYPT()
's whipping up a salt of its own needs only be a last-ditch effort.
And the salt isn't expected to be secret, so it being known beforehand is maybe not too great a problem.
Even so, using time()
for salting doesn't seem a very good option to me (this answer also confirms this).
Am I missing something obvious? Is maybe this behaviour configurable somehow (apart from recompiling)? Is it a known feature (I wasn't able to find any reference on Google or MySQL KB)?