Improvements all over.
[IMPROVED] Use SHA-1 instead of MD-4 for hashing the user givens. [UPDATED] Remember master password on by default. [IMPROVED] More and improved FAQ. [ADDED] Auto-generate build/version values in Info.plist and Settings Root.plist.
This commit is contained in:
parent
7b14556dbe
commit
b10c00786e
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit e8ae6057f8753ed48cb964a106e4b7289ba4156c
|
Subproject commit 905b44a5aa28319230d36842f9431d76411c146d
|
@ -6,20 +6,6 @@
|
|||||||
objectVersion = 46;
|
objectVersion = 46;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXAggregateTarget section */
|
|
||||||
DA6556DC14D55C1500841C99 /* InfoPlist */ = {
|
|
||||||
isa = PBXAggregateTarget;
|
|
||||||
buildConfigurationList = DA6556DD14D55C1600841C99 /* Build configuration list for PBXAggregateTarget "InfoPlist" */;
|
|
||||||
buildPhases = (
|
|
||||||
DA6556E014D55C2700841C99 /* ShellScript */,
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = InfoPlist;
|
|
||||||
productName = InfoPlist;
|
|
||||||
};
|
|
||||||
/* End PBXAggregateTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
DA007F5214B24DCD00251337 /* OPConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA007F5114B24DCD00251337 /* OPConfig.m */; };
|
DA007F5214B24DCD00251337 /* OPConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = DA007F5114B24DCD00251337 /* OPConfig.m */; };
|
||||||
DA007F5514B25EE100251337 /* ciphers.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA007F5414B25EE100251337 /* ciphers.plist */; };
|
DA007F5514B25EE100251337 /* ciphers.plist in Resources */ = {isa = PBXBuildFile; fileRef = DA007F5414B25EE100251337 /* ciphers.plist */; };
|
||||||
@ -670,13 +656,6 @@
|
|||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
DA6556E114D55C4400841C99 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = DA6556DC14D55C1500841C99;
|
|
||||||
remoteInfo = InfoPlist;
|
|
||||||
};
|
|
||||||
DAC63281148681190075AEA5 /* PBXContainerItemProxy */ = {
|
DAC63281148681190075AEA5 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
containerPortal = DA5BFA3B147E415C00F98B1E /* Project object */;
|
||||||
@ -1809,12 +1788,12 @@
|
|||||||
DAE2C646148247E500BA6B10 /* OPTypeViewController.m */,
|
DAE2C646148247E500BA6B10 /* OPTypeViewController.m */,
|
||||||
DA55B29C14B38272001131B7 /* OPContentViewController.h */,
|
DA55B29C14B38272001131B7 /* OPContentViewController.h */,
|
||||||
DA55B29D14B38272001131B7 /* OPContentViewController.m */,
|
DA55B29D14B38272001131B7 /* OPContentViewController.m */,
|
||||||
DA5BFA51147E415C00F98B1E /* Supporting Files */,
|
|
||||||
DA34DA1414B1BEA100F721C1 /* OPTypes.h */,
|
DA34DA1414B1BEA100F721C1 /* OPTypes.h */,
|
||||||
DA34DA1514B1BEA100F721C1 /* OPTypes.m */,
|
DA34DA1514B1BEA100F721C1 /* OPTypes.m */,
|
||||||
DA007F5014B24DCC00251337 /* OPConfig.h */,
|
DA007F5014B24DCC00251337 /* OPConfig.h */,
|
||||||
DA007F5114B24DCD00251337 /* OPConfig.m */,
|
DA007F5114B24DCD00251337 /* OPConfig.m */,
|
||||||
DADC3C4C14C62B350091CB4D /* Settings.bundle */,
|
DADC3C4C14C62B350091CB4D /* Settings.bundle */,
|
||||||
|
DA5BFA51147E415C00F98B1E /* Supporting Files */,
|
||||||
);
|
);
|
||||||
path = OnePassword;
|
path = OnePassword;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2292,15 +2271,14 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "OnePassword" */;
|
buildConfigurationList = DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "OnePassword" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
DA6556E314D55F3000841C99 /* ShellScript */,
|
|
||||||
DA5BFA40147E415C00F98B1E /* Sources */,
|
DA5BFA40147E415C00F98B1E /* Sources */,
|
||||||
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
DA5BFA41147E415C00F98B1E /* Frameworks */,
|
||||||
DA5BFA42147E415C00F98B1E /* Resources */,
|
DA5BFA42147E415C00F98B1E /* Resources */,
|
||||||
|
DA6556E314D55F3000841C99 /* ShellScript */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
DA6556E214D55C4400841C99 /* PBXTargetDependency */,
|
|
||||||
DAC63282148681190075AEA5 /* PBXTargetDependency */,
|
DAC63282148681190075AEA5 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = OnePassword;
|
name = OnePassword;
|
||||||
@ -2388,7 +2366,6 @@
|
|||||||
DAC77CAC148291A600BCF976 /* Pearl */,
|
DAC77CAC148291A600BCF976 /* Pearl */,
|
||||||
DAC6325C1486805C0075AEA5 /* uicolor-utilities */,
|
DAC6325C1486805C0075AEA5 /* uicolor-utilities */,
|
||||||
DAC6326B148680650075AEA5 /* jrswizzle */,
|
DAC6326B148680650075AEA5 /* jrswizzle */,
|
||||||
DA6556DC14D55C1500841C99 /* InfoPlist */,
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@ -2951,20 +2928,6 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
DA6556E014D55C2700841C99 /* ShellScript */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
outputPaths = (
|
|
||||||
InfoPlist.h,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = "/usr/bin/env bash";
|
|
||||||
shellScript = "cat > \"$SCRIPT_OUTPUT_FILE_0\" <<. \n#define GIT_COMMIT $(git describe --tags --always --dirty --long)\n#define GIT_TAG $(git describe --tags | sed 's/-[^-]*-[^-]*$//')h\n#define GIT_COMMIT_YEAR $(git log --format=format:%ci HEAD^.. | sed 's/-.*//')\n.\ntouch /Users/lhunath/Documents/workspace/lyndir/OnePassword/OnePassword/OnePassword-Info.plist";
|
|
||||||
};
|
|
||||||
DA6556E314D55F3000841C99 /* ShellScript */ = {
|
DA6556E314D55F3000841C99 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@ -2975,8 +2938,8 @@
|
|||||||
outputPaths = (
|
outputPaths = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = "/usr/bin/env bash";
|
||||||
shellScript = "PATH+=:/usr/libexec\n\nPlistBuddy -c \"Set :CFBundleVersion $(git describe --tags --always --dirty --long)\" \"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\nPlistBuddy -c \"Set :CFBundleShortVersionString $(git describe --tags | sed 's/-[^-]*-[^-]*$//')\" \"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\n\nPlistBuddy -c \"Set :CFBundleShortVersionString $(git describe --tags | sed 's/-[^-]*-[^-]*$//')\" \"OnePassword/Settings.bundle/Root.plist\"\n";
|
shellScript = "PATH+=:/usr/libexec\nset -e\n\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n\n PlistBuddy -c \"Set :$key $value\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :$key\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n\n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\nbuild=$(git describe --tags --always --dirty --long)\ntag=$(git describe --tags | sed 's/-[^-]*-[^-]*$//')\n\nsetPlistWithKey CFBundleVersion \"$build\"\nsetPlistWithKey CFBundleShortVersionString \"$tag\"\n\nsetSettingWithTitle \"Build\" \"$build\"\nsetSettingWithTitle \"Version\" \"$tag\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
@ -3061,11 +3024,6 @@
|
|||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
DA6556E214D55C4400841C99 /* PBXTargetDependency */ = {
|
|
||||||
isa = PBXTargetDependency;
|
|
||||||
target = DA6556DC14D55C1500841C99 /* InfoPlist */;
|
|
||||||
targetProxy = DA6556E114D55C4400841C99 /* PBXContainerItemProxy */;
|
|
||||||
};
|
|
||||||
DAC63282148681190075AEA5 /* PBXTargetDependency */ = {
|
DAC63282148681190075AEA5 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = DAC77CAC148291A600BCF976 /* Pearl */;
|
target = DAC77CAC148291A600BCF976 /* Pearl */;
|
||||||
@ -3174,20 +3132,6 @@
|
|||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
DA6556DE14D55C1600841C99 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
DA6556DF14D55C1600841C99 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
DAC632661486805C0075AEA5 /* Debug */ = {
|
DAC632661486805C0075AEA5 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@ -3283,14 +3227,6 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
DA6556DD14D55C1600841C99 /* Build configuration list for PBXAggregateTarget "InfoPlist" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
DA6556DE14D55C1600841C99 /* Debug */,
|
|
||||||
DA6556DF14D55C1600841C99 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
};
|
|
||||||
DAC632651486805C0075AEA5 /* Build configuration list for PBXNativeTarget "uicolor-utilities" */ = {
|
DAC632651486805C0075AEA5 /* Build configuration list for PBXNativeTarget "uicolor-utilities" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
@ -217,7 +217,10 @@
|
|||||||
dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyPhraseHash, answerHash);
|
dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyPhraseHash, answerHash);
|
||||||
|
|
||||||
[AlertViewController showAlertWithTitle:[PearlStrings get].commonTitleError
|
[AlertViewController showAlertWithTitle:[PearlStrings get].commonTitleError
|
||||||
message:@"Incorrect master password."
|
message:
|
||||||
|
@"Incorrect master password.\n\n"
|
||||||
|
@"If you are trying to use the app with a different master password, "
|
||||||
|
@"flip the 'Change my password' option in Settings."
|
||||||
viewStyle:UIAlertViewStyleDefault
|
viewStyle:UIAlertViewStyleDefault
|
||||||
tappedButtonBlock:
|
tappedButtonBlock:
|
||||||
^(UIAlertView *alert, NSInteger buttonIndex) {
|
^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
[self.defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
[self.defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(dataStoreError)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(dataStoreError)),
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(storeKeyPhrase)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(storeKeyPhrase)),
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(rememberKeyPhrase)),
|
[NSNumber numberWithBool:YES], NSStringFromSelector(@selector(rememberKeyPhrase)),
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(forgetKeyPhrase)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(forgetKeyPhrase)),
|
||||||
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(helpHidden)),
|
[NSNumber numberWithBool:NO], NSStringFromSelector(@selector(helpHidden)),
|
||||||
nil]];
|
nil]];
|
||||||
|
@ -91,12 +91,13 @@ NSString *OPCalculateContent(OPElementType type, NSString *name, NSString *keyPh
|
|||||||
|
|
||||||
// Determine the hash whose bytes will be used for calculating a password: md4(name-keyPhrase)
|
// Determine the hash whose bytes will be used for calculating a password: md4(name-keyPhrase)
|
||||||
assert(name && keyPhrase);
|
assert(name && keyPhrase);
|
||||||
NSData *keyHash = [[NSString stringWithFormat:@"%@-%@-%d", name, keyPhrase, counter] hashWith:PearlDigestMD4];
|
NSData *keyHash = [[NSString stringWithFormat:@"%@-%@-%d", name, keyPhrase, counter] hashWith:PearlDigestSHA1];
|
||||||
const char *keyBytes = keyHash.bytes;
|
const char *keyBytes = keyHash.bytes;
|
||||||
|
|
||||||
// Determine the cipher from the first hash byte.
|
// Determine the cipher from the first hash byte.
|
||||||
assert([keyHash length]);
|
assert([keyHash length]);
|
||||||
NSArray *typeCiphers = [[OPTypes_ciphers valueForKey:@"OPElementTypeCalculated"] valueForKey:NSStringFromOPElementType(type)];
|
NSArray *typeCiphers = [[OPTypes_ciphers valueForKey:ClassNameFromOPElementType(type)]
|
||||||
|
valueForKey:NSStringFromOPElementType(type)];
|
||||||
NSString *cipher = [typeCiphers objectAtIndex:keyBytes[0] % [typeCiphers count]];
|
NSString *cipher = [typeCiphers objectAtIndex:keyBytes[0] % [typeCiphers count]];
|
||||||
|
|
||||||
// Encode the content, character by character, using subsequent hash bytes and the cipher.
|
// Encode the content, character by character, using subsequent hash bytes and the cipher.
|
||||||
@ -111,4 +112,4 @@ NSString *OPCalculateContent(OPElementType type, NSString *name, NSString *keyPh
|
|||||||
}
|
}
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright ©2011-2012, Lyndir</string>
|
<string>©2011-2012, Lyndir</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
<string>MainStoryboard_iPhone</string>
|
<string>MainStoryboard_iPhone</string>
|
||||||
<key>UIMainStoryboardFile~ipad</key>
|
<key>UIMainStoryboardFile~ipad</key>
|
||||||
|
@ -82,82 +82,168 @@
|
|||||||
<h3>What is this thing?<br />
|
<h3>What is this thing?<br />
|
||||||
How do I use it?</h3>
|
How do I use it?</h3>
|
||||||
<p>
|
<p>
|
||||||
The idea of this application is that you <b>change all of your passwords</b> everywhere to a password
|
You use it by searching for the name of your site (you choose this yourself. For Twitter, you could use
|
||||||
generated by this app.
|
<code>twitter</code>, <code>twitter.com</code>, or something else entirely as the name. Just remember how
|
||||||
|
you name your sites and try to be consistent). Tap the resulting password to copy it for pasting elsewhere
|
||||||
|
or type it manually on your computer.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The thought behind this application is to secure your online life by <b>changing all of your passwords</b>
|
||||||
|
to passwords generated by this app.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>That's crazy talk.<br />
|
<h3>That's crazy talk.<br />
|
||||||
Why would I do that?</h3>
|
Why would I do that?</h3>
|
||||||
<p>
|
<p>
|
||||||
Everybody everywhere uses passwords for authentication nowadays. The theory of password authentication is
|
The theory of password authentication is simple: To log in to a site, you share a secret word with the site
|
||||||
simple: It's a secret word that <b>only you</b> and the other party know. So, because nobody else knows
|
that <b>only you and the site know</b>. Because nobody else knows your secret password, nobody else can log
|
||||||
your secret password, nobody else can log into your <abbr>E-Mail</abbr> or Twitter account with it.
|
into your site.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
That's fine and dandy in theory. In practice, it's an <b>absolute hell</b>. In modern times, people have
|
It sounds good in theory. In practice, it's an <b>absolute hell</b>. These days, people have hundreds of
|
||||||
hundreds of accounts on sites all over the Internet. So does that mean we're all remembering hundreds of
|
accounts on sites all over the Internet. Does that mean we're all remembering hundreds of secret passwords?
|
||||||
secret passwords? No, of course not. That would be <i>impossible</i>. If you're like most people, you
|
No, of course not. That would be impossible. If you're like most people, you remember one or two
|
||||||
remember one or two passwords, and use those for all your sites everywhere.
|
passwords, and use those for all your sites everywhere.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<q>So what</q>, you say? Here's the problem: You're not the only one that knows your secret password. Each
|
<q>So, what?</q>, you might say.<br />
|
||||||
time your make an account with a site and tell them your secret password, <i>they know it too</i>! Nothing
|
Here's the problem: When you share a secret password with a site, and then share the same secret password
|
||||||
is stopping them from trying to log into GMail, Hotmail or Twitter with the same password and username you
|
with another site, both sites can now use the password you gave them to log into your account on the
|
||||||
used to register with their own site. Even if you only give your password to sites you trust, all it takes
|
<i>other</i> site. Nothing is stopping them from trying to log into <i>your</i> GMail, Hotmail or Twitter
|
||||||
is for one of those sites to get hacked and loose their password database. Those hackers now have all it
|
accounts using the same password that you used to register an account on their site. Even if you only give
|
||||||
takes to impersonate you. This is, in fact, so common, that it's one of the main reasons people's accounts
|
your password to sites you trust, all it takes is for one of those sites to get hacked and loose their
|
||||||
are getting hacked or compromised nowadays.
|
passwords database. Those hackers now have all it takes to impersonate you. This is, in fact, so common,
|
||||||
|
that it's one of the main reasons people's accounts are getting hacked nowadays.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Some of you already try to remember unique-ish passwords for different sites. This causes problems too:
|
||||||
|
with so many passwords to remember, you easily forget passwords for sites you haven't used in a while. Or
|
||||||
|
you make up a simplification algorithm such as tacking your birth year onto the site name. This is really
|
||||||
|
not any more secure than using the same password for every site. And then there's those sites with
|
||||||
|
<q>password policies</q>: suddenly your long password isn't good enough, because it begins with a number,
|
||||||
|
or because (god forbid) it's <q>too long</q>. You now find yourself forced to create a strange variant
|
||||||
|
of your password that you'll have forgotten before the day is out.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This app <b>solves the problem</b> by letting you remember only a single password without requiring you to
|
This app <b>solves the problem</b> by letting you remember only a single password without requiring you to
|
||||||
share the password with anyone else. Instead, the app creates secure passwords for use with whatever site
|
share the password with anyone else. Instead, the app creates secure passwords for use with whatever site
|
||||||
or purpose you might need a password for.
|
or purpose you might need a password for.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3>I can't change all my passwords.<br />
|
||||||
|
Some of them were assigned to me.</h3>
|
||||||
|
<p>
|
||||||
|
That's why this application allows you to change the password type to <code>Personal</code> or <code>Device
|
||||||
|
Private</code>. These types let you enter a password for a site, and the app will encrypt and save it so
|
||||||
|
you it's there for future reference.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
These types of <q>stored</q> passwords don't have all the advantages that their generated counterparts have
|
||||||
|
(they can be lost if you loose your device and don't back it up), but when you can't change a site's
|
||||||
|
password to one generated by the app, this is as good as it gets.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>Uh, so what if I loose my device?<br />
|
<h3>So, what if I loose my device?<br />
|
||||||
I'm locked out of everything?</h3>
|
I'm locked out of everything?</h3>
|
||||||
<p>
|
<p>
|
||||||
<b>Absolutely not!</b> In fact, generated passwords aren't even stored on your device. No, not in the
|
<b>Absolutely not!</b> In fact, generated passwords aren't even stored on your device. No, not in the
|
||||||
cloud either. They're not stored anywhere! What that basically means is, if you grab the iPhone of the
|
cloud either. They're not stored anywhere! What that basically means is, if you grab the iPhone of a
|
||||||
person sitting next to you and open this app on it with your own master password, <i>it'll give you all
|
colleague or friend and open this app on it with your own master password, <i>it'll give you all your
|
||||||
your generated passwords</i>. So, if you loose your phone or forget it, just borrow a friend's phone or
|
generated passwords</i> (don't worry, it's perfectly safe). So, if you loose your iPhone or forget it,
|
||||||
get a new one, and you're back in business. No backups or restores needed.
|
just open the app on your iPad, or borrow a friend's phone, and you're back in business. No backups or
|
||||||
|
restores needed.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
That also means that, unlike all those apps that store your passwords or send them off to be stored
|
This also means that, unlike all those apps that store your passwords or send them off to be stored on the
|
||||||
on the internet, your passwords are much safer. Nobody knows about them. If your device is stolen,
|
Internet, this app makes your passwords much safer from theft. If your device is stolen, the thieves can't
|
||||||
the thieves can't get at them.
|
get at your passwords. There's also no cloud service that can be mis-managed or hacked.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>I entered my master password on my friend's app. It just says <q>Invalid master password</q> and exits!</h3>
|
<h3>Great, but that still means I need my phone to get my passwords.</h3>
|
||||||
<p>
|
<p>
|
||||||
For your own protection and to avoid opening the app after <i>mistyping</i> your master password (and thus
|
Correct. However, remember that usually you'll only need to use this app once for each site. After you log
|
||||||
generating bad passwords for your sites), the app normally checks whether you're entering the same master
|
into a site once using the password generated by this app, your browser will probably ask you to remember
|
||||||
password as the one you've been using before.
|
the password for the future. Agree to that, and you won't need to bring up your phone again the next time
|
||||||
|
you log in to the account.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
To open the app with <b>a different master password</b>, just go into your device's <code>Settings</code>, find
|
A <b>Mac version</b> of this app is also in the works so that you can easily get to all of your passwords
|
||||||
<code>Master Password</code>'s settings somewhere near the bottom, and flip the setting: <code>Change my
|
without needing to bring up your phone. More technically savvy users can already download a <b>Bash
|
||||||
password</code>. The next time you open the app, you can enter a new master password. Don't worry:
|
script</b> from the homepage that can generate these passwords for you on any POSIX system (such as your
|
||||||
you're not wiping your friend's passwords this way. All he needs to do to get back at his own passwords is
|
Mac).
|
||||||
flip the switch again and change back to his own master password.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Great, but that still means I need my phone to access anything.</h3>
|
<h3>I'm paranoid.<br />
|
||||||
|
How do I maximize my security?</h3>
|
||||||
<p>
|
<p>
|
||||||
Correct. However, remember that usually you'll only need to use this app once for each site. Imagine
|
For starters, make sure you've changed the passwords of all your sites you have accounts for to those
|
||||||
you're usually on your MacBook Air. You go to Twitter, it asks for your password. You get your phone out,
|
generated by this app and make sure that you use this app when registering a new account somewhere, to
|
||||||
start the app and generate the password for <code>twitter.com</code>. You copy the password manually by
|
determine the password to use for the account.
|
||||||
typing it out on your MacBook Air. You may notice that the generated passwords have been created such that
|
|
||||||
they're fairly easy to copy. Once you log in, though, your MacBook will ask you to save the password in its
|
|
||||||
key chain. Agree to that, and you won't need to bring up your phone again the next time you log in to
|
|
||||||
Twitter.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If you're still worried, the app's homepage details <b>the algorithm</b> used to generate your passwords.
|
It's also important that you've chosen a long master password. Short master passwords, especially 4-digit
|
||||||
There's also <b>a Bash script</b> that you can use to generate your passwords on any POSIX system (such as,
|
PIN codes, are easily brute-forced by attackers. Using a <b>12-character master password</b> provides
|
||||||
your Mac). A Mac version of this app is also in the works so that you can easily get to all your passwords
|
sufficient entropy to protect against any modern-day attempt at brute-forcing, assuming the password is not
|
||||||
without needing to bring up your phone.
|
based on easily determined facts (names, birth dates, etc.). If you're really paranoid, install a keyboard
|
||||||
|
of a non-latin script (russian, chinese, ...) and create a master password using these characters or even a
|
||||||
|
mix between scripts. Just don't forget it! :-)
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you go into <code>Settings</code>, on the bottom you'll find an entry for this application; tap it to
|
||||||
|
find some advanced settings for the app. Here, you can disable <code>Remember my password</code>. Doing
|
||||||
|
so will force the app to ask for your master password each time you open it. That way, when you show your
|
||||||
|
phone to somebody else after unlocking it, they can't go through your passwords.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>I forgot my master password. What are my options?</h3>
|
||||||
|
<p>
|
||||||
|
Due to the nature of this app's algorithms and the decisions that were made to protect against brute-force
|
||||||
|
attacks, it is simply infeasible to recover your master password. If you really can't remember it, your
|
||||||
|
passwords are <b>gone</b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Where you go from here is, you change your master password (In <code>Settings</code>, flip <code>Change my
|
||||||
|
password</code> and start the app again), and for each of your accounts, you go through the password
|
||||||
|
recovery procedure (which will usually involve sending a message to your E-Mail account) and reset the
|
||||||
|
passwords of these accounts to passwords generated by your newly chosen master password. Just don't forget
|
||||||
|
it again! :-)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>So how does this thing work internally?</h3>
|
||||||
|
<p>
|
||||||
|
Alright, let's describe the process in detail. This part will likely make sense to you only if you're
|
||||||
|
well versed in computer security jargon. If you're the kind of person who likes to know how the clock
|
||||||
|
ticks before deciding that it can be trusted to keep ticking, read on.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The user chooses a single master password, preferably sufficiently long to harden against brute-force
|
||||||
|
attacks. When the user requests a password be generated for a site, the application composes a string
|
||||||
|
consisting of the site name, the master password, and a password counter, delimited in that order by a dash
|
||||||
|
character, and hashes those <code>UTF-8</code> bytes using the <code>SHA-1</code> algorithm. The bytes
|
||||||
|
resulting from this hashing operation are called the <code>keyBytes</code> in the next steps.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Next, we need the password type that the user has chosen to use for the site. Password types determine the
|
||||||
|
<q>cipher</q> that will be used to encrypt <code>keyBytes</code> into a readable password. For
|
||||||
|
instance, the standard password type <q>Long Password</q> activates one of three pre-set ciphers:
|
||||||
|
<code>CvcvCvcvnoCvcv</code>, <code>CvcvnoCvcvCvcv</code> or <code>CvcvCvcvCvcvno</code>. Which of those
|
||||||
|
will be used, depends on the first of the <code>keyBytes</code>. Take the byte value modulo the amount of
|
||||||
|
pre-set ciphers (in this case, three), and the result tells you which of the three ciphers to use.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Now that we know what cipher to use for building our final password, all that's left is to iterate the
|
||||||
|
cipher, and produce a character of password output for each step. When you iterate the cipher, every
|
||||||
|
character in the cipher represents a set of possible output characters. For instance, a <code>C</code>
|
||||||
|
character in the cipher indicates that we need to choose a capital consonant character. An <code>o</code>
|
||||||
|
character in the cipher indicates that we need to choose an <q>other</q> (symbol) character. Exactly which
|
||||||
|
character to choose in that set for the password output depends on the next byte from <code>keyBytes</code>.
|
||||||
|
Like before, take the next unused <code>keyByte</code>'s byte value modulo the amount of characters in the
|
||||||
|
set of possible output characters for the cipher iteration and use the result to choose the output
|
||||||
|
character. Repeat until you've iterated the whole cipher.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The result is a password whose format is dictated by the password type's ciphers and whose exact value is
|
||||||
|
filled in by feeding the algorithm some bytes from a hash operation on the user's givens.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>This stuff is gold.<br />
|
<h3>This stuff is gold.<br />
|
||||||
|
@ -14,37 +14,37 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>DefaultValue</key>
|
<key>DefaultValue</key>
|
||||||
<string></string>
|
<string>[auto]</string>
|
||||||
<key>Key</key>
|
|
||||||
<string>version</string>
|
|
||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string>Version</string>
|
<string>Version</string>
|
||||||
|
<key>Key</key>
|
||||||
|
<string>unset</string>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
<string>PSTitleValueSpecifier</string>
|
<string>PSTitleValueSpecifier</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>DefaultValue</key>
|
<key>DefaultValue</key>
|
||||||
<string></string>
|
<string>[auto]</string>
|
||||||
<key>Key</key>
|
|
||||||
<string>build</string>
|
|
||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string>Build</string>
|
<string>Build</string>
|
||||||
|
<key>Key</key>
|
||||||
|
<string>unset</string>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
<string>PSTitleValueSpecifier</string>
|
<string>PSTitleValueSpecifier</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>DefaultValue</key>
|
<key>DefaultValue</key>
|
||||||
<string></string>
|
<string>[auto]</string>
|
||||||
<key>Key</key>
|
|
||||||
<string>copyright</string>
|
|
||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string>Copyright</string>
|
<string>Copyright</string>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
<string>PSTitleValueSpecifier</string>
|
<string>PSTitleValueSpecifier</string>
|
||||||
|
<key>Key</key>
|
||||||
|
<string>unset</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>FooterText</key>
|
<key>FooterText</key>
|
||||||
<string>This causes your master password to be remembered while your device is powered on. Similar to your phone's SIM lock, you only need to enter the password once after powering on.</string>
|
<string>This causes your master password to be remembered while your device is powered on. Similar to your phone's SIM lock, you only need to enter the password once after powering on.</string>
|
||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string>Master Password</string>
|
<string>Master Password</string>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>FooterText</key>
|
<key>FooterText</key>
|
||||||
<string>Use this to save your master password in the key chain. This is somewhat less secure should your device get stolen, but it means you won't need to enter the master password anymore. You can compensate for the reduced security by going into General->Passcode Lock, disabling "Simple Passcode", and setting a more secure passcode for your device.</string>
|
<string>Use this to save your master password in the key chain. This is somewhat less secure should your device get stolen, but it means you won't need to enter the master password anymore. You can compensate for the reduced security by going into General->Passcode Lock, disabling "Simple Passcode", and setting a more secure passcode for your device.</string>
|
||||||
<key>Title</key>
|
<key>Title</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>OPElementTypeCalculated</key>
|
<key>OPElementGeneratedEntity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>Long Password</key>
|
<key>Long Password</key>
|
||||||
<array>
|
<array>
|
||||||
|
Loading…
Reference in New Issue
Block a user