The encryption algorithm of mosquitto authentication plug-in mosquitto-auth-plug

mosquitto-auth-plug

PBKDF2 encryption


PBKDF2 actually selects a hash algorithm, and encrypts the password after multiple iterative calculations after adding salt. Of course, it is irreversible, which can prevent collision cracking. The more iterations, the safer it is.

mosquitto-auth-plug uses PBKDF2 encryption, and the compiled np executable program can be encrypted: (The following assumes that the password is admin)

./np -p admin

得到加密密码:
PBKDF2$sha256$901$qiCmZmc2ZKEJkEaL$7Nw6lpv9G0IoEgxcTfEbx4ajtMQD3shC

The returned password is separated by the $ symbol, the first is the PBKDF2 logo, the sha256 hash algorithm is used by default, 901 iterations of encryption are performed, and then openssl is used to generate a random number that passes through the BASE64 string, which is the salt, and finally the key generated by the real PBKDF2 .

After the password is stored in the database, when the user logs in with the username and password, auth-plug will query the database to obtain the password according to the username, and then encrypt the password according to the definition of the $ split identifier, and finally put the encrypted password with the database. The password of the user is compared to know whether the user's password is correct.

Calculate password for auth-plug using golang


golang.org/x/crypto/pbkdf2This is go's PBKDF2 encryption algorithm, golang.org is blocked by the wall, but it doesn't matter, there is a mirror image of crypto on github: https://github.com/golang/crypto

PBKDF2 calling method:

func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte

By looking at the np.c source file of auto-plug, you can know how to generate the password. In fact, it is to generate the salt first, call the RAND_bytes function of openssl to generate the default 12-byte random number, and then perform base64 to generate the salt.
Iter defaults to 901 times, the length of keyLen is 24, and the hash algorithm of h is sha256. After calling the Key method, the returned []byte array is passed through base64.StdEncoding.EncodeToString to obtain the encrypted Key, and finally spliced ​​with the $ symbol according to the rules written above. to get the final password.

Encryption speed and password length optimization


I tested the encryption of the golang version using the default iter = 901. I feel that the speed is too slow. It is impossible for a server to have high concurrency at this speed. Anyway, the security of the general system is not so high, so you can adjust and reduce the number of iters. In fact, even if iter is set to zero, PBKDF2 also executes sha256 twice, plus a 16-byte salt, which is much safer than MD5 of general websites, so let’s make do with it.
In fact, I want to test how much faster the encryption speed of np.c is than that of golang. If the gap is large, I can use cgo to write a replacement. I have no time to do it yet.

After more than ten minutes, I couldn't help but modify the np.c program and test it briefly. The same iter=901, the c version is almost twice as fast as golang, sweat!

However, when iter is relatively small, such as iter=9, there is not much difference between the two. Even when iter=0, the go version is faster. It should be that the c version does not optimize the reallocation of memory for each call, and go is better than GC.
For my application, there is no need to optimize with cgo because of the smaller iter.

The crypto/rand that comes with golang is too slow. It github.com/NebulousLabs/fastrandwill be much faster to use it. It is twice as fast to generate a 12-byte random string. If the number of bytes generated is large, it will be faster, even more than 10 times faster.

In addition, the length of the final password spliced ​​with $ is too long. If the database uses Redis, it is too wasteful of memory. The first three paragraphs can be greatly shortened, or even unnecessary. Then modify the source code of mosquitto-auth-plug to cooperate with optimization to reduce the length. .

If you are not afraid of slowness but want to improve security, you can set iter to a larger value.
Of course, since you have the source code, you can change whatever encryption method you use. If you have high requirements, you can even change it to bcrypt, which is more secure.
You can’t have both. The more secure hash encryption is, the slower the speed, because brute force crackers also need more time to collide and crack.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325671838&siteId=291194637