Complete security questions model.
This commit is contained in:
parent
1b703515dd
commit
c51262ccc2
@ -39,7 +39,7 @@ public enum MPResultType {
|
|||||||
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pg^VMAUBk5x3p%HP%i4=
|
* 16: pg^VMAUBk5x3p%HP%i4=
|
||||||
*/
|
*/
|
||||||
GeneratedMaximum( "maximum", "20 characters, contains symbols.", //
|
GeneratedMaximum( "maximum", "20 characters, contains symbols.", //
|
||||||
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ),
|
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ),
|
||||||
@ -47,7 +47,7 @@ public enum MPResultType {
|
|||||||
MPResultTypeClass.Template, 0x0 ),
|
MPResultTypeClass.Template, 0x0 ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BiroYena8:Kixa
|
* 17: BiroYena8:Kixa
|
||||||
*/
|
*/
|
||||||
GeneratedLong( "long", "Copy-friendly, 14 characters, contains symbols.", //
|
GeneratedLong( "long", "Copy-friendly, 14 characters, contains symbols.", //
|
||||||
ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
|
ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
|
||||||
@ -64,7 +64,7 @@ public enum MPResultType {
|
|||||||
MPResultTypeClass.Template, 0x1 ),
|
MPResultTypeClass.Template, 0x1 ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BirSuj0-
|
* 18: BirSuj0-
|
||||||
*/
|
*/
|
||||||
GeneratedMedium( "medium", "Copy-friendly, 8 characters, contains symbols.", //
|
GeneratedMedium( "medium", "Copy-friendly, 8 characters, contains symbols.", //
|
||||||
ImmutableList.of( new MPTemplate( "CvcnoCvc" ),
|
ImmutableList.of( new MPTemplate( "CvcnoCvc" ),
|
||||||
@ -72,7 +72,14 @@ public enum MPResultType {
|
|||||||
MPResultTypeClass.Template, 0x2 ),
|
MPResultTypeClass.Template, 0x2 ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pO98MoD0
|
* 19: Bir8
|
||||||
|
*/
|
||||||
|
GeneratedShort( "short", "Copy-friendly, 4 characters, no symbols.", //
|
||||||
|
ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
|
||||||
|
MPResultTypeClass.Template, 0x4 ),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 20: pO98MoD0
|
||||||
*/
|
*/
|
||||||
GeneratedBasic( "basic", "8 characters, no symbols.", //
|
GeneratedBasic( "basic", "8 characters, no symbols.", //
|
||||||
ImmutableList.of( new MPTemplate( "aaanaaan" ),
|
ImmutableList.of( new MPTemplate( "aaanaaan" ),
|
||||||
@ -81,28 +88,21 @@ public enum MPResultType {
|
|||||||
MPResultTypeClass.Template, 0x3 ),
|
MPResultTypeClass.Template, 0x3 ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bir8
|
* 21: 2798
|
||||||
*/
|
|
||||||
GeneratedShort( "short", "Copy-friendly, 4 characters, no symbols.", //
|
|
||||||
ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
|
|
||||||
MPResultTypeClass.Template, 0x4 ),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2798
|
|
||||||
*/
|
*/
|
||||||
GeneratedPIN( "pin", "4 numbers.", //
|
GeneratedPIN( "pin", "4 numbers.", //
|
||||||
ImmutableList.of( new MPTemplate( "nnnn" ) ), //
|
ImmutableList.of( new MPTemplate( "nnnn" ) ), //
|
||||||
MPResultTypeClass.Template, 0x5 ),
|
MPResultTypeClass.Template, 0x5 ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* birsujano
|
* 30: birsujano
|
||||||
*/
|
*/
|
||||||
GeneratedName( "name", "9 letter name.", //
|
GeneratedName( "name", "9 letter name.", //
|
||||||
ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
|
ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
|
||||||
MPResultTypeClass.Template, 0xE ),
|
MPResultTypeClass.Template, 0xE ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bir yennoquce fefi
|
* 31: bir yennoquce fefi
|
||||||
*/
|
*/
|
||||||
GeneratedPhrase( "phrase", "20 character sentence.", //
|
GeneratedPhrase( "phrase", "20 character sentence.", //
|
||||||
ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ),
|
ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ),
|
||||||
@ -111,21 +111,21 @@ public enum MPResultType {
|
|||||||
MPResultTypeClass.Template, 0xF ),
|
MPResultTypeClass.Template, 0xF ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom saved password.
|
* 1056: Custom saved password.
|
||||||
*/
|
*/
|
||||||
StoredPersonal( "personal", "AES-encrypted, exportable.", //
|
StoredPersonal( "personal", "AES-encrypted, exportable.", //
|
||||||
ImmutableList.<MPTemplate>of(), //
|
ImmutableList.<MPTemplate>of(), //
|
||||||
MPResultTypeClass.Stateful, 0x0, MPSiteFeature.ExportContent ),
|
MPResultTypeClass.Stateful, 0x0, MPSiteFeature.ExportContent ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom saved password that should not be exported from the device.
|
* 2081: Custom saved password that should not be exported from the device.
|
||||||
*/
|
*/
|
||||||
StoredDevicePrivate( "device", "AES-encrypted, not exported.", //
|
StoredDevicePrivate( "device", "AES-encrypted, not exported.", //
|
||||||
ImmutableList.<MPTemplate>of(), //
|
ImmutableList.<MPTemplate>of(), //
|
||||||
MPResultTypeClass.Stateful, 0x1, MPSiteFeature.DevicePrivate ),
|
MPResultTypeClass.Stateful, 0x1, MPSiteFeature.DevicePrivate ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a unique binary key.
|
* 4160: Derive a unique binary key.
|
||||||
*/
|
*/
|
||||||
DeriveKey( "key", "Encryption key.", //
|
DeriveKey( "key", "Encryption key.", //
|
||||||
ImmutableList.<MPTemplate>of(), //
|
ImmutableList.<MPTemplate>of(), //
|
||||||
|
@ -27,7 +27,7 @@ import javax.annotation.Nullable;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 2018-05-14
|
* @author lhunath, 2018-05-14
|
||||||
*/
|
*/
|
||||||
public interface MPSite extends Comparable<MPSite> {
|
public interface MPSite<Q extends MPQuestion> extends Comparable<MPSite<Q>> {
|
||||||
|
|
||||||
// - Meta
|
// - Meta
|
||||||
|
|
||||||
@ -61,7 +61,11 @@ public interface MPSite extends Comparable<MPSite> {
|
|||||||
|
|
||||||
// - Relations
|
// - Relations
|
||||||
|
|
||||||
MPUser<? extends MPSite> getUser();
|
MPUser<? extends MPSite<?>> getUser();
|
||||||
|
|
||||||
Collection<? extends MPQuestion> getQuestions();
|
void addQuestion(Q question);
|
||||||
|
|
||||||
|
void deleteQuestion(Q question);
|
||||||
|
|
||||||
|
Collection<Q> getQuestions();
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 14-12-16
|
* @author lhunath, 14-12-16
|
||||||
*/
|
*/
|
||||||
public abstract class MPBasicSite implements MPSite {
|
public abstract class MPBasicSite<Q extends MPQuestion> implements MPSite<Q> {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private MPAlgorithm algorithm;
|
private MPAlgorithm algorithm;
|
||||||
@ -41,7 +41,7 @@ public abstract class MPBasicSite implements MPSite {
|
|||||||
private MPResultType resultType;
|
private MPResultType resultType;
|
||||||
private MPResultType loginType;
|
private MPResultType loginType;
|
||||||
|
|
||||||
private final Collection<MPFileQuestion> questions = new LinkedHashSet<>();
|
private final Collection<Q> questions = new LinkedHashSet<>();
|
||||||
|
|
||||||
protected MPBasicSite(final String name, final MPAlgorithm algorithm) {
|
protected MPBasicSite(final String name, final MPAlgorithm algorithm) {
|
||||||
this( name, algorithm, null, null, null );
|
this( name, algorithm, null, null, null );
|
||||||
@ -139,7 +139,17 @@ public abstract class MPBasicSite implements MPSite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<? extends MPQuestion> getQuestions() {
|
public void addQuestion(final Q question) {
|
||||||
|
questions.add( question );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteQuestion(final Q question) {
|
||||||
|
questions.remove( question );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Q> getQuestions() {
|
||||||
return Collections.unmodifiableCollection( questions );
|
return Collections.unmodifiableCollection( questions );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,11 +160,11 @@ public abstract class MPBasicSite implements MPSite {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(final Object obj) {
|
||||||
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getName(), ((MPSite) obj).getName() ));
|
return (this == obj) || ((obj instanceof MPSite) && Objects.equals( getName(), ((MPSite<?>) obj).getName() ));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull final MPSite o) {
|
public int compareTo(@NotNull final MPSite<Q> o) {
|
||||||
return getName().compareTo( o.getName() );
|
return getName().compareTo( o.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ package com.lyndir.masterpassword.model.impl;
|
|||||||
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.*;
|
import com.lyndir.masterpassword.*;
|
||||||
|
import com.lyndir.masterpassword.model.MPSite;
|
||||||
import com.lyndir.masterpassword.model.MPUser;
|
import com.lyndir.masterpassword.model.MPUser;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -30,7 +31,7 @@ import org.joda.time.ReadableInstant;
|
|||||||
/**
|
/**
|
||||||
* @author lhunath, 14-12-05
|
* @author lhunath, 14-12-05
|
||||||
*/
|
*/
|
||||||
public class MPFileSite extends MPBasicSite {
|
public class MPFileSite extends MPBasicSite<MPFileQuestion> {
|
||||||
|
|
||||||
private final MPFileUser user;
|
private final MPFileUser user;
|
||||||
|
|
||||||
@ -60,7 +61,8 @@ public class MPFileSite extends MPBasicSite {
|
|||||||
@Nullable final MPResultType resultType, @Nullable final String resultState,
|
@Nullable final MPResultType resultType, @Nullable final String resultState,
|
||||||
@Nullable final MPResultType loginType, @Nullable final String loginState,
|
@Nullable final MPResultType loginType, @Nullable final String loginState,
|
||||||
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
@Nullable final String url, final int uses, final ReadableInstant lastUsed) {
|
||||||
super( name, (algorithm == null)? user.getAlgorithm(): algorithm, counter, resultType, loginType );
|
super( name, (algorithm == null)? user.getAlgorithm(): algorithm, counter,
|
||||||
|
(resultType == null)? user.getDefaultType(): resultType, loginType );
|
||||||
|
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.resultState = resultState;
|
this.resultState = resultState;
|
||||||
@ -144,7 +146,7 @@ public class MPFileSite extends MPBasicSite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MPUser<? extends com.lyndir.masterpassword.model.MPSite> getUser() {
|
public MPFileUser getUser() {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,26 +191,27 @@ public class MPJSONFile extends MPJSONAnyObject {
|
|||||||
String full_name;
|
String full_name;
|
||||||
String last_used;
|
String last_used;
|
||||||
@Nullable
|
@Nullable
|
||||||
String key_id;
|
|
||||||
@Nullable
|
|
||||||
MPAlgorithm.Version algorithm;
|
MPAlgorithm.Version algorithm;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
String key_id;
|
||||||
|
@Nullable
|
||||||
MPResultType default_type;
|
MPResultType default_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Site extends MPJSONAnyObject {
|
public static class Site extends MPJSONAnyObject {
|
||||||
|
|
||||||
@Nullable
|
|
||||||
MPResultType type;
|
|
||||||
long counter;
|
long counter;
|
||||||
MPAlgorithm.Version algorithm;
|
MPAlgorithm.Version algorithm;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
MPResultType type;
|
||||||
|
@Nullable
|
||||||
String password;
|
String password;
|
||||||
@Nullable
|
@Nullable
|
||||||
String login_name;
|
|
||||||
@Nullable
|
|
||||||
MPResultType login_type;
|
MPResultType login_type;
|
||||||
|
@Nullable
|
||||||
|
String login_name;
|
||||||
|
|
||||||
int uses;
|
int uses;
|
||||||
@Nullable
|
@Nullable
|
||||||
String last_used;
|
String last_used;
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
//==============================================================================
|
||||||
|
// This file is part of Master Password.
|
||||||
|
// Copyright (c) 2011-2017, Maarten Billemont.
|
||||||
|
//
|
||||||
|
// Master Password is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Master Password is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You can find a copy of the GNU General Public License in the
|
||||||
|
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
package com.lyndir.masterpassword.gui.model;
|
||||||
|
|
||||||
|
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.ifNotNullElse;
|
||||||
|
|
||||||
|
import com.lyndir.masterpassword.MPResultType;
|
||||||
|
import com.lyndir.masterpassword.model.impl.MPBasicQuestion;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lhunath, 2018-05-16
|
||||||
|
*/
|
||||||
|
public class MPIncognitoQuestion extends MPBasicQuestion {
|
||||||
|
|
||||||
|
private final MPIncognitoSite site;
|
||||||
|
|
||||||
|
public MPIncognitoQuestion(final MPIncognitoSite site, final String keyword, @Nullable final MPResultType type) {
|
||||||
|
super( keyword, ifNotNullElse( type, site.getAlgorithm().mpw_default_answer_type() ) );
|
||||||
|
|
||||||
|
this.site = site;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public MPIncognitoSite getSite() {
|
||||||
|
return site;
|
||||||
|
}
|
||||||
|
}
|
@ -18,20 +18,17 @@
|
|||||||
|
|
||||||
package com.lyndir.masterpassword.gui.model;
|
package com.lyndir.masterpassword.gui.model;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
import com.lyndir.masterpassword.MPAlgorithm;
|
import com.lyndir.masterpassword.MPAlgorithm;
|
||||||
import com.lyndir.masterpassword.MPResultType;
|
import com.lyndir.masterpassword.MPResultType;
|
||||||
import com.lyndir.masterpassword.model.*;
|
|
||||||
import com.lyndir.masterpassword.model.impl.MPBasicSite;
|
import com.lyndir.masterpassword.model.impl.MPBasicSite;
|
||||||
import java.util.Collection;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author lhunath, 14-12-16
|
* @author lhunath, 14-12-16
|
||||||
*/
|
*/
|
||||||
public class MPIncognitoSite extends MPBasicSite {
|
public class MPIncognitoSite extends MPBasicSite<MPIncognitoQuestion> {
|
||||||
|
|
||||||
private final MPIncognitoUser user;
|
private final MPIncognitoUser user;
|
||||||
|
|
||||||
@ -48,12 +45,7 @@ public class MPIncognitoSite extends MPBasicSite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MPUser<? extends MPSite> getUser() {
|
public MPIncognitoUser getUser() {
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<MPQuestion> getQuestions() {
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user