2
0

Fully replace Java mpw algorithm implementation with proxy to standard C implementation.

This commit is contained in:
Maarten Billemont
2018-06-04 01:43:46 -04:00
parent 6957d46ef9
commit 882de547d0
33 changed files with 356 additions and 431 deletions

View File

@@ -7,17 +7,18 @@ description = 'Master Password Site Model'
dependencies {
implementation group: 'com.lyndir.lhunath.opal', name: 'opal-system', version: '1.7-p1'
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.5'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.5'
api project( ':masterpassword-algorithm' )
api 'joda-time:joda-time:2.4'
api 'com.fasterxml.jackson.core:jackson-annotations:2.9.5'
api 'com.fasterxml.jackson.core:jackson-databind:2.9.5'
api group: 'joda-time', name: 'joda-time', version: '2.4'
api group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5'
api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5'
api group: 'com.google.code.findbugs', name: 'findbugs-annotations', version: '3.0.1'
compileOnly 'com.google.auto.value:auto-value:1.2'
compileOnly group: 'com.google.auto.value', name: 'auto-value', version: '1.2'
apt group: 'com.google.auto.value', name: 'auto-value', version: '1.2'
testCompile 'org.testng:testng:6.8.5'
testCompile 'ch.qos.logback:logback-classic:1.1.2'
testCompile group: 'org.testng', name: 'testng', version: '6.8.5'
testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2'
}
test.useTestNG()

View File

