std::string hashForUser(const std::string& username) { std::string password; if (username == "user") { password = "******"; } else if (username == "admin") { password = "******"; } else return ""; Poco::MD5Engine md5; md5.update(username); md5.update(std::string(":poco:")); md5.update(password); std::string hashedPassword = digestToHexString(md5); int iterations; std::string salt = saltForUser(username, iterations); Poco::PBKDF2Engine<Poco::HMACEngine<Poco::SHA1Engine> > pbkdf2(salt, iterations, 20); pbkdf2.update(hashedPassword); return digestToBinaryString(pbkdf2); }
AuthenticateResult SCRAMAuthenticator::authenticate(const Credentials& creds, Poco::UInt32 conversationID) { if (conversationID == 0) { conversationID = newConversationID(); Conversation::Ptr pConv = new Conversation; pConv->username = creds.getAttribute(Credentials::ATTR_USERNAME); pConv->clientNonce = creds.getAttribute(Credentials::ATTR_NONCE); pConv->serverNonce = createNonce(); pConv->salt = saltForUser(pConv->username, pConv->iterations); if (!pConv->salt.empty()) { Credentials serverCreds; serverCreds.setAttribute(Credentials::ATTR_NONCE, pConv->serverNonce); serverCreds.setAttribute(Credentials::ATTR_SALT, pConv->salt); serverCreds.setAttribute(Credentials::ATTR_ITERATIONS, Poco::NumberFormatter::format(pConv->iterations)); _conversations.add(conversationID, pConv); pConv->state = STATE_START; return AuthenticateResult(AuthenticateResult::AUTH_CONTINUE, serverCreds, conversationID); } } else { Conversation::Ptr pConv = _conversations.get(conversationID); if (pConv) { if (pConv->state == STATE_START) { const std::string receivedServerNonce = creds.getAttribute(Credentials::ATTR_NONCE); const std::string receivedClientProof = creds.getAttribute(Credentials::ATTR_PASSWORD); const std::string saltedPassword = hashForUser(pConv->username); std::string clientAuthMessage; const std::string computedClientProof = computeClientProof(pConv->username, pConv->clientNonce, pConv->salt, pConv->iterations, saltedPassword, pConv->serverNonce, clientAuthMessage); if (computedClientProof == receivedClientProof && pConv->serverNonce == receivedServerNonce) { std::string serverSignature = computeServerSignature(saltedPassword, clientAuthMessage); Credentials serverCreds; serverCreds.setAttribute(Credentials::ATTR_SIGNATURE, serverSignature); pConv->state = STATE_CLIENT_AUTH; return AuthenticateResult(AuthenticateResult::AUTH_CONTINUE, serverCreds, conversationID); } else { _conversations.remove(conversationID); } } else if (pConv->state == STATE_CLIENT_AUTH) { _conversations.remove(conversationID); Credentials serverCreds; serverCreds.setAttribute(Credentials::ATTR_USERNAME, pConv->username); return AuthenticateResult(AuthenticateResult::AUTH_DONE, serverCreds, conversationID); } } } return AuthenticateResult(); }