use of com.google.u2f.key.messages.RegisterResponse 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.key.messages.RegisterResponse in project OpenUnison by TremoloSecurity.
the class RawMessageCodec method decodeRegisterResponse.
public static RegisterResponse decodeRegisterResponse(byte[] data) throws U2FException {
try {
DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(data));
byte reservedByte = inputStream.readByte();
byte[] userPublicKey = new byte[65];
inputStream.readFully(userPublicKey);
byte[] keyHandle = new byte[inputStream.readUnsignedByte()];
inputStream.readFully(keyHandle);
X509Certificate attestationCertificate = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(inputStream);
byte[] signature = new byte[inputStream.available()];
inputStream.readFully(signature);
if (inputStream.available() != 0) {
throw new U2FException("Message ends with unexpected data");
}
if (reservedByte != REGISTRATION_RESERVED_BYTE_VALUE) {
throw new U2FException(String.format("Incorrect value of reserved byte. Expected: %d. Was: %d", REGISTRATION_RESERVED_BYTE_VALUE, reservedByte));
}
return new RegisterResponse(userPublicKey, keyHandle, attestationCertificate, signature);
} catch (IOException e) {
throw new U2FException("Error when parsing raw RegisterResponse", e);
} catch (CertificateException e) {
throw new U2FException("Error when parsing attestation certificate", e);
}
}
use of com.google.u2f.key.messages.RegisterResponse in project OpenUnison by TremoloSecurity.
the class U2FKeyReferenceImpl method register.
@Override
public RegisterResponse register(RegisterRequest registerRequest) throws U2FException {
Log.info(">> register");
byte[] applicationSha256 = registerRequest.getApplicationSha256();
byte[] challengeSha256 = registerRequest.getChallengeSha256();
Log.info(" -- Inputs --");
Log.info(" applicationSha256: " + Hex.encodeHexString(applicationSha256));
Log.info(" challengeSha256: " + Hex.encodeHexString(challengeSha256));
byte userPresent = userPresenceVerifier.verifyUserPresence();
if ((userPresent & UserPresenceVerifier.USER_PRESENT_FLAG) == 0) {
throw new U2FException("Cannot verify user presence");
}
KeyPair keyPair = keyPairGenerator.generateKeyPair(applicationSha256, challengeSha256);
byte[] keyHandle = keyHandleGenerator.generateKeyHandle(applicationSha256, keyPair);
dataStore.storeKeyPair(keyHandle, keyPair);
byte[] userPublicKey = keyPairGenerator.encodePublicKey(keyPair.getPublic());
byte[] signedData = RawMessageCodec.encodeRegistrationSignedBytes(applicationSha256, challengeSha256, keyHandle, userPublicKey);
Log.info("Signing bytes " + Hex.encodeHexString(signedData));
byte[] signature = crypto.sign(signedData, certificatePrivateKey);
Log.info(" -- Outputs --");
Log.info(" userPublicKey: " + Hex.encodeHexString(userPublicKey));
Log.info(" keyHandle: " + Hex.encodeHexString(keyHandle));
Log.info(" vendorCertificate: " + vendorCertificate);
Log.info(" signature: " + Hex.encodeHexString(signature));
Log.info("<< register");
return new RegisterResponse(userPublicKey, keyHandle, vendorCertificate, signature);
}
use of com.google.u2f.key.messages.RegisterResponse 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