A Java proof-of-concept CLI for Master Password.
This commit is contained in:
parent
0e8e4dc06d
commit
04a6c8e68d
49
MasterPassword/Java/masterpassword-algorithm/pom.xml
Normal file
49
MasterPassword/Java/masterpassword-algorithm/pom.xml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!-- PROJECT METADATA -->
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>Master Password Algorithm Implementation</name>
|
||||||
|
<description>The implementation of the Master Password algorithm</description>
|
||||||
|
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword-algorithm</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<!-- DEPENDENCY MANAGEMENT -->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- PROJECT REFERENCES -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||||
|
<artifactId>opal-system</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||||
|
<artifactId>opal-crypto</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- EXTERNAL DEPENDENCIES -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.plist</groupId>
|
||||||
|
<artifactId>property-list</artifactId>
|
||||||
|
<version>svn-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lambdaworks</groupId>
|
||||||
|
<artifactId>scrypt</artifactId>
|
||||||
|
<version>1.3.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public enum MPElementFeature {
|
||||||
|
|
||||||
|
/** Export the key-protected content data. */
|
||||||
|
ExportContent,
|
||||||
|
/** Never export content. */
|
||||||
|
DevicePrivate,
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public enum MPElementType {
|
||||||
|
|
||||||
|
GeneratedMaximum( "Maximum Security Password", "Maximum", "20 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||||
|
GeneratedLong( "Long Password", "Long", "Copy-friendly, 14 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||||
|
GeneratedMedium( "Medium Password", "Medium", "Copy-friendly, 8 characters, contains symbols.", MPElementTypeClass.Generated ),
|
||||||
|
GeneratedShort( "Short Password", "Short", "Copy-friendly, 4 characters, no symbols.", MPElementTypeClass.Generated ),
|
||||||
|
GeneratedBasic( "Basic Password", "Basic", "8 characters, no symbols.", MPElementTypeClass.Generated ),
|
||||||
|
GeneratedPIN( "PIN", "PIN", "4 numbers.", MPElementTypeClass.Generated ),
|
||||||
|
|
||||||
|
StoredPersonal( "Personal Password", "Personal", "AES-encrypted, exportable.", MPElementTypeClass.Stored, MPElementFeature.ExportContent ),
|
||||||
|
StoredDevicePrivate( "Device Private Password", "Private", "AES-encrypted, not exported.", MPElementTypeClass.Stored, MPElementFeature.DevicePrivate );
|
||||||
|
|
||||||
|
static final Logger logger = Logger.get( MPElementType.class );
|
||||||
|
|
||||||
|
private final MPElementTypeClass typeClass;
|
||||||
|
private final Set<MPElementFeature> typeFeatures;
|
||||||
|
private final String name;
|
||||||
|
private final String shortName;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
MPElementType(final String name, final String shortName, final String description, final MPElementTypeClass typeClass, final MPElementFeature... typeFeatures) {
|
||||||
|
|
||||||
|
this.name = name;
|
||||||
|
this.shortName = shortName;
|
||||||
|
this.typeClass = typeClass;
|
||||||
|
this.description = description;
|
||||||
|
|
||||||
|
ImmutableSet.Builder<MPElementFeature> typeFeaturesBuilder = ImmutableSet.builder();
|
||||||
|
for (final MPElementFeature typeFeature : typeFeatures)
|
||||||
|
typeFeaturesBuilder.add( typeFeature );
|
||||||
|
this.typeFeatures = typeFeaturesBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPElementTypeClass getTypeClass() {
|
||||||
|
|
||||||
|
return typeClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<MPElementFeature> getTypeFeatures() {
|
||||||
|
|
||||||
|
return typeFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getShortName() {
|
||||||
|
|
||||||
|
return shortName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MPElementType forName(final String name) {
|
||||||
|
|
||||||
|
for (final MPElementType type : values())
|
||||||
|
if (type.getName().equals( name ))
|
||||||
|
return type;
|
||||||
|
|
||||||
|
throw logger.bug( "Element type not known: %s", name );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.lyndir.lhunath.masterpassword.entity.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public enum MPElementTypeClass {
|
||||||
|
|
||||||
|
Generated(MPElementGeneratedEntity.class),
|
||||||
|
Stored(MPElementStoredEntity.class);
|
||||||
|
|
||||||
|
private final Class<? extends MPElementEntity> entityClass;
|
||||||
|
|
||||||
|
MPElementTypeClass(final Class<? extends MPElementEntity> entityClass) {
|
||||||
|
|
||||||
|
this.entityClass = entityClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<? extends MPElementEntity> getEntityClass() {
|
||||||
|
|
||||||
|
return entityClass;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPTemplate extends MetaObject {
|
||||||
|
|
||||||
|
private final List<MPTemplateCharacterClass> template;
|
||||||
|
|
||||||
|
public MPTemplate(final String template, final Map<Character, MPTemplateCharacterClass> characterClasses) {
|
||||||
|
|
||||||
|
ImmutableList.Builder<MPTemplateCharacterClass> builder = ImmutableList.<MPTemplateCharacterClass>builder();
|
||||||
|
for (int i = 0; i < template.length(); ++i)
|
||||||
|
builder.add( characterClasses.get( template.charAt( i ) ) );
|
||||||
|
|
||||||
|
this.template = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPTemplate(final List<MPTemplateCharacterClass> template) {
|
||||||
|
|
||||||
|
this.template = template;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPTemplateCharacterClass getCharacterClassAtIndex(final int index) {
|
||||||
|
|
||||||
|
return template.get( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int length() {
|
||||||
|
|
||||||
|
return template.size();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.ObjectMeta;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPTemplateCharacterClass extends MetaObject {
|
||||||
|
|
||||||
|
private final char identifier;
|
||||||
|
@ObjectMeta(useFor = { })
|
||||||
|
private final char[] characters;
|
||||||
|
|
||||||
|
public MPTemplateCharacterClass(final char identifier, final char[] characters) {
|
||||||
|
|
||||||
|
this.identifier = identifier;
|
||||||
|
this.characters = characters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getIdentifier() {
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getCharacterAtRollingIndex(final int index) {
|
||||||
|
|
||||||
|
return characters[index % characters.length];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.io.Closeables;
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.MetaObject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import net.sf.plist.*;
|
||||||
|
import net.sf.plist.io.PropertyListException;
|
||||||
|
import net.sf.plist.io.PropertyListParser;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPTemplates extends MetaObject {
|
||||||
|
|
||||||
|
static final Logger logger = Logger.get( MPTemplates.class );
|
||||||
|
|
||||||
|
private final Map<MPElementType, List<MPTemplate>> templates;
|
||||||
|
|
||||||
|
public MPTemplates(final Map<MPElementType, List<MPTemplate>> templates) {
|
||||||
|
|
||||||
|
this.templates = templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MPTemplates loadFromPList(final String templateResource) {
|
||||||
|
|
||||||
|
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
|
||||||
|
InputStream templateStream = Thread.currentThread().getContextClassLoader().getResourceAsStream( templateResource );
|
||||||
|
try {
|
||||||
|
NSObject plistObject = PropertyListParser.parse( templateStream );
|
||||||
|
Preconditions.checkState( NSDictionary.class.isAssignableFrom( plistObject.getClass() ) );
|
||||||
|
NSDictionary plist = (NSDictionary) plistObject;
|
||||||
|
|
||||||
|
NSDictionary characterClassesDict = (NSDictionary) plist.get( "MPCharacterClasses" );
|
||||||
|
NSDictionary templatesDict = (NSDictionary) plist.get( "MPElementGeneratedEntity" );
|
||||||
|
|
||||||
|
ImmutableMap.Builder<Character, MPTemplateCharacterClass> characterClassesBuilder = ImmutableMap.builder();
|
||||||
|
for (final Map.Entry<String, NSObject> characterClassEntry : characterClassesDict.entrySet()) {
|
||||||
|
String key = characterClassEntry.getKey();
|
||||||
|
NSObject value = characterClassEntry.getValue();
|
||||||
|
Preconditions.checkState( key.length() == 1 );
|
||||||
|
Preconditions.checkState( NSString.class.isAssignableFrom( value.getClass() ));
|
||||||
|
|
||||||
|
char character = key.charAt( 0 );
|
||||||
|
char[] characterClass = ((NSString)value).getValue().toCharArray();
|
||||||
|
characterClassesBuilder.put( character, new MPTemplateCharacterClass( character, characterClass ) );
|
||||||
|
}
|
||||||
|
ImmutableMap<Character, MPTemplateCharacterClass> characterClasses = characterClassesBuilder.build();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<MPElementType, List<MPTemplate>> templatesBuilder = ImmutableMap.builder();
|
||||||
|
for (final Map.Entry<String, NSObject> template : templatesDict.entrySet()) {
|
||||||
|
String key = template.getKey();
|
||||||
|
NSObject value = template.getValue();
|
||||||
|
Preconditions.checkState( NSArray.class.isAssignableFrom( value.getClass() ) );
|
||||||
|
|
||||||
|
MPElementType type = MPElementType.forName( key );
|
||||||
|
List<NSObject> templateStrings = ((NSArray) value).getValue();
|
||||||
|
|
||||||
|
ImmutableList.Builder<MPTemplate> typeTemplatesBuilder = ImmutableList.<MPTemplate>builder();
|
||||||
|
for (final NSObject templateString : templateStrings)
|
||||||
|
typeTemplatesBuilder.add( new MPTemplate( ((NSString) templateString).getValue(), characterClasses ) );
|
||||||
|
|
||||||
|
templatesBuilder.put( type, typeTemplatesBuilder.build() );
|
||||||
|
}
|
||||||
|
ImmutableMap<MPElementType, List<MPTemplate>> templates = templatesBuilder.build();
|
||||||
|
|
||||||
|
return new MPTemplates( templates );
|
||||||
|
}
|
||||||
|
catch (PropertyListException e) {
|
||||||
|
logger.err( e, "Could not parse templates from: %s", templateResource );
|
||||||
|
throw Throwables.propagate( e );
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
logger.err( e, "Could not read templates from: %s", templateResource );
|
||||||
|
throw Throwables.propagate( e );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Closeables.closeQuietly( templateStream );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPTemplate getTemplateForTypeAtRollingIndex(final MPElementType type, final int templateIndex) {
|
||||||
|
|
||||||
|
List<MPTemplate> typeTemplates = templates.get( type );
|
||||||
|
|
||||||
|
return typeTemplates.get( templateIndex % typeTemplates.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String... arguments) {
|
||||||
|
|
||||||
|
loadFromPList( "templates.plist" );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.primitives.Bytes;
|
||||||
|
import com.lambdaworks.crypto.SCrypt;
|
||||||
|
import com.lyndir.lhunath.opal.crypto.CryptUtils;
|
||||||
|
import com.lyndir.lhunath.opal.system.*;
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the Master Password algorithm.
|
||||||
|
*
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public abstract class MasterPassword {
|
||||||
|
|
||||||
|
static final Logger logger = Logger.get( MasterPassword.class );
|
||||||
|
private static final int MP_N = 32768;
|
||||||
|
private static final int MP_r = 8;
|
||||||
|
private static final int MP_p = 2;
|
||||||
|
private static final int MP_dkLen = 64;
|
||||||
|
private static final Charset MP_charset = Charsets.UTF_8;
|
||||||
|
private static final ByteOrder MP_byteOrder = ByteOrder.BIG_ENDIAN;
|
||||||
|
private static final MessageDigests MP_hash = MessageDigests.SHA256;
|
||||||
|
private static final MessageAuthenticationDigests MP_mac = MessageAuthenticationDigests.HmacSHA256;
|
||||||
|
private static final MPTemplates templates = MPTemplates.loadFromPList( "templates.plist" );
|
||||||
|
|
||||||
|
public static byte[] keyForPassword(final String password, final String username) {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
byte[] nusernameLengthBytes = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE )
|
||||||
|
.order( MP_byteOrder )
|
||||||
|
.putInt( username.length() )
|
||||||
|
.array();
|
||||||
|
byte[] salt = Bytes.concat( "com.lyndir.masterpassword".getBytes( MP_charset ), //
|
||||||
|
nusernameLengthBytes, //
|
||||||
|
username.getBytes( MP_charset ) );
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] key = SCrypt.scrypt( password.getBytes( MP_charset ), salt, MP_N, MP_r, MP_p, MP_dkLen );
|
||||||
|
logger.trc( "User: %s, password: %s derives to key ID: %s (took %.2fs)", username, password,
|
||||||
|
CodeUtils.encodeHex( keyIDForKey( key ) ), (double) (System.currentTimeMillis() - start) / 1000 );
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
catch (GeneralSecurityException e) {
|
||||||
|
throw logger.bug( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] subkeyForKey(final byte[] key, final int subkeyLength) {
|
||||||
|
|
||||||
|
byte[] subkey = new byte[Math.min( subkeyLength, key.length )];
|
||||||
|
System.arraycopy( key, 0, subkey, 0, subkey.length );
|
||||||
|
|
||||||
|
return subkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] keyIDForPassword(final String password, final String username) {
|
||||||
|
|
||||||
|
return keyIDForKey( keyForPassword( password, username ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] keyIDForKey(final byte[] key) {
|
||||||
|
|
||||||
|
return MP_hash.of( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateContent(final MPElementType type, final String name, final byte[] key, int counter) {
|
||||||
|
|
||||||
|
Preconditions.checkArgument( type.getTypeClass() == MPElementTypeClass.Generated );
|
||||||
|
Preconditions.checkArgument( !name.isEmpty() );
|
||||||
|
Preconditions.checkArgument( key.length > 0 );
|
||||||
|
|
||||||
|
if (counter == 0)
|
||||||
|
counter = (int) (System.currentTimeMillis() / (300 * 1000)) * 300;
|
||||||
|
|
||||||
|
byte[] nameLengthBytes = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( MP_byteOrder ).putInt( name.length() ).array();
|
||||||
|
byte[] counterBytes = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( MP_byteOrder ).putInt( counter ).array();
|
||||||
|
logger.trc( "seed from: hmac-sha256(%s, 'com.lyndir.masterpassword' | %s | %s | %s)", CryptUtils.encodeBase64( key ),
|
||||||
|
CodeUtils.encodeHex( nameLengthBytes ), name, CodeUtils.encodeHex( counterBytes ) );
|
||||||
|
byte[] seed = MP_mac.of( key, Bytes.concat( "com.lyndir.masterpassword".getBytes( MP_charset ), //
|
||||||
|
nameLengthBytes, //
|
||||||
|
name.getBytes( MP_charset ), //
|
||||||
|
counterBytes ) );
|
||||||
|
logger.trc( "seed is: %s", CryptUtils.encodeBase64( seed ) );
|
||||||
|
|
||||||
|
Preconditions.checkState( seed.length > 0 );
|
||||||
|
int templateIndex = seed[0] & 0xFF; // Mask the integer's sign.
|
||||||
|
MPTemplate template = templates.getTemplateForTypeAtRollingIndex( type, templateIndex );
|
||||||
|
logger.trc( "type: %s, template: %s", type, template );
|
||||||
|
|
||||||
|
StringBuilder password = new StringBuilder( template.length() );
|
||||||
|
for (int i = 0; i < template.length(); ++i) {
|
||||||
|
int characterIndex = seed[i + 1] & 0xFF; // Mask the integer's sign.
|
||||||
|
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
|
||||||
|
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
|
||||||
|
logger.trc( "class: %s, index: %d, byte: 0x%02X, chosen password character: %s", characterClass, characterIndex, seed[i + 1],
|
||||||
|
passwordCharacter );
|
||||||
|
|
||||||
|
password.append( passwordCharacter );
|
||||||
|
}
|
||||||
|
|
||||||
|
return password.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(final String... arguments) {
|
||||||
|
|
||||||
|
String masterPassword = "test-mp";
|
||||||
|
String username = "test-user";
|
||||||
|
String siteName = "test-site";
|
||||||
|
MPElementType siteType = MPElementType.GeneratedLong;
|
||||||
|
int siteCounter = 42;
|
||||||
|
|
||||||
|
String sitePassword = generateContent( siteType, siteName, keyForPassword( masterPassword, username ), siteCounter );
|
||||||
|
|
||||||
|
logger.inf( "master password: %s, username: %s\nsite name: %s, site type: %s, site counter: %d\n => site password: %s",
|
||||||
|
masterPassword, username, siteName, siteType, siteCounter, sitePassword );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPElementEntity {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPElementGeneratedEntity extends MPElementEntity {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.lyndir.lhunath.masterpassword.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <i>07 04, 2012</i>
|
||||||
|
*
|
||||||
|
* @author lhunath
|
||||||
|
*/
|
||||||
|
public class MPElementStoredEntity extends MPElementEntity {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
../../../../../../Resources/ciphers.plist
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>MPElementGeneratedEntity</key>
|
||||||
|
<dict>
|
||||||
|
<key>Maximum Security Password</key>
|
||||||
|
<array>
|
||||||
|
<string>anoxxxxxxxxxxxxxxxxx</string>
|
||||||
|
<string>axxxxxxxxxxxxxxxxxno</string>
|
||||||
|
</array>
|
||||||
|
<key>Long Password</key>
|
||||||
|
<array>
|
||||||
|
<string>CvcvnoCvcvCvcv</string>
|
||||||
|
<string>CvcvCvcvnoCvcv</string>
|
||||||
|
<string>CvcvCvcvCvcvno</string>
|
||||||
|
<string>CvccnoCvcvCvcv</string>
|
||||||
|
<string>CvccCvcvnoCvcv</string>
|
||||||
|
<string>CvccCvcvCvcvno</string>
|
||||||
|
<string>CvcvnoCvccCvcv</string>
|
||||||
|
<string>CvcvCvccnoCvcv</string>
|
||||||
|
<string>CvcvCvccCvcvno</string>
|
||||||
|
<string>CvcvnoCvcvCvcc</string>
|
||||||
|
<string>CvcvCvcvnoCvcc</string>
|
||||||
|
<string>CvcvCvcvCvccno</string>
|
||||||
|
<string>CvccnoCvccCvcv</string>
|
||||||
|
<string>CvccCvccnoCvcv</string>
|
||||||
|
<string>CvccCvccCvcvno</string>
|
||||||
|
<string>CvcvnoCvccCvcc</string>
|
||||||
|
<string>CvcvCvccnoCvcc</string>
|
||||||
|
<string>CvcvCvccCvccno</string>
|
||||||
|
<string>CvccnoCvcvCvcc</string>
|
||||||
|
<string>CvccCvcvnoCvcc</string>
|
||||||
|
<string>CvccCvcvCvccno</string>
|
||||||
|
</array>
|
||||||
|
<key>Medium Password</key>
|
||||||
|
<array>
|
||||||
|
<string>CvcnoCvc</string>
|
||||||
|
<string>CvcCvcno</string>
|
||||||
|
</array>
|
||||||
|
<key>Short Password</key>
|
||||||
|
<array>
|
||||||
|
<string>Cvcn</string>
|
||||||
|
</array>
|
||||||
|
<key>Basic Password</key>
|
||||||
|
<array>
|
||||||
|
<string>aaanaaan</string>
|
||||||
|
<string>aannaaan</string>
|
||||||
|
<string>aaannaaa</string>
|
||||||
|
</array>
|
||||||
|
<key>PIN</key>
|
||||||
|
<array>
|
||||||
|
<string>nnnn</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<key>MPCharacterClasses</key>
|
||||||
|
<dict>
|
||||||
|
<key>V</key>
|
||||||
|
<string>AEIOU</string>
|
||||||
|
<key>C</key>
|
||||||
|
<string>BCDFGHJKLMNPQRSTVWXYZ</string>
|
||||||
|
<key>v</key>
|
||||||
|
<string>aeiou</string>
|
||||||
|
<key>c</key>
|
||||||
|
<string>bcdfghjklmnpqrstvwxyz</string>
|
||||||
|
<key>A</key>
|
||||||
|
<string>AEIOUBCDFGHJKLMNPQRSTVWXYZ</string>
|
||||||
|
<key>a</key>
|
||||||
|
<string>AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz</string>
|
||||||
|
<key>n</key>
|
||||||
|
<string>0123456789</string>
|
||||||
|
<key>o</key>
|
||||||
|
<string>@&%?,=[]_:-+*$#!'^~;()/.</string>
|
||||||
|
<key>x</key>
|
||||||
|
<string>AEIOUaeiouBCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz0123456789!@#$%^&*()</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
@ -0,0 +1,5 @@
|
|||||||
|
#Generated by Maven
|
||||||
|
#Wed Jul 04 23:49:38 CEST 2012
|
||||||
|
version=GIT-SNAPSHOT
|
||||||
|
groupId=com.lyndir.lhunath.masterpassword
|
||||||
|
artifactId=masterpassword-algorithm
|
80
MasterPassword/Java/masterpassword-cli/pom.xml
Normal file
80
MasterPassword/Java/masterpassword-cli/pom.xml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!-- PROJECT METADATA -->
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>Master Password CLI</name>
|
||||||
|
<description>A CLI interface to the Master Password algorithm</description>
|
||||||
|
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword-cli</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<!-- BUILD CONFIGURATION -->
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/scripts</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
<targetPath>${project.build.directory}</targetPath>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>com.lyndir.lhunath.masterpassword.CLI</mainClass>
|
||||||
|
<addClasspath>true</addClasspath>
|
||||||
|
<classpathPrefix>lib/</classpathPrefix>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-dependencies</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-dependencies</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${project.build.directory}/lib</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<!-- DEPENDENCY MANAGEMENT -->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- PROJECT REFERENCES -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword-algorithm</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Maarten Billemont
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package com.lyndir.lhunath.masterpassword;
|
||||||
|
|
||||||
|
import com.google.common.io.LineReader;
|
||||||
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p> <i>Jun 10, 2008</i> </p>
|
||||||
|
*
|
||||||
|
* @author mbillemo
|
||||||
|
*/
|
||||||
|
public class CLI {
|
||||||
|
|
||||||
|
static final Logger logger = Logger.get( CLI.class );
|
||||||
|
|
||||||
|
public static void main(final String[] args)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
InputStream in = System.in;
|
||||||
|
|
||||||
|
/* Arguments. */
|
||||||
|
String userName = null, siteName = null;
|
||||||
|
int counter = 1;
|
||||||
|
MPElementType type = MPElementType.GeneratedLong;
|
||||||
|
boolean typeArg = false, counterArg = false, userNameArg = false;
|
||||||
|
for (final String arg : Arrays.asList( args ))
|
||||||
|
if ("-t".equals( arg ) || "--type".equals( arg ))
|
||||||
|
typeArg = true;
|
||||||
|
else if (typeArg) {
|
||||||
|
if ("list".equalsIgnoreCase( arg )) {
|
||||||
|
System.out.format( "%30s | %s\n", "type", "description" );
|
||||||
|
for (final MPElementType aType : MPElementType.values())
|
||||||
|
System.out.format( "%30s | %s\n", aType.getName(), aType.getDescription() );
|
||||||
|
System.exit( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
type = MPElementType.forName( arg );
|
||||||
|
typeArg = false;
|
||||||
|
} else if ("-c".equals( arg ) || "--counter".equals( arg ))
|
||||||
|
counterArg = true;
|
||||||
|
else if (counterArg) {
|
||||||
|
counter = ConversionUtils.toIntegerNN( arg );
|
||||||
|
counterArg = false;
|
||||||
|
} else if ("-u".equals( arg ) || "--username".equals( arg ))
|
||||||
|
userNameArg = true;
|
||||||
|
else if (userNameArg) {
|
||||||
|
userName = arg;
|
||||||
|
userNameArg = false;
|
||||||
|
} else if ("-h".equals( arg ) || "--help".equals( arg )) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "\tMaster Password CLI" );
|
||||||
|
System.out.println( "\t\tLyndir" );
|
||||||
|
|
||||||
|
System.out.println( "[options] [site name]" );
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "Available options:" );
|
||||||
|
System.out.println( "\t-t | --type [site password type]" );
|
||||||
|
System.out.format( "\t\tDefault: %s. The password type to use for this site.\n", type.getName() );
|
||||||
|
System.out.println( "\t\tUse 'list' to see the available types." );
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "\t-c | --counter [site counter]" );
|
||||||
|
System.out.format( "\t\tDefault: %d. The counter to use for this site.\n", counter );
|
||||||
|
System.out.println( "\t\tIncrement the counter if you need a new password." );
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "\t-u | --username [user's name]" );
|
||||||
|
System.out.println( "\t\tDefault: asked. The name of the current user." );
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
siteName = arg;
|
||||||
|
LineReader lineReader = new LineReader( new InputStreamReader( System.in ) );
|
||||||
|
if (siteName == null) {
|
||||||
|
System.out.print( "Site name: " );
|
||||||
|
siteName = lineReader.readLine();
|
||||||
|
}
|
||||||
|
if (userName == null) {
|
||||||
|
System.out.print( "User's name: " );
|
||||||
|
userName = lineReader.readLine();
|
||||||
|
}
|
||||||
|
System.out.print( "User's master password: " );
|
||||||
|
String masterPassword = lineReader.readLine();
|
||||||
|
|
||||||
|
String sitePassword = MasterPassword.generateContent( type, siteName, MasterPassword.keyForPassword( masterPassword, userName ),
|
||||||
|
counter );
|
||||||
|
System.out.println( sitePassword );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
<configuration scan="true">
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||||
|
<Pattern>%-8relative %22c{0} [%-5level] %msg%n</Pattern>
|
||||||
|
</layout>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<logger name="com.lyndir" level="TRACE" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<logger name="org.apache.wicket" level="DEBUG" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
4
MasterPassword/Java/masterpassword-cli/src/main/scripts/mpw
Executable file
4
MasterPassword/Java/masterpassword-cli/src/main/scripts/mpw
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
java -jar masterpassword-cli-GIT-SNAPSHOT.jar "$@"
|
Binary file not shown.
Binary file not shown.
BIN
MasterPassword/Java/masterpassword-cli/target/lib/asm-3.3.1.jar
Normal file
BIN
MasterPassword/Java/masterpassword-cli/target/lib/asm-3.3.1.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
MasterPassword/Java/masterpassword-cli/target/lib/guava-r09.jar
Normal file
BIN
MasterPassword/Java/masterpassword-cli/target/lib/guava-r09.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,5 @@
|
|||||||
|
#Generated by Maven
|
||||||
|
#Wed Jul 04 23:49:39 CEST 2012
|
||||||
|
version=GIT-SNAPSHOT
|
||||||
|
groupId=com.lyndir.lhunath.masterpassword
|
||||||
|
artifactId=masterpassword-cli
|
4
MasterPassword/Java/masterpassword-cli/target/mpw
Executable file
4
MasterPassword/Java/masterpassword-cli/target/mpw
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cd "${BASH_SOURCE[0]%/*}"
|
||||||
|
java -jar masterpassword-cli-GIT-SNAPSHOT.jar "$@"
|
26
MasterPassword/Java/pom.xml
Normal file
26
MasterPassword/Java/pom.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!-- PROJECT METADATA -->
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lyndir.lhunath</groupId>
|
||||||
|
<artifactId>lyndir</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>Master Password</name>
|
||||||
|
<description>A Java implementation of the Master Password algorithm.</description>
|
||||||
|
|
||||||
|
<groupId>com.lyndir.lhunath.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>masterpassword-algorithm</module>
|
||||||
|
<module>masterpassword-cli</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
</project>
|
Loading…
Reference in New Issue
Block a user