Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time-limited sync words (uplift to 1.40.x) #13533

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion android/java/org/chromium/chrome/browser/BraveSyncWorker.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,14 @@ public void run() {
}
};

public String GetCodephrase() {
public String GetPureWords() {
return BraveSyncWorkerJni.get().getSyncCodeWords(mNativeBraveSyncWorker);
}

public String GetTimeLimitedWordsFromPure(String pureWords) {
return BraveSyncWorkerJni.get().getTimeLimitedWordsFromPure(pureWords);
}

public void SaveCodephrase(String codephrase) {
BraveSyncWorkerJni.get().saveCodeWords(mNativeBraveSyncWorker, codephrase);
}
Expand All @@ -159,6 +163,14 @@ public String GetSeedHexFromQrJson(String jsonQr) {
return BraveSyncWorkerJni.get().getSeedHexFromQrJson(jsonQr);
}

public int GetWordsValidationResult(String timeLimitedWords) {
return BraveSyncWorkerJni.get().getWordsValidationResult(timeLimitedWords);
}

public String GetPureWordsFromTimeLimited(String timeLimitedWords) {
return BraveSyncWorkerJni.get().getPureWordsFromTimeLimited(timeLimitedWords);
}

public void RequestSync() {
BraveSyncWorkerJni.get().requestSync(mNativeBraveSyncWorker);
}
Expand Down Expand Up @@ -204,6 +216,10 @@ interface Natives {
String getQrDataJson(String seedHex);
int getQrCodeValidationResult(String jsonQr);
String getSeedHexFromQrJson(String jsonQr);
int getWordsValidationResult(String timeLimitedWords);
String getPureWordsFromTimeLimited(String timeLimitedWords);
String getTimeLimitedWordsFromPure(String pureWords);

void saveCodeWords(long nativeBraveSyncWorker, String passphrase);

void finalizeSyncSetup(long nativeBraveSyncWorker);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,31 @@ private void setSyncText(String title, String message, TextView textView) {
textView.setText(formatedText);
}

private String getWordsValidationString(String words) {
int validationResult = getBraveSyncWorker().GetWordsValidationResult(words);
Log.v(TAG, "validationResult is " + validationResult);
switch (validationResult) {
case 0:
// kValid, empty string indicates there is no error
return "";
case 2:
// kVersionDeprecated
return getResources().getString(R.string.brave_sync_code_from_deprecated_version);
case 3:
// kExpired
return getResources().getString(R.string.brave_sync_code_expired);
case 4:
// kValidForTooLong
return getResources().getString(R.string.brave_sync_code_valid_for_too_long);

default:
// These three different types of errors have the same message
// kWrongWordsNumber
// kNotValidPureWords
return getResources().getString(R.string.brave_sync_wrong_code_error);
}
}

/** OnClickListener for the clear button. We show an alert dialog to confirm the action */
@Override
public void onClick(View v) {
Expand All @@ -568,7 +593,7 @@ public void onClick(View v) {
setJoinExistingChainLayout();
} else if (mStartNewChainButton == v) {
// Creating a new chain
GetCodephrase();
GetPureWords();
setNewChainLayout();
seedWordsReceived(mCodephrase);
} else if (mMobileButton == v) {
Expand Down Expand Up @@ -613,27 +638,18 @@ public void onClick(View v) {
.replace(" ", " ")
.replace("\n", " ")
.split(" ");
if (BIP39_WORD_COUNT != words.length) {
Log.e(TAG, "Confirm code words - wrong words count " + words.length);
onSyncError(getResources().getString(R.string.brave_sync_word_count_error));
return;
}

String hexString = getBraveSyncWorker().GetSeedHexFromWords(
TextUtils.join(" ", words));
if (hexString == null || hexString.isEmpty()) {
String trimmedWords = TextUtils.join(" ", words);
String validationError = getWordsValidationString(trimmedWords);
if (!validationError.isEmpty()) {
Log.e(TAG, "Confirm code words - wrong codephrase");
onSyncError(getResources().getString(R.string.brave_sync_wrong_code_error));
onSyncError(validationError);
return;
}

String codephraseCandidate = TextUtils.join(" ", words);
// Validate the code words with GetSeedHexFromWords
String seedHex = getBraveSyncWorker().GetSeedHexFromWords(codephraseCandidate);
if (null == seedHex || seedHex.isEmpty()) {
onSyncError(getResources().getString(R.string.brave_sync_wrong_code_error));
return;
}
String codephraseCandidate =
getBraveSyncWorker().GetPureWordsFromTimeLimited(trimmedWords);
assert codephraseCandidate != null && !codephraseCandidate.isEmpty();

showFinalSecurityWarning(FinalWarningFor.CODE_WORDS, () -> {
// We have the confirmation from user
Expand Down Expand Up @@ -1218,9 +1234,9 @@ private void setNewChainLayout() {
}

private String mCodephrase;
public String GetCodephrase() {
public String GetPureWords() {
if (mCodephrase == null || mCodephrase.isEmpty()) {
mCodephrase = getBraveSyncWorker().GetCodephrase();
mCodephrase = getBraveSyncWorker().GetPureWords();
}
return mCodephrase;
}
Expand Down Expand Up @@ -1266,7 +1282,7 @@ private void setAddMobileDeviceLayout() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
String seedHex = getBraveSyncWorker().GetSeedHexFromWords(GetCodephrase());
String seedHex = getBraveSyncWorker().GetSeedHexFromWords(GetPureWords());
if (null == seedHex || seedHex.isEmpty()) {
// Give up, seed must be valid
Log.e(TAG, "setAddMobileDeviceLayout seedHex is empty");
Expand Down Expand Up @@ -1345,9 +1361,12 @@ private void setAddLaptopLayout() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
String codePhrase = GetCodephrase();
String codePhrase = GetPureWords();
assert codePhrase != null && !codePhrase.isEmpty();
mBraveSyncAddDeviceCodeWords.setText(codePhrase);
String timeLimitedWords =
getBraveSyncWorker().GetTimeLimitedWordsFromPure(codePhrase);
assert timeLimitedWords != null && !timeLimitedWords.isEmpty();
mBraveSyncAddDeviceCodeWords.setText(timeLimitedWords);
}
});
}
Expand Down
12 changes: 12 additions & 0 deletions app/brave_settings_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,18 @@
<message name="IDS_BRAVE_SYNC_INVALID_SYNC_CODE_TITLE" desc="Error message in dialog for when sync words are invalid (title)">
Invalid sync code, please check and try again.
</message>
<message name="IDS_BRAVE_SYNC_CODE_INVALID" desc="Text for general sync setup error.">
This code is invalid
</message>
<message name="IDS_BRAVE_SYNC_CODE_FROM_DEPRECATED_VERSION" desc="Text for error when trying to use old version sync code after v1 sunset date.">
This code was generated by a deprecated version of Brave, please upgrade your other device first
</message>
<message name="IDS_BRAVE_SYNC_CODE_EXPIRED" desc="Text for error when trying to use the sync code which has expired.">
This code has expired. Please generate a new one on your other device and try again.
</message>
<message name="IDS_BRAVE_SYNC_CODE_VALID_FOR_TOO_LONG" desc="Text for error when trying to use the sync code which is valid till the time too far in the future.">
This code is invalid. Please check that the time and timezone are set correctly on your device.
</message>
<message name="IDS_BRAVE_SYNC_RESET_BUTTON" desc="The Sync button that opens a modal to leave the current sync chain">
Leave Sync Chain
</message>
Expand Down
46 changes: 46 additions & 0 deletions browser/android/brave_sync_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "brave/components/brave_sync/qr_code_data.h"
#include "brave/components/brave_sync/qr_code_validator.h"
#include "brave/components/brave_sync/sync_service_impl_helper.h"
#include "brave/components/brave_sync/time_limited_words.h"
#include "brave/components/sync/driver/brave_sync_service_impl.h"

#include "chrome/browser/profiles/profile.h"
Expand Down Expand Up @@ -351,6 +352,51 @@ int JNI_BraveSyncWorker_GetQrCodeValidationResult(
brave_sync::QrCodeDataValidator::ValidateQrDataJson(str_json_qr));
}

int JNI_BraveSyncWorker_GetWordsValidationResult(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& time_limited_words) {
std::string str_time_limited_words =
base::android::ConvertJavaStringToUTF8(time_limited_words);
DCHECK(!str_time_limited_words.empty());

auto pure_words_with_status =
brave_sync::TimeLimitedWords::Parse(str_time_limited_words);

return static_cast<int>(pure_words_with_status.status);
}

static base::android::ScopedJavaLocalRef<jstring>
JNI_BraveSyncWorker_GetPureWordsFromTimeLimited(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& time_limited_words) {
std::string str_time_limited_words =
base::android::ConvertJavaStringToUTF8(time_limited_words);
DCHECK(!str_time_limited_words.empty());

auto pure_words_with_status =
brave_sync::TimeLimitedWords::Parse(str_time_limited_words);
DCHECK_EQ(pure_words_with_status.status,
brave_sync::WordsValidationStatus::kValid);
DCHECK(pure_words_with_status.pure_words.has_value());

return base::android::ConvertUTF8ToJavaString(
env, pure_words_with_status.pure_words.value());
}

static base::android::ScopedJavaLocalRef<jstring>
JNI_BraveSyncWorker_GetTimeLimitedWordsFromPure(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& pure_words) {
std::string str_pure_words =
base::android::ConvertJavaStringToUTF8(pure_words);
DCHECK(!str_pure_words.empty());

std::string time_limited_words =
brave_sync::TimeLimitedWords::GenerateForNow(str_pure_words);

return base::android::ConvertUTF8ToJavaString(env, time_limited_words);
}

static base::android::ScopedJavaLocalRef<jstring>
JNI_BraveSyncWorker_GetSeedHexFromQrJson(
JNIEnv* env,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export class BraveSyncBrowserProxy {
getSyncCode() {
return sendWithPromise('SyncSetupGetSyncCode');
}
getPureSyncCode() {
return sendWithPromise('SyncSetupGetPureSyncCode');
}
getQRCode(syncCode) {
return sendWithPromise('SyncGetQRCode', syncCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,12 @@ <h2 class="device-title">$i18n{braveSyncChooseDeviceComputerTitle}</h2>
<textarea autofocus class="sync-code-text" value="{{syncCode::input}}"></textarea>
<div class="sync-code-footer">
[[i18n('braveSyncWordCount', syncCodeWordCount_)]]
<template is="dom-if" if="[[isInvalidSyncCode]]">
<div class="invalid-sync-code">
$i18n{braveSyncInvalidSyncCodeTitle}
</div>
</template>
</div>
<template is="dom-if" if="[[syncCodeValidationError]]">
<div class="invalid-sync-code">
[[syncCodeValidationError]]
</div>
</template>
</div>

<div slot="button-container">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ Polymer({
value: 'choose',
notify: true
},
isInvalidSyncCode: {
type: Boolean,
value: false,
syncCodeValidationError: {
type: String,
value: '',
notify: true
},
syncCodeWordCount_: {
Expand All @@ -64,7 +64,6 @@ Polymer({
},

observers: [
'updateSyncCodeValidity_(syncCode)',
'getQRCode_(syncCode, codeType)',
],

Expand All @@ -75,10 +74,6 @@ Polymer({
this.syncBrowserProxy_ = BraveSyncBrowserProxy.getInstance();
},

updateSyncCodeValidity_: function() {
this.isInvalidSyncCode = false
},

computeSyncCodeWordCount_: function() {
if (!this.syncCode) {
return 0
Expand Down
6 changes: 3 additions & 3 deletions browser/resources/settings/brave_sync_page/brave_sync_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ Polymer({
*/
handleSyncPrefsChanged_: async function(syncPrefs) {
if (this.syncStatus_ && !this.syncStatus_.firstSetupInProgress) {
const syncCode = await this.braveBrowserProxy_.getSyncCode()
const pureSyncCode = await this.braveBrowserProxy_.getPureSyncCode()
if (syncPrefs.passphraseRequired) {
await this.browserProxy_.setDecryptionPassphrase(syncCode);
await this.browserProxy_.setDecryptionPassphrase(pureSyncCode);
} else if (!this.isEncryptionSet_) {
this.browserProxy_.setEncryptionPassphrase(syncCode)
this.browserProxy_.setEncryptionPassphrase(pureSyncCode)
.then(successfullySet => {
this.isEncryptionSet_ = successfullySet
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ <h1>$i18n{braveSyncSetupTitle}</h1>
<settings-brave-sync-code-dialog
code-type="{{syncCodeDialogType_}}"
sync-code="{{syncCode}}"
is-invalid-sync-code="{{isInvalidSyncCode_}}"
sync-code-validation-error="{{syncCodeValidationError_}}"
on-done="handleSyncCodeDialogDone_"
></settings-brave-sync-code-dialog>
</template>
14 changes: 6 additions & 8 deletions browser/resources/settings/brave_sync_page/brave_sync_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ Polymer({
type: Boolean,
value: false,
},
isInvalidSyncCode_: {
type: Boolean,
value: false,
}
syncCodeValidationError_: {
type: String,
value: '',
}
},

/** @private {?BraveSyncBrowserProxy} */
Expand Down Expand Up @@ -88,13 +88,11 @@ Polymer({
try {
success = await this.syncBrowserProxy_.setSyncCode(syncCodeToSubmit)
} catch (e) {
console.error("Error setting sync code")
this.syncCodeValidationError_ = e
success = false
}
this.isSubmittingSyncCode_ = false
if (!success) {
this.isInvalidSyncCode_ = true
} else {
if (success) {
this.syncCodeDialogType_ = undefined
this.fire('setup-success')
}
Expand Down
3 changes: 0 additions & 3 deletions browser/ui/android/strings/android_brave_strings.grd
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,6 @@ until they verify, or until 90 days have passed.
<message name="IDS_BRAVE_SYNC_WORD_COUNT_TEXT" desc="Text for Brave Sync word count message.">
Word count: <ph name="WORD_COUNT">%1$d</ph>
</message>
<message name="IDS_BRAVE_SYNC_WORD_COUNT_ERROR" desc="Text for Brave Sync word count error.">
Incorrect number of words
</message>
<message name="IDS_BRAVE_SYNC_WRONG_CODE_ERROR" desc="Text for wrong Brave Sync code error.">
Wrong sync code
</message>
Expand Down
Loading