use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.
the class U2FServerUnison method processSignResponse.
@Override
public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2FException {
if (log.isDebugEnabled()) {
log.debug(">> processSignResponse");
}
String sessionId = signResponse.getSessionId();
String browserDataBase64 = signResponse.getClientData();
String rawSignDataBase64 = signResponse.getSignatureData();
SignSessionData sessionData = dataStore.getSignSessionData(sessionId);
if (sessionData == null) {
throw new U2FException("Unknown session_id");
}
String appId = sessionData.getAppId();
SecurityKeyData securityKeyData = null;
for (SecurityKeyData temp : dataStore.getSecurityKeyData(sessionData.getAccountName())) {
if (Arrays.equals(sessionData.getPublicKey(), temp.getPublicKey())) {
securityKeyData = temp;
break;
}
}
if (securityKeyData == null) {
throw new U2FException("No security keys registered for this user");
}
String browserData = new String(Base64.decodeBase64(browserDataBase64));
byte[] rawSignData = Base64.decodeBase64(rawSignDataBase64);
if (log.isDebugEnabled()) {
log.debug("-- Input --");
log.debug(" sessionId: " + sessionId);
log.debug(" publicKey: " + Hex.encodeHexString(securityKeyData.getPublicKey()));
log.debug(" challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
log.debug(" accountName: " + sessionData.getAccountName());
log.debug(" browserData: " + browserData);
log.debug(" rawSignData: " + Hex.encodeHexString(rawSignData));
}
verifyBrowserData(new JsonParser().parse(browserData), "navigator.id.getAssertion", sessionData);
AuthenticateResponse authenticateResponse = RawMessageCodec.decodeAuthenticateResponse(rawSignData);
byte userPresence = authenticateResponse.getUserPresence();
int counter = authenticateResponse.getCounter();
byte[] signature = authenticateResponse.getSignature();
if (log.isDebugEnabled()) {
log.debug("-- Parsed rawSignData --");
log.debug(" userPresence: " + Integer.toHexString(userPresence & 0xFF));
log.debug(" counter: " + counter);
log.debug(" signature: " + Hex.encodeHexString(signature));
}
if ((userPresence & UserPresenceVerifier.USER_PRESENT_FLAG) == 0) {
throw new U2FException("User presence invalid during authentication");
}
if (counter <= securityKeyData.getCounter()) {
throw new U2FException("Counter value smaller than expected!");
}
byte[] appIdSha256 = crypto.computeSha256(appId.getBytes());
byte[] browserDataSha256 = crypto.computeSha256(browserData.getBytes());
byte[] signedBytes = RawMessageCodec.encodeAuthenticateSignedBytes(appIdSha256, userPresence, counter, browserDataSha256);
if (log.isDebugEnabled()) {
log.debug("Verifying signature of bytes " + Hex.encodeHexString(signedBytes));
}
if (!crypto.verifySignature(crypto.decodePublicKey(securityKeyData.getPublicKey()), signedBytes, signature)) {
throw new U2FException("Signature is invalid");
}
dataStore.updateSecurityKeyCounter(sessionData.getAccountName(), securityKeyData.getPublicKey(), counter);
if (log.isDebugEnabled()) {
log.debug("<< processSignResponse");
}
return securityKeyData;
}
use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.
the class U2FServerUnison method verifyBrowserData.
private void verifyBrowserData(JsonElement browserDataAsElement, String messageType, EnrollSessionData sessionData) throws U2FException {
if (!browserDataAsElement.isJsonObject()) {
throw new U2FException("browserdata has wrong format");
}
JsonObject browserData = browserDataAsElement.getAsJsonObject();
// check that the right "typ" parameter is present in the browserdata JSON
if (!browserData.has(TYPE_PARAM)) {
throw new U2FException("bad browserdata: missing 'typ' param");
}
String type = browserData.get(TYPE_PARAM).getAsString();
if (!messageType.equals(type)) {
throw new U2FException("bad browserdata: bad type " + type);
}
// check that the right challenge is in the browserdata
if (!browserData.has(CHALLENGE_PARAM)) {
throw new U2FException("bad browserdata: missing 'challenge' param");
}
if (browserData.has(ORIGIN_PARAM)) {
verifyOrigin(browserData.get(ORIGIN_PARAM).getAsString());
}
byte[] challengeFromBrowserData = Base64.decodeBase64(browserData.get(CHALLENGE_PARAM).getAsString());
if (!Arrays.equals(challengeFromBrowserData, sessionData.getChallenge())) {
throw new U2FException("wrong challenge signed in browserdata");
}
// TODO: Deal with ChannelID
}
use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.
the class U2fAuth method startAuthentication.
private void startAuthentication(HttpServletRequest request, HttpServletResponse response, AuthStep as) throws ServletException, MalformedURLException, IOException {
AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
// SharedSession.getSharedSession().getSession(req.getSession().getId());
HttpSession session = ((HttpServletRequest) request).getSession();
UrlHolder holder = (UrlHolder) request.getAttribute(ProxyConstants.AUTOIDM_CFG);
RequestHolder reqHolder = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getHolder();
String urlChain = holder.getUrl().getAuthChain();
AuthChainType act = holder.getConfig().getAuthChains().get(reqHolder.getAuthChainName());
AuthMechType amt = act.getAuthMech().get(as.getId());
HashMap<String, Attribute> authParams = (HashMap<String, Attribute>) session.getAttribute(ProxyConstants.AUTH_MECH_PARAMS);
String challengeStoreAttribute = authParams.get("attribute").getValues().get(0);
String encyrptionKeyName = authParams.get("encryptionKeyName").getValues().get(0);
String uidAttributeName = authParams.get("uidAttributeName").getValues().get(0);
String formURI = authParams.get("formURI").getValues().get(0);
List<SecurityKeyData> keys;
try {
keys = U2fUtil.loadUserKeys(userData, challengeStoreAttribute, encyrptionKeyName);
} catch (Exception e1) {
throw new ServletException("Could not loak keys", e1);
}
Set<String> origins = new HashSet<String>();
String appID = U2fUtil.getApplicationId(request);
origins.add(appID);
U2FServer u2f = new U2FServerUnison(this.challengeGen, new UnisonDataStore(UUID.randomUUID().toString(), keys), new BouncyCastleCrypto(), origins);
String uid = userData.getAttribs().get(uidAttributeName).getValues().get(0);
if (keys == null || keys.size() == 0) {
if (amt.getRequired().equals("required")) {
as.setSuccess(false);
}
holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
return;
}
U2fSignRequest sigReq = null;
try {
sigReq = u2f.getSignRequest(uid, appID);
} catch (U2FException e) {
logger.error("Could not start authentication", e);
if (amt.getRequired().equals("required")) {
as.setSuccess(false);
}
holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
return;
}
Gson gson = new Gson();
request.getSession().setAttribute(AUTH_SIGN_REQ, sigReq);
request.getSession().setAttribute(AUTH_SIGN_REQ_JSON, gson.toJson(sigReq));
request.getSession().setAttribute(SERVER, u2f);
response.sendRedirect(formURI);
}
use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.
the class BouncyCastleCrypto method verifySignature.
@Override
public boolean verifySignature(PublicKey publicKey, byte[] signedBytes, byte[] signature) throws U2FException {
try {
Signature ecdsaSignature = Signature.getInstance("SHA256withECDSA");
ecdsaSignature.initVerify(publicKey);
ecdsaSignature.update(signedBytes);
return ecdsaSignature.verify(signature);
} catch (InvalidKeyException e) {
throw new U2FException("Error when verifying signature", e);
} catch (SignatureException e) {
throw new U2FException("Error when verifying signature", e);
} catch (NoSuchAlgorithmException e) {
throw new U2FException("Error when verifying signature", e);
}
}
use of com.google.u2f.U2FException in project OpenUnison by TremoloSecurity.
the class U2FServerReferenceImpl method processRegistrationResponse.
@Override
public SecurityKeyData processRegistrationResponse(RegistrationResponse registrationResponse, long currentTimeInMillis) throws U2FException {
Log.info(">> processRegistrationResponse");
String sessionId = registrationResponse.getSessionId();
String clientDataBase64 = registrationResponse.getClientData();
String rawRegistrationDataBase64 = registrationResponse.getRegistrationData();
Log.info(">> rawRegistrationDataBase64: " + rawRegistrationDataBase64);
EnrollSessionData sessionData = dataStore.getEnrollSessionData(sessionId);
if (sessionData == null) {
throw new U2FException("Unknown session_id");
}
String appId = sessionData.getAppId();
String clientData = new String(Base64.decodeBase64(clientDataBase64));
byte[] rawRegistrationData = Base64.decodeBase64(rawRegistrationDataBase64);
Log.info("-- Input --");
Log.info(" sessionId: " + sessionId);
Log.info(" challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
Log.info(" accountName: " + sessionData.getAccountName());
Log.info(" clientData: " + clientData);
Log.info(" rawRegistrationData: " + Hex.encodeHexString(rawRegistrationData));
RegisterResponse registerResponse = RawMessageCodec.decodeRegisterResponse(rawRegistrationData);
byte[] userPublicKey = registerResponse.getUserPublicKey();
byte[] keyHandle = registerResponse.getKeyHandle();
X509Certificate attestationCertificate = registerResponse.getAttestationCertificate();
byte[] signature = registerResponse.getSignature();
List<Transports> transports = null;
try {
transports = U2fAttestation.Parse(attestationCertificate).getTransports();
} catch (CertificateParsingException e) {
Log.warning("Could not parse transports extension " + e.getMessage());
}
Log.info("-- Parsed rawRegistrationResponse --");
Log.info(" userPublicKey: " + Hex.encodeHexString(userPublicKey));
Log.info(" keyHandle: " + Hex.encodeHexString(keyHandle));
Log.info(" attestationCertificate: " + attestationCertificate.toString());
Log.info(" transports: " + transports);
try {
Log.info(" attestationCertificate bytes: " + Hex.encodeHexString(attestationCertificate.getEncoded()));
} catch (CertificateEncodingException e) {
throw new U2FException("Cannot encode certificate", e);
}
Log.info(" signature: " + Hex.encodeHexString(signature));
byte[] appIdSha256 = crypto.computeSha256(appId.getBytes());
byte[] clientDataSha256 = crypto.computeSha256(clientData.getBytes());
byte[] signedBytes = RawMessageCodec.encodeRegistrationSignedBytes(appIdSha256, clientDataSha256, keyHandle, userPublicKey);
Set<X509Certificate> trustedCertificates = dataStore.getTrustedCertificates();
if (!trustedCertificates.contains(attestationCertificate)) {
Log.warning("attestion cert is not trusted");
}
verifyBrowserData(new JsonParser().parse(clientData), "navigator.id.finishEnrollment", sessionData);
Log.info("Verifying signature of bytes " + Hex.encodeHexString(signedBytes));
if (!crypto.verifySignature(attestationCertificate, signedBytes, signature)) {
throw new U2FException("Signature is invalid");
}
// The first time we create the SecurityKeyData, we set the counter value to 0.
// We don't actually know what the counter value of the real device is - but it will
// be something bigger (or equal) to 0, so subsequent signatures will check out ok.
SecurityKeyData securityKeyData = new SecurityKeyData(currentTimeInMillis, transports, keyHandle, userPublicKey, attestationCertificate, /* initial counter value */
0);
dataStore.addSecurityKeyData(sessionData.getAccountName(), securityKeyData);
Log.info("<< processRegistrationResponse");
return securityKeyData;
}
Aggregations