use of co.krypt.krypton.me.MeStorage in project krypton-android by kryptco.
the class SettingsFragment method onCreateView.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_settings, container, false);
Button doneButton = (Button) root.findViewById(R.id.doneButton);
final Fragment self = this;
doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MainActivity activity = (MainActivity) getActivity();
activity.postCurrentActivePageView();
getActivity().getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.enter_from_bottom, R.anim.exit_to_bottom).hide(self).commit();
}
});
TextView versionText = (TextView) root.findViewById(R.id.versionText);
try {
PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);
versionText.setText(packageInfo.versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
ImageButton deleteButton = (ImageButton) root.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LocalAuthentication.requestAuthentication(getActivity(), "Destroy key pair permanently?", "You will have to generate a new key pair and re-add it to services like GitHub.", () -> new Thread(() -> {
try {
new Analytics(getContext()).postEvent("keypair", "destroy", null, null, false);
EventBus.getDefault().post(new TeamService.RequestTeamOperation(Sigchain.RequestableTeamOperation.leave(), C.background(getContext())));
Silo.shared(getContext()).unpairAll();
KeyManager.deleteAllMeKeyPairs(getContext());
new MeStorage(getContext()).delete();
new JoinTeamProgress(getContext()).resetAndDeleteTeam(getContext());
new CreateTeamProgress(getContext()).reset();
startActivity(new Intent(getContext(), OnboardingActivity.class));
} catch (Exception e) {
e.printStackTrace();
}
}).start());
}
});
Button contactButton = (Button) root.findViewById(R.id.contactUsButton);
contactButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.parse("mailto:hello@krypt.co?subject=Krypton%20Feedback&body=");
intent.setData(data);
startActivity(intent);
}
});
Button softwareButton = (Button) root.findViewById(R.id.softwareButton);
softwareButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://krypt.co/app/open-source-libraries/"));
startActivity(browserIntent);
}
});
Button privacyButton = (Button) root.findViewById(R.id.privacyButton);
privacyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://krypt.co/app/privacy/"));
startActivity(browserIntent);
}
});
SwitchCompat disableAnalyticsSwitch = (SwitchCompat) root.findViewById(R.id.disableAnalyticsSwitch);
disableAnalyticsSwitch.setChecked(new Analytics(getContext()).isDisabled());
disableAnalyticsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
new Analytics(getContext()).setAnalyticsDisabled(isChecked);
}
});
SwitchCompat enableApprovedNotifications = (SwitchCompat) root.findViewById(R.id.enableAutoApproveNotificationsSwitch);
enableApprovedNotifications.setChecked(new Settings(getContext()).approvedNotificationsEnabled());
enableApprovedNotifications.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
new Settings(getContext()).setApprovedNotificationsEnabled(isChecked);
}
});
SwitchCompat silenceNotifications = (SwitchCompat) root.findViewById(R.id.silenceNotificationsSwitch);
silenceNotifications.setChecked(new Settings(getContext()).silenceNotifications());
silenceNotifications.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
new Settings(getContext()).setSilenceNotifications(isChecked);
}
});
ImageButton exportLogsButton = (ImageButton) root.findViewById(R.id.exportLogsButton);
exportLogsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String token = AuditLogContentProvider.setToken(v.getContext());
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Krypton Audit Log");
sendIntent.setType("application/x-sqlite3");
Uri auditLogUriWithToken = AuditLogContentProvider.getAuditLogURIWithToken();
if (auditLogUriWithToken == null) {
return;
}
sendIntent.putExtra(Intent.EXTRA_STREAM, auditLogUriWithToken);
startActivity(sendIntent);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(v.getContext(), "Error exporting audit log: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
Button editKnownHostsButton = (Button) root.findViewById(R.id.editKnownHostsButton);
editKnownHostsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getView().setTranslationZ(0);
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
KnownHostsFragment knownHostsFragment = new KnownHostsFragment();
transaction.setCustomAnimations(R.anim.enter_from_bottom, R.anim.delayed).replace(R.id.fragmentOverlay, knownHostsFragment).commit();
new Analytics(getActivity().getApplicationContext()).postPageView("KnownHostsEdit");
}
});
return root;
}
use of co.krypt.krypton.me.MeStorage in project krypton-android by kryptco.
the class Silo method respondToRequest.
public void respondToRequest(Pairing pairing, Request request, boolean requestAllowed) throws Unrecoverable {
// Fine-grained locking allows performing signatures in parallel
synchronized ((Silo.class.getName() + request.requestID).intern()) {
synchronized (Silo.class) {
if (sendCachedResponseIfPresent(pairing, request)) {
return;
}
}
Response response = Response.with(request);
Analytics analytics = new Analytics(context);
if (analytics.isDisabled()) {
response.trackingID = "disabled";
} else {
response.trackingID = analytics.getClientID();
}
request.body.visit(new RequestBody.Visitor<Void, Unrecoverable>() {
@Override
public Void visit(MeRequest meRequest) throws CryptoException {
response.meResponse = new MeResponse(meStorage.loadWithUserID(meRequest.userID()));
return null;
}
@Override
public Void visit(SignRequest signRequest) throws Unrecoverable {
signRequest.validate();
response.signResponse = new SignResponse();
if (requestAllowed) {
try {
SSHKeyPairI key = MeStorage.getOrLoadKeyPair(context);
if (MessageDigest.isEqual(signRequest.publicKeyFingerprint, key.publicKeyFingerprint())) {
if (signRequest.verifyHostName()) {
String hostName = signRequest.hostAuth.hostNames[0];
String hostKey = Base64.encodeAsString(signRequest.hostAuth.hostKey);
synchronized (databaseLock) {
List<KnownHost> matchingKnownHosts = dbHelper.getKnownHostDao().queryForEq("host_name", hostName);
try {
Sigchain.NativeResult<List<Sigchain.PinnedHost>> teamPinnedHosts = TeamDataProvider.getPinnedKeysByHost(context, hostName);
if (teamPinnedHosts.success != null) {
for (Sigchain.PinnedHost pinnedHost : teamPinnedHosts.success) {
matchingKnownHosts.add(new KnownHost(pinnedHost.host, co.krypt.krypton.crypto.Base64.encode(pinnedHost.publicKey), 0));
}
}
} catch (Native.NotLinked e) {
e.printStackTrace();
}
if (matchingKnownHosts.size() == 0) {
dbHelper.getKnownHostDao().create(new KnownHost(hostName, hostKey, System.currentTimeMillis() / 1000));
broadcastKnownHostsChanged();
} else {
boolean foundKnownHost = false;
List<String> pinnedPublicKeys = new ArrayList<>();
for (KnownHost pinnedHost : matchingKnownHosts) {
pinnedPublicKeys.add(pinnedHost.publicKey);
if (pinnedHost.publicKey.equals(hostKey)) {
foundKnownHost = true;
break;
}
}
if (!foundKnownHost) {
throw new MismatchedHostKeyException(pinnedPublicKeys, "Expected " + pinnedPublicKeys.toString() + " received " + hostKey);
}
}
}
}
String algo = signRequest.algo();
if ((key instanceof RSASSHKeyPair) && request.semVer().lessThan(Versions.KR_SUPPORTS_RSA_SHA256_512)) {
algo = "ssh-rsa";
}
response.signResponse.signature = key.signDigestAppendingPubkey(signRequest.data, algo);
SSHSignatureLog log = new SSHSignatureLog(signRequest.data, true, signRequest.command, signRequest.user(), signRequest.firstHostnameIfExists(), System.currentTimeMillis() / 1000, signRequest.verifyHostName(), JSON.toJson(signRequest.hostAuth), pairing.getUUIDString(), pairing.workstationName);
co.krypt.krypton.team.log.Log teamLog = co.krypt.krypton.team.log.Log.fromSSHRequest(pairing, request, signRequest, co.krypt.krypton.team.log.Log.Body.SSH.Result.signature(response.signResponse.signature));
EventBus.getDefault().post(new TeamService.EncryptLog(C.background(context), teamLog));
pairingStorage.appendToSSHLog(log);
Notifications.notifySuccess(context, pairing, request, log);
if (signRequest.verifiedHostNameOrDefault("unknown host").equals("me.krypt.co")) {
Intent sshMeIntent = new Intent(TestSSHFragment.SSH_ME_ACTION);
LocalBroadcastManager.getInstance(context).sendBroadcast(sshMeIntent);
}
if (signRequest.hostAuth == null) {
new Analytics(context).postEvent("host", "unknown", null, null, false);
} else if (!signRequest.verifyHostName()) {
new Analytics(context).postEvent("host", "unverified", null, null, false);
}
} else {
Log.e(TAG, Base64.encodeAsString(signRequest.publicKeyFingerprint) + " != " + Base64.encodeAsString(key.publicKeyFingerprint()));
response.signResponse.error = "unknown key fingerprint";
}
} catch (SQLException e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
response.signResponse.error = "SQL error: " + e.getMessage() + "\n" + sw.toString();
e.printStackTrace();
} catch (MismatchedHostKeyException e) {
response.signResponse.error = "host public key mismatched";
if (signRequest.hostAuth.hostKey != null) {
co.krypt.krypton.team.log.Log teamLog = co.krypt.krypton.team.log.Log.fromSSHRequest(pairing, request, signRequest, co.krypt.krypton.team.log.Log.Body.SSH.Result.hostMismatch(e.pinnedPublicKeys.toArray(new String[] {})));
EventBus.getDefault().post(new TeamService.EncryptLog(C.background(context), teamLog));
}
Notifications.notifyReject(context, pairing, request, "Host public key mismatched.");
e.printStackTrace();
}
} else {
response.signResponse.error = "rejected";
co.krypt.krypton.team.log.Log teamLog = co.krypt.krypton.team.log.Log.fromSSHRequest(pairing, request, signRequest, co.krypt.krypton.team.log.Log.Body.SSH.Result.userRejected());
EventBus.getDefault().post(new TeamService.EncryptLog(C.background(context), teamLog));
pairingStorage.appendToSSHLog(new SSHSignatureLog(signRequest.data, false, signRequest.command, signRequest.user(), signRequest.firstHostnameIfExists(), System.currentTimeMillis() / 1000, signRequest.verifyHostName(), JSON.toJson(signRequest.hostAuth), pairing.getUUIDString(), pairing.workstationName));
}
return null;
}
@Override
public Void visit(GitSignRequest gitSignRequest) throws Unrecoverable {
if (requestAllowed) {
try {
SSHKeyPairI key = MeStorage.getOrLoadKeyPair(context);
new MeStorage(context).loadWithUserID(UserID.parse(gitSignRequest.userID));
co.krypt.krypton.team.log.Log.Body.GitSignatureResult gitSignatureResult = new co.krypt.krypton.team.log.Log.Body.GitSignatureResult();
co.krypt.krypton.log.Log log = gitSignRequest.body.visit(new GitSignRequestBody.Visitor<co.krypt.krypton.log.Log, Exception>() {
@Override
public co.krypt.krypton.log.Log visit(CommitInfo commit) throws Unrecoverable {
byte[] signature = SignableUtils.signBinaryDocument(commit, key, HashAlgorithm.SHA512);
response.gitSignResponse = new GitSignResponse(signature, null);
gitSignatureResult.signature = signature;
GitCommitSignatureLog commitLog = new GitCommitSignatureLog(pairing, commit, new AsciiArmor(AsciiArmor.HeaderLine.SIGNATURE, AsciiArmor.backwardsCompatibleHeaders(request.semVer()), signature).toString());
pairings().appendToCommitLogs(commitLog);
return commitLog;
}
@Override
public co.krypt.krypton.log.Log visit(TagInfo tag) throws Unrecoverable {
byte[] signature = SignableUtils.signBinaryDocument(tag, key, HashAlgorithm.SHA512);
response.gitSignResponse = new GitSignResponse(signature, null);
gitSignatureResult.signature = signature;
GitTagSignatureLog tagLog = new GitTagSignatureLog(pairing, tag, new AsciiArmor(AsciiArmor.HeaderLine.SIGNATURE, AsciiArmor.backwardsCompatibleHeaders(request.semVer()), signature).toString());
pairings().appendToTagLogs(tagLog);
return tagLog;
}
});
co.krypt.krypton.team.log.Log teamLog = co.krypt.krypton.team.log.Log.fromGitRequest(pairing, request, gitSignRequest, gitSignatureResult);
EventBus.getDefault().post(new TeamService.EncryptLog(C.background(context), teamLog));
Notifications.notifySuccess(context, pairing, request, log);
} catch (Exception e) {
e.printStackTrace();
response.gitSignResponse = new GitSignResponse(null, "unknown error");
}
} else {
response.gitSignResponse = new GitSignResponse(null, "rejected");
gitSignRequest.body.visit(new GitSignRequestBody.Visitor<Void, RuntimeException>() {
@Override
public Void visit(CommitInfo commit) throws RuntimeException {
pairings().appendToCommitLogs(new GitCommitSignatureLog(pairing, commit, null));
return null;
}
@Override
public Void visit(TagInfo tag) throws RuntimeException {
pairings().appendToTagLogs(new GitTagSignatureLog(pairing, tag, null));
return null;
}
});
co.krypt.krypton.team.log.Log teamLog = co.krypt.krypton.team.log.Log.fromGitRequest(pairing, request, gitSignRequest, co.krypt.krypton.team.log.Log.Body.GitSignatureResult.userRejected());
EventBus.getDefault().post(new TeamService.EncryptLog(C.background(context), teamLog));
}
return null;
}
@Override
public Void visit(UnpairRequest unpairRequest) throws Unrecoverable {
// Processed in handle()
return null;
}
@Override
public Void visit(HostsRequest hostsRequest) throws Unrecoverable {
HostsResponse hostsResponse = new HostsResponse();
synchronized (databaseLock) {
try {
List<SSHSignatureLog> sshLogs = dbHelper.getSSHSignatureLogDao().queryBuilder().groupByRaw("user, host_name").query();
List<UserAndHost> userAndHosts = new LinkedList<>();
for (SSHSignatureLog log : sshLogs) {
UserAndHost userAndHost = new UserAndHost();
userAndHost.user = log.user;
userAndHost.host = log.hostName;
userAndHosts.add(userAndHost);
}
HostInfo hostInfo = new HostInfo();
UserAndHost[] userAndHostsArray = new UserAndHost[userAndHosts.size()];
userAndHosts.toArray(userAndHostsArray);
hostInfo.hosts = userAndHostsArray;
List<UserID> userIDs = meStorage.getUserIDs();
List<String> userIDStrings = new LinkedList<>();
for (UserID userID : userIDs) {
userIDStrings.add(userID.toString());
}
String[] userIDArray = new String[userIDs.size()];
userIDStrings.toArray(userIDArray);
hostInfo.pgpUserIDs = userIDArray;
hostsResponse.hostInfo = hostInfo;
} catch (SQLException e1) {
hostsResponse.error = "sql exception";
}
}
response.hostsResponse = hostsResponse;
return null;
}
@Override
public Void visit(ReadTeamRequest readTeamRequest) throws Unrecoverable {
SuccessOrTaggedErrorResult<JsonObject> result = new SuccessOrTaggedErrorResult<>();
response.readTeamResponse = result;
if (requestAllowed) {
try {
Sigchain.NativeResult<JsonObject> readToken = TeamDataProvider.signReadToken(context, readTeamRequest.publicKey);
if (readToken.success != null) {
result.success = readToken.success;
} else {
result.error = readToken.error;
}
} catch (Native.NotLinked e) {
e.printStackTrace();
result.error = e.getMessage();
}
} else {
response.readTeamResponse.error = "rejected";
}
return null;
}
@Override
public Void visit(LogDecryptionRequest logDecryptionRequest) throws Unrecoverable {
SuccessOrTaggedErrorResult<JsonObject> result = new SuccessOrTaggedErrorResult<>();
response.logDecryptionResponse = result;
if (requestAllowed) {
try {
Sigchain.NativeResult<JsonObject> unwrappedKey = TeamDataProvider.unwrapKey(context, logDecryptionRequest.wrappedKey);
if (unwrappedKey.success != null) {
result.success = unwrappedKey.success;
} else {
result.error = unwrappedKey.error;
}
} catch (Native.NotLinked e) {
e.printStackTrace();
result.error = e.getMessage();
}
} else {
response.logDecryptionResponse.error = "rejected";
}
return null;
}
@Override
public Void visit(TeamOperationRequest teamOperationRequest) throws Unrecoverable {
SuccessOrTaggedErrorResult<Sigchain.TeamOperationResponse> result = new SuccessOrTaggedErrorResult<>();
response.teamOperationResponse = result;
if (requestAllowed) {
try {
Sigchain.NativeResult<Sigchain.TeamOperationResponse> nativeResult = TeamDataProvider.requestTeamOperation(context, teamOperationRequest.operation);
if (nativeResult.success != null) {
response.teamOperationResponse.success = nativeResult.success;
} else {
response.teamOperationResponse.error = nativeResult.error;
}
} catch (Native.NotLinked e) {
e.printStackTrace();
result.error = e.getMessage();
}
} else {
response.teamOperationResponse.error = "rejected";
}
return null;
}
});
response.snsEndpointARN = SNSTransport.getInstance(context).getEndpointARN();
synchronized (Silo.class) {
try {
if (responseDiskCacheByRequestID != null && !responseDiskCacheByRequestID.isClosed()) {
DiskLruCache.Editor cacheEditor = responseDiskCacheByRequestID.edit(request.requestIDCacheKey(pairing));
cacheEditor.set(0, JSON.toJson(response));
cacheEditor.commit();
responseDiskCacheByRequestID.flush();
}
} catch (IOException e) {
e.printStackTrace();
throw new Unrecoverable(e);
}
responseMemCacheByRequestID.put(request.requestIDCacheKey(pairing), response);
}
send(pairing, response);
}
}
use of co.krypt.krypton.me.MeStorage in project krypton-android by kryptco.
the class EnterEmailFragment method next.
private void next() {
Analytics analytics = new Analytics(getContext());
String email = profileEmail.getText().toString();
if (email == null || email.trim().equals("")) {
analytics.postEvent("email", "skipped", null, null, false);
email = Build.MODEL;
} else {
analytics.postEvent("email", "typed", null, null, false);
email = email.trim();
}
analytics.publishEmailToTeamsIfNeeded(email);
try {
new MeStorage(getContext()).setEmail(email);
} catch (CryptoException e) {
e.printStackTrace();
Error.shortToast(getContext(), "Failed to set email: " + e.getMessage());
return;
}
final OnboardingProgress progress = new OnboardingProgress(getContext());
progress.setStage(OnboardingStage.FIRST_PAIR);
FirstPairFragment firstPairFragment = new FirstPairFragment();
FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left).add(R.id.activity_onboarding, firstPairFragment).hide(this).show(firstPairFragment).commit();
}
use of co.krypt.krypton.me.MeStorage in project krypton-android by kryptco.
the class MemberEnterEmail method onCreateView.
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.fragment_teams_invite_inperson_member_enter_email, container, false);
email = v.findViewById(R.id.memberEmailInPerson);
email.setText("loading...");
email.setTextColor(getResources().getColor(R.color.appGray, null));
email.setEnabled(false);
Email.colorValidEmail(email);
nextButton = v.findViewById(R.id.inpersonEmailNext);
nextButton.setOnClickListener(b -> {
EventBus.getDefault().unregister(this);
nextButton.setEnabled(false);
new Thread(() -> {
try {
new MeStorage(getContext()).setEmail(email.getText().toString().trim());
} catch (CryptoException e) {
co.krypt.krypton.uiutils.Error.shortToast(getContext(), "Failed to set email: " + e.getMessage());
e.printStackTrace();
return;
}
getActivity().runOnUiThread(() -> Transitions.beginSlide(this).replace(R.id.fragmentOverlay, new MemberQR()).addToBackStack(null).commitAllowingStateLoss());
}).start();
});
nextButton.setEnabled(false);
EventBus.getDefault().register(this);
EventBus.getDefault().post(new GetProfile(getContext()));
return v;
}
use of co.krypt.krypton.me.MeStorage in project krypton-android by kryptco.
the class MemberQR method onCreateView.
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
final View v = inflater.inflate(R.layout.fragment_teams_invite_inperson_member_qr, container, false);
qrPayloads.set(null);
qr = v.findViewById(R.id.memberQRCode);
AppCompatButton cancelButton = v.findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(v_ -> {
Transitions.beginFade(this).remove(this).commitAllowingStateLoss();
});
loadQRProgress = v.findViewById(R.id.loadQRProgressBar);
joinProgress = v.findViewById(R.id.memberJoinProgress);
joinProgress.setAlpha(0);
Sigchain.AdminQRPayload adminQRPayload = MemberScan.lastScannedPayload.get();
if (adminQRPayload == null) {
getFragmentManager().popBackStackImmediate();
} else {
new Thread(() -> {
Profile p = new MeStorage(getContext()).load();
if (p == null) {
Error.shortToast(getContext(), "Error loading profile, first generate your Krypton SSH key");
} else {
EventBus.getDefault().register(this);
EventBus.getDefault().post(new TeamService.GenerateClient(C.background(getContext()), new Sigchain.GenerateClientInput(p, adminQRPayload.teamPublicKey, adminQRPayload.lastBlockHash)));
}
}).start();
}
return v;
}
Aggregations