use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.
the class Registration method doFilter.
@Override
public void doFilter(HttpFilterRequest request, HttpFilterResponse response, HttpFilterChain chain) throws Exception {
if (request.getMethod().equalsIgnoreCase("GET")) {
// TODO switch this off
AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
String accountName = userData.getAttribs().get(this.uidAttributeName).getValues().get(0);
List<SecurityKeyData> keys = U2fUtil.loadUserKeys(userData, challengeStoreAttribute, encyrptionKeyName);
Set<String> origins = new HashSet<String>();
String appID = U2fUtil.getApplicationId(request.getServletRequest());
origins.add(appID);
U2FServer u2f = new U2FServerUnison(this.challengeGen, new UnisonDataStore(UUID.randomUUID().toString(), keys, (this.requireAttestation ? this.attestationCerts : new HashSet<X509Certificate>())), new BouncyCastleCrypto(), origins, this.requireAttestation);
RegistrationRequest regRequest = u2f.getRegistrationRequest(accountName, appID);
request.getSession().setAttribute(Registration.REGISTRATION_REQUEST_JSON, gson.toJson(regRequest));
request.getSession().setAttribute(Registration.REGISTRATION_REQUEST, regRequest);
request.getSession().setAttribute(Registration.SERVER, u2f);
request.setAttribute(REGISTRATION_URI, request.getRequestURL().toString());
request.getRequestDispatcher(this.challengeURI).forward(request.getServletRequest(), response.getServletResponse());
} else if (request.getMethod().equalsIgnoreCase("POST")) {
U2FServer u2f = (U2FServer) request.getSession().getAttribute(SERVER);
if (logger.isDebugEnabled()) {
logger.debug("response : '" + request.getParameter("tokenResponse").getValues().get(0) + "'");
}
RegistrationResponseHolder rrh = gson.fromJson(request.getParameter("tokenResponse").getValues().get(0), RegistrationResponseHolder.class);
RegistrationResponse rr = new RegistrationResponse(rrh.getRegistrationData(), rrh.getClientData(), rrh.getClientData());
try {
u2f.processRegistrationResponse(rr, System.currentTimeMillis());
} catch (U2FException e) {
logger.error("Could not register", e);
request.setAttribute("register.result", false);
request.getRequestDispatcher(this.registrationCompleteURI).forward(request.getServletRequest(), response.getServletResponse());
return;
}
AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
String encrypted = U2fUtil.encode(u2f.getAllSecurityKeys("doesntmatter"), encyrptionKeyName);
WFCall wc = new WFCall();
wc.setName(this.workflowName);
wc.setUidAttributeName(this.uidAttributeName);
TremoloUser tu = new TremoloUser();
tu.setUid(userData.getAttribs().get(this.uidAttributeName).getValues().get(0));
tu.getAttributes().add(new Attribute(this.uidAttributeName, userData.getAttribs().get(this.uidAttributeName).getValues().get(0)));
tu.getAttributes().add(new Attribute(this.challengeStoreAttribute, encrypted));
wc.setUser(tu);
Map<String, Object> req = new HashMap<String, Object>();
req.put(ProvisioningParams.UNISON_EXEC_TYPE, ProvisioningParams.UNISON_EXEC_SYNC);
wc.setRequestParams(req);
GlobalEntries.getGlobalEntries().getConfigManager().getProvisioningEngine().getWorkFlow(this.workflowName).executeWorkflow(wc);
request.setAttribute("register.result", true);
request.getRequestDispatcher(this.registrationCompleteURI).forward(request.getServletRequest(), response.getServletResponse());
}
}
use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.
the class U2FServerUnison method getSignRequest.
@Override
public U2fSignRequest getSignRequest(String accountName, String appId) throws U2FException {
if (log.isDebugEnabled()) {
log.debug(">> getSignRequest " + accountName);
}
List<SecurityKeyData> securityKeyDataList = dataStore.getSecurityKeyData(accountName);
byte[] challenge = challengeGenerator.generateChallenge(accountName);
String challengeBase64 = Base64.encodeBase64URLSafeString(challenge);
ImmutableList.Builder<RegisteredKey> registeredKeys = ImmutableList.builder();
if (log.isDebugEnabled()) {
log.debug(" challenge: " + Hex.encodeHexString(challenge));
}
for (SecurityKeyData securityKeyData : securityKeyDataList) {
SignSessionData sessionData = new SignSessionData(accountName, appId, challenge, securityKeyData.getPublicKey());
String sessionId = dataStore.storeSessionData(sessionData);
byte[] keyHandle = securityKeyData.getKeyHandle();
List<Transports> transports = securityKeyData.getTransports();
if (log.isDebugEnabled()) {
log.debug("-- Output --");
log.debug(" sessionId: " + sessionId);
log.debug(" keyHandle: " + Hex.encodeHexString(keyHandle));
}
String keyHandleBase64 = Base64.encodeBase64URLSafeString(keyHandle);
if (log.isDebugEnabled()) {
log.debug("<< getRegisteredKey " + accountName);
}
registeredKeys.add(new RegisteredKey(U2FConsts.U2F_V2, keyHandleBase64, transports, appId, sessionId));
}
return new U2fSignRequest(challengeBase64, registeredKeys.build());
}
use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.
the class U2FServerUnison method processRegistrationResponse.
@Override
public SecurityKeyData processRegistrationResponse(RegistrationResponse registrationResponse, long currentTimeInMillis) throws U2FException {
log.debug(">> processRegistrationResponse");
String sessionId = registrationResponse.getSessionId();
String clientDataBase64 = registrationResponse.getClientData();
String rawRegistrationDataBase64 = registrationResponse.getRegistrationData();
log.debug(">> 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);
if (log.isDebugEnabled()) {
log.debug("-- Input --");
log.debug(" sessionId: " + sessionId);
log.debug(" challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
log.debug(" accountName: " + sessionData.getAccountName());
log.debug(" clientData: " + clientData);
log.debug(" 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.warn("Could not parse transports extension " + e.getMessage());
}
if (log.isDebugEnabled()) {
log.debug("-- Parsed rawRegistrationResponse --");
log.debug(" userPublicKey: " + Hex.encodeHexString(userPublicKey));
log.debug(" keyHandle: " + Hex.encodeHexString(keyHandle));
log.debug(" attestationCertificate: " + attestationCertificate.toString());
log.debug(" transports: " + transports);
try {
log.debug(" attestationCertificate bytes: " + Hex.encodeHexString(attestationCertificate.getEncoded()));
} catch (CertificateEncodingException e) {
throw new U2FException("Cannot encode certificate", e);
}
log.debug(" 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();
boolean found = false;
for (X509Certificate trusted : trustedCertificates) {
try {
attestationCertificate.verify(trusted.getPublicKey());
found = true;
} catch (InvalidKeyException | CertificateException | NoSuchAlgorithmException | NoSuchProviderException | SignatureException e) {
}
}
if (!found) {
if (!this.requireAttestation) {
log.warn("attestion cert is not trusted");
} else {
throw new U2FException("Attestation certificate is not trusted");
}
}
verifyBrowserData(new JsonParser().parse(clientData), "navigator.id.finishEnrollment", sessionData);
if (log.isDebugEnabled()) {
log.debug("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);
if (log.isDebugEnabled()) {
log.debug("<< processRegistrationResponse");
}
return securityKeyData;
}
use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.
the class U2FServerReferenceImpl method processSignResponse.
@Override
public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2FException {
Log.info(">> 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);
Log.info("-- Input --");
Log.info(" sessionId: " + sessionId);
Log.info(" publicKey: " + Hex.encodeHexString(securityKeyData.getPublicKey()));
Log.info(" challenge: " + Hex.encodeHexString(sessionData.getChallenge()));
Log.info(" accountName: " + sessionData.getAccountName());
Log.info(" browserData: " + browserData);
Log.info(" 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();
Log.info("-- Parsed rawSignData --");
Log.info(" userPresence: " + Integer.toHexString(userPresence & 0xFF));
Log.info(" counter: " + counter);
Log.info(" 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);
Log.info("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);
Log.info("<< processSignResponse");
return securityKeyData;
}
use of com.google.u2f.server.data.SecurityKeyData in project OpenUnison by TremoloSecurity.
the class U2FServerReferenceImpl method getSignRequest.
@Override
public U2fSignRequest getSignRequest(String accountName, String appId) throws U2FException {
Log.info(">> getSignRequest " + accountName);
List<SecurityKeyData> securityKeyDataList = dataStore.getSecurityKeyData(accountName);
byte[] challenge = challengeGenerator.generateChallenge(accountName);
String challengeBase64 = Base64.encodeBase64URLSafeString(challenge);
ImmutableList.Builder<RegisteredKey> registeredKeys = ImmutableList.builder();
Log.info(" challenge: " + Hex.encodeHexString(challenge));
for (SecurityKeyData securityKeyData : securityKeyDataList) {
SignSessionData sessionData = new SignSessionData(accountName, appId, challenge, securityKeyData.getPublicKey());
String sessionId = dataStore.storeSessionData(sessionData);
byte[] keyHandle = securityKeyData.getKeyHandle();
List<Transports> transports = securityKeyData.getTransports();
Log.info("-- Output --");
Log.info(" sessionId: " + sessionId);
Log.info(" keyHandle: " + Hex.encodeHexString(keyHandle));
String keyHandleBase64 = Base64.encodeBase64URLSafeString(keyHandle);
Log.info("<< getRegisteredKey " + accountName);
registeredKeys.add(new RegisteredKey(U2FConsts.U2F_V2, keyHandleBase64, transports, appId, sessionId));
}
return new U2fSignRequest(challengeBase64, registeredKeys.build());
}
Aggregations