{_t("Secure your encrypted message history with a Recovery Passphrase.")}
{_t("You'll need it if you log out or lose access to this device.")}
+
+ {strengthMeter}
+ {helpText}
+
opt out.": "If you don't want encrypted message history to be availble on other devices, .",
- "Or, if you don't want to create a Recovery Passphrase, skip this step and .": "Or, if you don't want to create a Recovery Passphrase, skip this step and .",
- "That matches!": "That matches!",
- "That doesn't match.": "That doesn't match.",
- "Go back to set it again.": "Go back to set it again.",
- "Type in your Recovery Passphrase to confirm you remember it. If it helps, add it to your password manager or store it somewhere safe.": "Type in your Recovery Passphrase to confirm you remember it. If it helps, add it to your password manager or store it somewhere safe.",
- "Repeat your passphrase...": "Repeat your passphrase...",
- "Make a copy of this Recovery Key and keep it safe.": "Make a copy of this Recovery Key and keep it safe.",
- "As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.": "As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.",
- "Your Recovery Key": "Your Recovery Key",
- "Copy to clipboard": "Copy to clipboard",
- "Download": "Download",
- "I've made a copy": "I've made a copy",
- "Your Recovery Key has been copied to your clipboard, paste it to:": "Your Recovery Key has been copied to your clipboard, paste it to:",
- "Your Recovery Key is in your Downloads folder.": "Your Recovery Key is in your Downloads folder.",
- "Print it and store it somewhere safe": "Print it and store it somewhere safe",
- "Save it on a USB key or backup drive": "Save it on a USB key or backup drive",
- "Copy it to your personal cloud storage": "Copy it to your personal cloud storage",
- "Got it": "Got it",
- "Backup created": "Backup created",
- "Your encryption keys are now being backed up to your Homeserver.": "Your encryption keys are now being backed up to your Homeserver.",
- "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.": "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.",
- "Set up Secure Message Recovery": "Set up Secure Message Recovery",
- "Create a Recovery Passphrase": "Create a Recovery Passphrase",
- "Confirm Recovery Passphrase": "Confirm Recovery Passphrase",
- "Recovery Key": "Recovery Key",
- "Keep it safe": "Keep it safe",
- "Backing up...": "Backing up...",
- "Create Key Backup": "Create Key Backup",
- "Unable to create key backup": "Unable to create key backup",
- "Retry": "Retry",
"Unable to load backup status": "Unable to load backup status",
"Unable to restore backup": "Unable to restore backup",
"No backup found!": "No backup found!",
@@ -1016,6 +1006,7 @@
"Restored %(sessionCount)s session keys": "Restored %(sessionCount)s session keys",
"Enter Recovery Passphrase": "Enter Recovery Passphrase",
"Access your secure message history and set up secure messaging by entering your recovery passphrase.": "Access your secure message history and set up secure messaging by entering your recovery passphrase.",
+ "Next": "Next",
"If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options": "If you've forgotten your recovery passphrase you can use your recovery key or set up new recovery options",
"Enter Recovery Key": "Enter Recovery Key",
"This looks like a valid recovery key!": "This looks like a valid recovery key!",
@@ -1346,6 +1337,41 @@
"The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.",
"File to import": "File to import",
"Import": "Import",
+ "Great! This passphrase looks strong enough.": "Great! This passphrase looks strong enough.",
+ "Secure your encrypted message history with a Recovery Passphrase.": "Secure your encrypted message history with a Recovery Passphrase.",
+ "You'll need it if you log out or lose access to this device.": "You'll need it if you log out or lose access to this device.",
+ "Enter a passphrase...": "Enter a passphrase...",
+ "If you don't want encrypted message history to be availble on other devices, .": "If you don't want encrypted message history to be availble on other devices, .",
+ "Or, if you don't want to create a Recovery Passphrase, skip this step and .": "Or, if you don't want to create a Recovery Passphrase, skip this step and .",
+ "That matches!": "That matches!",
+ "That doesn't match.": "That doesn't match.",
+ "Go back to set it again.": "Go back to set it again.",
+ "Type in your Recovery Passphrase to confirm you remember it. If it helps, add it to your password manager or store it somewhere safe.": "Type in your Recovery Passphrase to confirm you remember it. If it helps, add it to your password manager or store it somewhere safe.",
+ "Repeat your passphrase...": "Repeat your passphrase...",
+ "Make a copy of this Recovery Key and keep it safe.": "Make a copy of this Recovery Key and keep it safe.",
+ "As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.": "As a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase.",
+ "Your Recovery Key": "Your Recovery Key",
+ "Copy to clipboard": "Copy to clipboard",
+ "Download": "Download",
+ "I've made a copy": "I've made a copy",
+ "Your Recovery Key has been copied to your clipboard, paste it to:": "Your Recovery Key has been copied to your clipboard, paste it to:",
+ "Your Recovery Key is in your Downloads folder.": "Your Recovery Key is in your Downloads folder.",
+ "Print it and store it somewhere safe": "Print it and store it somewhere safe",
+ "Save it on a USB key or backup drive": "Save it on a USB key or backup drive",
+ "Copy it to your personal cloud storage": "Copy it to your personal cloud storage",
+ "Got it": "Got it",
+ "Backup created": "Backup created",
+ "Your encryption keys are now being backed up to your Homeserver.": "Your encryption keys are now being backed up to your Homeserver.",
+ "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.": "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another device.",
+ "Set up Secure Message Recovery": "Set up Secure Message Recovery",
+ "Create a Recovery Passphrase": "Create a Recovery Passphrase",
+ "Confirm Recovery Passphrase": "Confirm Recovery Passphrase",
+ "Recovery Key": "Recovery Key",
+ "Keep it safe": "Keep it safe",
+ "Backing up...": "Backing up...",
+ "Create Key Backup": "Create Key Backup",
+ "Unable to create key backup": "Unable to create key backup",
+ "Retry": "Retry",
"Failed to set direct chat tag": "Failed to set direct chat tag",
"Failed to remove tag %(tagName)s from room": "Failed to remove tag %(tagName)s from room",
"Failed to add tag %(tagName)s to room": "Failed to add tag %(tagName)s to room"
diff --git a/src/utils/PasswordScorer.js b/src/utils/PasswordScorer.js
new file mode 100644
index 0000000000..e4bbec1637
--- /dev/null
+++ b/src/utils/PasswordScorer.js
@@ -0,0 +1,84 @@
+/*
+Copyright 2018 New Vector Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import Zxcvbn from 'zxcvbn';
+
+import MatrixClientPeg from '../MatrixClientPeg';
+import { _t, _td } from '../languageHandler';
+
+const ZXCVBN_USER_INPUTS = [
+ 'riot',
+ 'matrix',
+];
+
+// Translations for zxcvbn's suggestion strings
+_td("Use a few words, avoid common phrases");
+_td("No need for symbols, digits, or uppercase letters");
+_td("Use a longer keyboard pattern with more turns");
+_td("Avoid repeated words and characters");
+_td("Avoid sequences");
+_td("Avoid recent years");
+_td("Avoid years that are associated with you");
+_td("Avoid dates and years that are associated with you");
+_td("Capitalization doesn't help very much");
+_td("All-uppercase is almost as easy to guess as all-lowercase");
+_td("Reversed words aren't much harder to guess");
+_td("Predictable substitutions like '@' instead of 'a' don't help very much");
+_td("Add another word or two. Uncommon words are better.");
+
+// and warnings
+_td("Repeats like \"aaa\" are easy to guess");
+_td("Repeats like \"abcabcabc\" are only slightly harder to guess than \"abc\"");
+_td("Sequences like abc or 6543 are easy to guess");
+_td("Recent years are easy to guess");
+_td("Dates are often easy to guess");
+_td("This is a top-10 common password");
+_td("This is a top-100 common password");
+_td("This is a very common password");
+_td("This is similar to a commonly used password");
+_td("A word by itself is easy to guess");
+_td("Names and surnames by themselves are easy to guess");
+_td("Common names and surnames are easy to guess");
+
+/**
+ * Wrapper around zxcvbn password strength estimation
+ * Include this only from async components: it pulls in zxcvbn
+ * (obviously) which is large.
+ */
+export function scorePassword(password) {
+ if (password.length === 0) return null;
+
+ const userInputs = ZXCVBN_USER_INPUTS.slice();
+ userInputs.push(MatrixClientPeg.get().getUserIdLocalpart());
+
+ let zxcvbnResult = Zxcvbn(password, userInputs);
+ // Work around https://github.com/dropbox/zxcvbn/issues/216
+ if (password.includes(' ')) {
+ const resultNoSpaces = Zxcvbn(password.replace(/ /g, ''), userInputs);
+ if (resultNoSpaces.score < zxcvbnResult.score) zxcvbnResult = resultNoSpaces;
+ }
+
+ for (let i = 0; i < zxcvbnResult.feedback.suggestions.length; ++i) {
+ // translate suggestions
+ zxcvbnResult.feedback.suggestions[i] = _t(zxcvbnResult.feedback.suggestions[i]);
+ }
+ // and warning, if any
+ if (zxcvbnResult.feedback.warning) {
+ zxcvbnResult.feedback.warning = _t(zxcvbnResult.feedback.warning);
+ }
+
+ return zxcvbnResult;
+}