I am doing a project wherein, to access the service, the client needs to authenticate itself(client has a username and password) over RMI. I want to achieve this without using SSL(hence, modification and sniffing are the major threats).
Here's a "token" that a client sends every time a service is accessed.
class Token {
String username;
byte[] encryptedText;
}
Encrypted Text variable contains a combination of password and timestamp that is encrypted with AES-256 CBC using the password itself as the key. eg:
encryptedText[0] = AES(20) //encrypt length of password
encryptedText[1] = AES(30) //encrypt length of TimeStamp
encryptedText[2-21] = AES(password) //encrypted password
encryptedText[22-51] = AES(timestamp) //encrypted timestamp
The server on receiving this token retrieves the password for the username and tries to decrypt the encrypted text with the password as the key. If the result is not a combination of password and a recent TimeStamp, it is a wrong attempt.
I know this is not scalable, since every time a service is requested, a record has to be fetched, but is this secure?
From what I can think of:-
I'm assuming that AES()
doesn't just mean the pseudo-random permutation of a block cipher, but rather the block cipher with a mode of operation and a padding.
It would be possible to recover the password through a padding oracle attack if it's possible to distinguish a bad padding from a good padding. This is very likely, because the response is probably finished earlier when there is a BadPaddingException and further computation cannot be done.
The main two problems are that you're
This pseudo encryption code is better:
// salt and masterHash can be cached for multiple requests
salt = SecureRandom().nextBytes(8 bytes)
// adjust iterations (65336) according to appropriate performance:
masterHash = pbkdf2(password, salt, 65336)
iv = SecureRandom().nextBytes(16 bytes)
sessionKey = SecureRandom().nextBytes(16 bytes)
encKey = hmacSha256(masterHash, "enc") // crop according to intended AES key size
macKey = hmacSha256(masterHash, "mac")
ciphertext = AES(encKey, iv, sessionKey + ts.length + ts)
tag = hmacSha256(macKey, username + salt + iv + ciphertext)
return salt + iv + ciphertext + tag
Here +
means concatenation and AES
means AES in CBC mode with PKCS#7 padding.
The receiver must first derive the macKey
to then calculate the tag
and then check whether the transmitted tag
matches with the calculated tag
. If it does then decrypt the ciphertext. If this works, then the sessionKey
can be used for further communication.
The only thing that an attacker could do, is preventing you from authenticating to the server by manipulating the transmitted request in order to produce a failed authentication on the server.