@@ -18,10 +18,13 @@
package com.lyndir.masterpassword.model;
import com.lyndir.masterpassword.MPException;
/**
* @author lhunath, 14-12-17
*/
public class MPIncorrectMasterPasswordException extends Exception {
public class MPIncorrectMasterPasswordException extends MPException {
private final MPUser<?> user;

View File

@@ -18,8 +18,7 @@
package com.lyndir.masterpassword.model;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import com.lyndir.masterpassword.MPResultType;
import com.lyndir.masterpassword.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -43,7 +42,7 @@ public interface MPQuestion extends Comparable<MPQuestion> {
@Nonnull
String getAnswer(@Nullable String state)
throws MPKeyUnavailableException;
throws MPKeyUnavailableException, MPAlgorithmException;
// -- Relationship

View File

@@ -54,10 +54,10 @@ public interface MPSite<Q extends MPQuestion> extends Comparable<MPSite<?>> {
void setLoginType(@Nullable MPResultType loginType);
String getResult(MPKeyPurpose keyPurpose, @Nullable String keyContext, @Nullable String state)
throws MPKeyUnavailableException;
throws MPKeyUnavailableException, MPAlgorithmException;
String getLogin(@Nullable String state)
throws MPKeyUnavailableException;
throws MPKeyUnavailableException, MPAlgorithmException;
// - Relations

View File

@@ -62,7 +62,7 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
* @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
*/
void authenticate(char[] masterPassword)
throws MPIncorrectMasterPasswordException;
throws MPIncorrectMasterPasswordException, MPAlgorithmException;
/**
* Performs an authentication attempt against the keyID for this user.
@@ -74,7 +74,7 @@ public interface MPUser<S extends MPSite<?>> extends Comparable<MPUser<?>> {
* @throws MPIncorrectMasterPasswordException If authentication fails due to the given master password not matching the user's keyID.
*/
void authenticate(MPMasterKey masterKey)
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException;
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException;
boolean isMasterKeyAvailable();

View File

@@ -61,7 +61,7 @@ public abstract class MPBasicQuestion implements MPQuestion {
@Nonnull
@Override
public String getAnswer(@Nullable final String state)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getSite().getResult( MPKeyPurpose.Recovery, getKeyword(), null, getType(), state );
}

View File

@@ -108,14 +108,14 @@ public abstract class MPBasicSite<Q extends MPQuestion> implements MPSite<Q> {
@Override
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext, @Nullable final String state)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getResult( keyPurpose, keyContext, getCounter(), getResultType(), state );
}
protected String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
@Nullable final UnsignedInteger counter, final MPResultType type, @Nullable final String state)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getUser().getMasterKey().siteResult(
getName(), getAlgorithm(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ),
@@ -124,7 +124,7 @@ public abstract class MPBasicSite<Q extends MPQuestion> implements MPSite<Q> {
protected String getState(final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
@Nullable final UnsignedInteger counter, final MPResultType type, final String state)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getUser().getMasterKey().siteState(
getName(), getAlgorithm(), ifNotNullElse( counter, getAlgorithm().mpw_default_counter() ),
@@ -133,7 +133,7 @@ public abstract class MPBasicSite<Q extends MPQuestion> implements MPSite<Q> {
@Override
public String getLogin(@Nullable final String state)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getResult( MPKeyPurpose.Identification, null, null, getLoginType(), state );
}

View File

@@ -22,6 +22,7 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.google.common.collect.ImmutableList;
import com.lyndir.lhunath.opal.system.CodeUtils;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.masterpassword.*;
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
import com.lyndir.masterpassword.model.MPUser;
@@ -35,6 +36,8 @@ import javax.annotation.Nullable;
*/
public abstract class MPBasicUser<S extends MPBasicSite<?>> implements MPUser<S> {
protected final Logger logger = Logger.get( getClass() );
private int avatar;
private final String fullName;
private MPAlgorithm algorithm;
@@ -86,7 +89,8 @@ public abstract class MPBasicUser<S extends MPBasicSite<?>> implements MPUser<S>
try {
return getMasterKey().getKeyID( getAlgorithm() );
}
catch (final MPKeyUnavailableException ignore) {
catch (final MPException e) {
logger.wrn( e, "While deriving key ID for user: %s", this );
return null;
}
}
@@ -99,7 +103,7 @@ public abstract class MPBasicUser<S extends MPBasicSite<?>> implements MPUser<S>
@Override
public void authenticate(final char[] masterPassword)
throws MPIncorrectMasterPasswordException {
throws MPIncorrectMasterPasswordException, MPAlgorithmException {
try {
authenticate( new MPMasterKey( getFullName(), masterPassword ) );
}
@@ -110,7 +114,7 @@ public abstract class MPBasicUser<S extends MPBasicSite<?>> implements MPUser<S>
@Override
public void authenticate(final MPMasterKey masterKey)
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
if (!masterKey.getFullName().equals( getFullName() ))
throw new IllegalArgumentException(
"Master key (for " + masterKey.getFullName() + ") is not for this user (" + getFullName() + ")." );
@@ -132,7 +136,7 @@ public abstract class MPBasicUser<S extends MPBasicSite<?>> implements MPUser<S>
public MPMasterKey getMasterKey()
throws MPKeyUnavailableException {
if (masterKey == null)
throw new MPKeyUnavailableException();
throw new MPKeyUnavailableException( "Master key was not yet set." );
return masterKey;
}

View File

@@ -44,12 +44,12 @@ public class MPFileQuestion extends MPBasicQuestion {
}
public String getAnswer()
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getAnswer( state );
}
public void setAnswer(final MPResultType type, @Nullable final String answer)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
setType( type );
if (answer == null)

View File

@@ -94,19 +94,19 @@ public class MPFileSite extends MPBasicSite<MPFileQuestion> {
}
public String getResult()
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getResult( MPKeyPurpose.Authentication, null );
}
public String getResult(final MPKeyPurpose keyPurpose, @Nullable final String keyContext)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getResult( keyPurpose, keyContext, getResultState() );
}
public String getLogin()
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
return getLogin( getLoginState() );
}
@@ -117,7 +117,7 @@ public class MPFileSite extends MPBasicSite<MPFileQuestion> {
}
public void setSitePassword(final MPResultType resultType, @Nullable final String password)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
setResultType( resultType );
if (password == null)
@@ -133,7 +133,7 @@ public class MPFileSite extends MPBasicSite<MPFileQuestion> {
}
public void setLoginName(@Nonnull final MPResultType loginType, @Nullable final String loginName)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
setLoginType( loginType );
if (loginName == null)

View File

@@ -87,6 +87,9 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
catch (final MPKeyUnavailableException e) {
throw new IllegalStateException( "Cannot update algorithm when keyID is set but masterKey is unavailable.", e );
}
catch (final MPAlgorithmException e) {
throw new IllegalStateException( e );
}
}
super.setAlgorithm( algorithm );
@@ -135,7 +138,7 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
@Override
public void authenticate(final MPMasterKey masterKey)
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
super.authenticate( masterKey );
if (keyID == null)
@@ -143,7 +146,7 @@ public class MPFileUser extends MPBasicUser<MPFileSite> {
}
void save()
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
MPFileUserManager.get().save( this, getMasterKey() );
}

View File

@@ -24,8 +24,7 @@ import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.io.CharSink;
import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import com.lyndir.masterpassword.MPMasterKey;
import com.lyndir.masterpassword.*;
import com.lyndir.masterpassword.model.*;
import java.io.*;
import java.util.HashMap;
@@ -88,7 +87,7 @@ public class MPFileUserManager extends MPUserManager<MPFileUser> {
catch (final IOException | MPMarshalException e) {
logger.err( e, "Couldn't read user from: %s", userFile );
}
catch (final MPKeyUnavailableException | MPIncorrectMasterPasswordException e) {
catch (final MPKeyUnavailableException | MPIncorrectMasterPasswordException | MPAlgorithmException e) {
logger.err( e, "Couldn't authenticate user for: %s", userFile );
}
@@ -119,7 +118,7 @@ public class MPFileUserManager extends MPUserManager<MPFileUser> {
* Write the current user state to disk.
*/
public void save(final MPFileUser user, final MPMasterKey masterKey)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
try {
MPMarshalFormat format = user.getFormat();
new CharSink() {

View File

@@ -21,6 +21,7 @@ package com.lyndir.masterpassword.model.impl;
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.lyndir.masterpassword.MPAlgorithmException;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import com.lyndir.masterpassword.model.MPConstant;
import javax.annotation.Nonnull;
@@ -38,7 +39,7 @@ public class MPFlatMarshaller implements MPMarshaller {
@Nonnull
@Override
public String marshall(final MPFileUser user)
throws MPKeyUnavailableException, MPMarshalException {
throws MPKeyUnavailableException, MPMarshalException, MPAlgorithmException {
StringBuilder content = new StringBuilder();
content.append( "# Master Password site export\n" );
content.append( "# " ).append( user.getContentMode().description() ).append( '\n' );

View File

@@ -50,7 +50,7 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
@Nonnull
@Override
public MPFileUser unmarshall(@Nonnull final File file, @Nullable final char[] masterPassword)
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
try (Reader reader = new InputStreamReader( new FileInputStream( file ), Charsets.UTF_8 )) {
return unmarshall( CharStreams.toString( reader ), masterPassword );
}
@@ -59,7 +59,7 @@ public class MPFlatUnmarshaller implements MPUnmarshaller {
@Nonnull
@Override
public MPFileUser unmarshall(@Nonnull final String content, @Nullable final char[] masterPassword)
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
MPFileUser user = null;
byte[] keyID = null;
String fullName = null;

View File

@@ -27,6 +27,7 @@ import com.lyndir.lhunath.opal.system.CodeUtils;
import com.lyndir.masterpassword.*;
import com.lyndir.masterpassword.model.MPConstant;
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.Nullable;
@@ -36,6 +37,7 @@ import org.joda.time.Instant;
/**
* @author lhunath, 2018-04-27
*/
@SuppressFBWarnings( "URF_UNREAD_FIELD" )
public class MPJSONFile extends MPJSONAnyObject {
protected static final ObjectMapper objectMapper = new ObjectMapper();
@@ -46,7 +48,7 @@ public class MPJSONFile extends MPJSONAnyObject {
}
public MPJSONFile write(final MPFileUser modelUser)
throws MPKeyUnavailableException {
throws MPKeyUnavailableException, MPAlgorithmException {
// Section: "export"
if (export == null)
export = new Export();
@@ -134,7 +136,7 @@ public class MPJSONFile extends MPJSONAnyObject {
}
public MPFileUser read(@Nullable final char[] masterPassword)
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
MPAlgorithm algorithm = ifNotNullElse( user.algorithm, MPAlgorithm.Version.CURRENT ).getAlgorithm();
MPFileUser model = new MPFileUser(
user.full_name, CodeUtils.decodeHex( user.key_id ), algorithm, user.avatar,

View File

@@ -21,6 +21,7 @@ package com.lyndir.masterpassword.model.impl;
import static com.lyndir.masterpassword.model.impl.MPJSONFile.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.lyndir.masterpassword.MPAlgorithmException;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import javax.annotation.Nonnull;
@@ -33,7 +34,7 @@ public class MPJSONMarshaller implements MPMarshaller {
@Nonnull
@Override
public String marshall(final MPFileUser user)
throws MPKeyUnavailableException, MPMarshalException {
throws MPKeyUnavailableException, MPMarshalException, MPAlgorithmException {
try {
return objectMapper.writeValueAsString( user.getJSON().write( user ) );

View File

@@ -22,6 +22,7 @@ import static com.lyndir.masterpassword.model.impl.MPJSONFile.*;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.lyndir.masterpassword.MPAlgorithmException;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
import java.io.File;
@@ -38,7 +39,7 @@ public class MPJSONUnmarshaller implements MPUnmarshaller {
@Nonnull
@Override
public MPFileUser unmarshall(@Nonnull final File file, @Nullable final char[] masterPassword)
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
try {
return objectMapper.readValue( file, MPJSONFile.class ).read( masterPassword );
@@ -54,7 +55,7 @@ public class MPJSONUnmarshaller implements MPUnmarshaller {
@Nonnull
@Override
public MPFileUser unmarshall(@Nonnull final String content, @Nullable final char[] masterPassword)
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException {
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException {
try {
return objectMapper.readValue( content, MPJSONFile.class ).read( masterPassword );

View File

@@ -18,10 +18,13 @@
package com.lyndir.masterpassword.model.impl;
import com.lyndir.masterpassword.MPException;
/**
* @author lhunath, 2018-04-26
*/
public class MPMarshalException extends Exception {
public class MPMarshalException extends MPException {
public MPMarshalException(final String message) {
super( message );

View File

@@ -18,6 +18,7 @@
package com.lyndir.masterpassword.model.impl;
import com.lyndir.masterpassword.MPAlgorithmException;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import javax.annotation.Nonnull;
@@ -30,7 +31,7 @@ public interface MPMarshaller {
@Nonnull
String marshall(MPFileUser user)
throws MPKeyUnavailableException, MPMarshalException;
throws MPKeyUnavailableException, MPMarshalException, MPAlgorithmException;
enum ContentMode {
PROTECTED( "Export of site names and stored passwords (unless device-private) encrypted with the master key.", true ),

View File

@@ -18,6 +18,7 @@
package com.lyndir.masterpassword.model.impl;
import com.lyndir.masterpassword.MPAlgorithmException;
import com.lyndir.masterpassword.MPKeyUnavailableException;
import com.lyndir.masterpassword.model.MPIncorrectMasterPasswordException;
import java.io.File;
@@ -33,9 +34,9 @@ public interface MPUnmarshaller {
@Nonnull
MPFileUser unmarshall(@Nonnull File file, @Nullable char[] masterPassword)
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException;
throws IOException, MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException;
@Nonnull
MPFileUser unmarshall(@Nonnull String content, @Nullable char[] masterPassword)
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException;
throws MPMarshalException, MPIncorrectMasterPasswordException, MPKeyUnavailableException, MPAlgorithmException;
}