package edu.stanford.prpl.phoneIdp.server.impl; import java.security.SignatureException; import java.util.Date; import java.util.Iterator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServlet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.stanford.prpl.phoneIdp.common.api.Challenge; import edu.stanford.prpl.phoneIdp.common.api.Response; import edu.stanford.prpl.phoneIdp.common.impl.ChallengeImpl; import edu.stanford.prpl.phoneIdp.common.impl.ResponseImpl; import edu.stanford.prpl.phoneIdp.common.impl.Signature; import edu.stanford.prpl.phoneIdp.server.api.AccountEntry; import edu.stanford.prpl.phoneIdp.server.api.AccountStore; import edu.stanford.prpl.phoneIdp.server.api.AuthCode; import edu.stanford.prpl.phoneIdp.server.api.AuthCodeCache; import edu.stanford.prpl.phoneIdp.server.api.AuthCodeCacheEntry; import edu.stanford.prpl.phoneIdp.server.api.Authenticator; import edu.stanford.prpl.phoneIdp.server.api.Credential; public class AuthenticatorImpl extends Authenticator { private static final Log log = LogFactory.getLog(AuthenticatorImpl.class); public AuthenticatorImpl() { // for testing accountStore_ = AccountStoreImpl.getInstance(); authCodeCache_ = AuthCodeCacheImpl.getInstance(); } @Override public Challenge generateChallenge(Credential cred) { //todo pass in http request so that endpoint can be calculated correctly. Challenge c = new ChallengeImpl(null, null); c.createChallenge(); AuthCode acode = new AuthCodeImpl(c.getAuthCode(), new Date(), false); //store in accountsstore activeauthcodes accountStore_.activateAuthCode(cred.getOpenId(), acode); //store in authcode cache for reverse lookup authCodeCache_.add(c.getAuthCode(), cred.getOpenId()); return c; } public boolean verifyResponse(String signedText) { boolean result = false; //try against all outstanding open authcodes for (Iterator<String> it = authCodeCache_.getAuthCodeOidMap().keySet().iterator(); it.hasNext();) { AuthCodeCacheEntry cacheEntry = authCodeCache_.get(it.next()); Credential userCred_ = accountStore_.get(cacheEntry.getOid_()).getMyCredential(); //Look up AccountsStore with OID. Get shared secret String sharedSecret = userCred_.getSharedSecret(); //Create response object and plain text //decoding the encoded authcode Challenge expectedChallenge = new ChallengeImpl(null, cacheEntry.getAuthCode_().getAuthCode()); expectedChallenge.setEndPointURL(); Response expectedResponse = new ResponseImpl(userCred_, expectedChallenge); String expectedPlainText = expectedResponse.getPlainText(); //Do signing. String expectedSignedText = null; try { expectedSignedText = Signature.calculateRFC2104HMAC(expectedPlainText, sharedSecret); } catch (SignatureException e) { e.printStackTrace(); } log.info("Authcodecache Entry: " + cacheEntry.getAuthCode_().getAuthCode() + ", expectedPlainText: " + expectedPlainText + ", expectedSignedText: " + expectedSignedText + ", actualSignedText: " + signedText); //Match against resp. result = signedText.equals(expectedSignedText); if (result) { //Do housekeeping authCodeCache_.deactivate(cacheEntry.getAuthCode_().getAuthCode()); accountStore_.validateAuthCode(userCred_.getOpenId(), cacheEntry.getAuthCode_()); break; } authCodeCache_.printEntries(); } return result; } @Override public boolean verifyResponse(Response resp) { //Assumption: have been able to construct a response object //with plaintext authCode boolean result = false; //try against all outstanding open authcodes for (Iterator<String> it = authCodeCache_.getAuthCodeOidMap().keySet().iterator(); it.hasNext();) { AuthCodeCacheEntry cacheEntry = authCodeCache_.get(it.next()); //Lookup AccountsStore with OID. Get shared secret String sharedSecret = accountStore_.get(cacheEntry.getOid_()).getMyCredential().getSharedSecret(); //Do signing. String expectedSignedText = null; try { expectedSignedText = Signature.calculateRFC2104HMAC(cacheEntry.getAuthCode_().getAuthCode(), sharedSecret); } catch (SignatureException e) { e.printStackTrace(); } //Match against resp. result = resp.getSignedText_().equals(expectedSignedText); if (result) { break; } } authCodeCache_.printEntries(); return result; } }