2
0

Harmonize C/Java code more, WIP crypt/derive in Java.

This commit is contained in:
Maarten Billemont 2017-09-19 14:52:43 -04:00
parent 473e3ca11f
commit ad00ceb4ce
16 changed files with 207 additions and 73 deletions

View File

@ -180,7 +180,7 @@ static const char *mpw_sitePasswordFromCrypt_v0(
mpw_free( &plainBytes, bufSize ); mpw_free( &plainBytes, bufSize );
if (!plainText) if (!plainText)
err( "AES decryption error: %s\n", strerror( errno ) ); err( "AES decryption error: %s\n", strerror( errno ) );
trc( "decrypted -> plainText: %s = %s\n", plainText, mpw_hex( plainText, sizeof( plainText ) ) ); trc( "decrypted -> plainText: %s\n", plainText );
return plainText; return plainText;
} }
@ -217,7 +217,7 @@ static const char *mpw_sitePasswordFromDerive_v0(
mpw_free_string( &b64Key ); mpw_free_string( &b64Key );
} }
else else
trc( "b64 encoded -> key.id: %s\n", mpw_id_buf( b64Key, strlen( b64Key ) ) ); trc( "b64 encoded -> key: %s\n", b64Key );
mpw_free( &resultKey, keySize ); mpw_free( &resultKey, keySize );
return b64Key; return b64Key;
@ -248,7 +248,7 @@ static const char *mpw_siteState_v0(
mpw_free_string( &cipherText ); mpw_free_string( &cipherText );
} }
else else
trc( "b64 encoded -> cipherText: %s = %s\n", cipherText, mpw_hex( cipherText, sizeof( cipherText ) ) ); trc( "b64 encoded -> cipherText: %s\n", cipherText );
mpw_free( &cipherBuf, bufSize ); mpw_free( &cipherBuf, bufSize );
return cipherText; return cipherText;

View File

@ -18,12 +18,6 @@
package com.lyndir.masterpassword; package com.lyndir.masterpassword;
import com.google.common.base.Charsets;
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
import com.lyndir.lhunath.opal.system.MessageDigests;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
/** /**
* @author lhunath, 2016-10-29 * @author lhunath, 2016-10-29

View File

@ -18,9 +18,7 @@
package com.lyndir.masterpassword; package com.lyndir.masterpassword;
import com.google.common.collect.ImmutableList;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
@ -31,9 +29,18 @@ import org.jetbrains.annotations.NonNls;
* @author lhunath, 14-12-02 * @author lhunath, 14-12-02
*/ */
public enum MPKeyPurpose { public enum MPKeyPurpose {
Password( "authentication", "Generate a key for authentication.", "com.lyndir.masterpassword" ), /**
Login( "identification", "Generate a name for identification.", "com.lyndir.masterpassword.login" ), * Generate a key for authentication.
Answer( "recovery", "Generate an account recovery token.", "com.lyndir.masterpassword.answer" ); */
Authentication( "authentication", "Generate a key for authentication.", "com.lyndir.masterpassword" ),
/**
* Generate a name for identification.
*/
Identification( "identification", "Generate a name for identification.", "com.lyndir.masterpassword.login" ),
/**
* Generate a recovery token.
*/
Recovery( "recovery", "Generate a recovery token.", "com.lyndir.masterpassword.answer" );
static final Logger logger = Logger.get( MPResultType.class ); static final Logger logger = Logger.get( MPResultType.class );

View File

@ -32,11 +32,19 @@ import org.jetbrains.annotations.Contract;
* @author lhunath * @author lhunath
*/ */
public enum MPResultType { public enum MPResultType {
// bit 0-3 | MPResultTypeClass | MPSiteFeature
/**
* pg^VMAUBk5x3p%HP%i4=
*/
GeneratedMaximum( "Maximum", "20 characters, contains symbols.", // GeneratedMaximum( "Maximum", "20 characters, contains symbols.", //
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), // ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ),
MPResultTypeClass.Generated, 0x0 ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
MPResultTypeClass.Template, 0x0 ),
/**
* 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" ),
new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ),
@ -49,40 +57,77 @@ public enum MPResultType {
new MPTemplate( "CvcvCvccnoCvcc" ), new MPTemplate( "CvcvCvccCvccno" ), new MPTemplate( "CvcvCvccnoCvcc" ), new MPTemplate( "CvcvCvccCvccno" ),
new MPTemplate( "CvccnoCvcvCvcc" ), new MPTemplate( "CvccCvcvnoCvcc" ), new MPTemplate( "CvccnoCvcvCvcc" ), new MPTemplate( "CvccCvcvnoCvcc" ),
new MPTemplate( "CvccCvcvCvccno" ) ), // new MPTemplate( "CvccCvcvCvccno" ) ), //
MPResultTypeClass.Generated, 0x1 ), MPResultTypeClass.Template, 0x1 ),
/**
* BirSuj0-
*/
GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", // GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", //
ImmutableList.of( new MPTemplate( "CvcnoCvc" ), new MPTemplate( "CvcCvcno" ) ), // ImmutableList.of( new MPTemplate( "CvcnoCvc" ),
MPResultTypeClass.Generated, 0x2 ), new MPTemplate( "CvcCvcno" ) ), //
MPResultTypeClass.Template, 0x2 ),
/**
* pO98MoD0
*/
GeneratedBasic( "Basic", "8 characters, no symbols.", // GeneratedBasic( "Basic", "8 characters, no symbols.", //
ImmutableList.of( new MPTemplate( "aaanaaan" ), new MPTemplate( "aannaaan" ), new MPTemplate( "aaannaaa" ) ), // ImmutableList.of( new MPTemplate( "aaanaaan" ),
MPResultTypeClass.Generated, 0x3 ), new MPTemplate( "aannaaan" ),
new MPTemplate( "aaannaaa" ) ), //
MPResultTypeClass.Template, 0x3 ),
/**
* Bir8
*/
GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", // GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", //
ImmutableList.of( new MPTemplate( "Cvcn" ) ), // ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
MPResultTypeClass.Generated, 0x4 ), MPResultTypeClass.Template, 0x4 ),
/**
* 2798
*/
GeneratedPIN( "PIN", "4 numbers.", // GeneratedPIN( "PIN", "4 numbers.", //
ImmutableList.of( new MPTemplate( "nnnn" ) ), // ImmutableList.of( new MPTemplate( "nnnn" ) ), //
MPResultTypeClass.Generated, 0x5 ), MPResultTypeClass.Template, 0x5 ),
/**
* birsujano
*/
GeneratedName( "Name", "9 letter name.", // GeneratedName( "Name", "9 letter name.", //
ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), // ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
MPResultTypeClass.Generated, 0xE ), MPResultTypeClass.Template, 0xE ),
/**
* bir yennoquce fefi
*/
GeneratedPhrase( "Phrase", "20 character sentence.", // GeneratedPhrase( "Phrase", "20 character sentence.", //
ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ), new MPTemplate( "cvc cvccvcvcv cvcv" ), ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ),
new MPTemplate( "cvc cvccvcvcv cvcv" ),
new MPTemplate( "cv cvccv cvc cvcvccv" ) ), // new MPTemplate( "cv cvccv cvc cvcvccv" ) ), //
MPResultTypeClass.Generated, 0xF ), MPResultTypeClass.Template, 0xF ),
/**
* Custom saved password.
*/
StoredPersonal( "Personal", "AES-encrypted, exportable.", // StoredPersonal( "Personal", "AES-encrypted, exportable.", //
ImmutableList.<MPTemplate>of(), // ImmutableList.<MPTemplate>of(), //
MPResultTypeClass.Stored, 0x0, MPSiteFeature.ExportContent ), MPResultTypeClass.Stateful, 0x0, MPSiteFeature.ExportContent ),
/**
* 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.Stored, 0x1, MPSiteFeature.DevicePrivate ); MPResultTypeClass.Stateful, 0x1, MPSiteFeature.DevicePrivate ),
/**
* Derive a unique binary key.
*/
DeriveKey( "Key", "Encryption key.", //
ImmutableList.<MPTemplate>of(), //
MPResultTypeClass.Derive, 0x0, MPSiteFeature.Alternative );
public static MPResultType DEFAULT = GeneratedLong;
static final Logger logger = Logger.get( MPResultType.class ); static final Logger logger = Logger.get( MPResultType.class );
@ -185,13 +230,14 @@ public enum MPResultType {
} }
/** /**
* @param mask The mask for which we look up types. * @param mask The type mask for which we look up types.
* *
* @return All types that support the given mask. * @return All types that support the given mask's class & features.
*/ */
public static ImmutableList<MPResultType> forMask(final int mask) { public static ImmutableList<MPResultType> forMask(final int mask) {
int typeMask = mask & ~0xF; int typeMask = mask & ~0xF; // Ignore resultType bit 0-3
ImmutableList.Builder<MPResultType> types = ImmutableList.builder(); ImmutableList.Builder<MPResultType> types = ImmutableList.builder();
for (final MPResultType resultType : values()) for (final MPResultType resultType : values())
if (((resultType.getType() & ~0xF) & typeMask) != 0) if (((resultType.getType() & ~0xF) & typeMask) != 0)

View File

@ -24,8 +24,20 @@ package com.lyndir.masterpassword;
* @author lhunath * @author lhunath
*/ */
public enum MPResultTypeClass { public enum MPResultTypeClass {
Generated( 1 << 4 ), // bit 4 - 9
Stored( 1 << 5 );
/**
* Use the site key to generate a password from a template.
*/
Template( 1 << 4 ),
/**
* Use the site key to encrypt and decrypt a stateful entity.
*/
Stateful( 1 << 5 ),
/**
* Use the site key to derive a site-specific object.
*/
Derive( 1 << 6 );
private final int mask; private final int mask;

View File

@ -24,6 +24,7 @@ package com.lyndir.masterpassword;
* @author lhunath * @author lhunath
*/ */
public enum MPSiteFeature { public enum MPSiteFeature {
// bit 10 - 15
/** /**
* Export the key-protected content data. * Export the key-protected content data.
@ -33,7 +34,12 @@ public enum MPSiteFeature {
/** /**
* Never export content. * Never export content.
*/ */
DevicePrivate( 1 << 11 ); DevicePrivate( 1 << 11 ),
/**
* Don't use this as the primary authentication result type.
*/
Alternative( 1 << 12 );
MPSiteFeature(final int mask) { MPSiteFeature(final int mask) {
this.mask = mask; this.mask = mask;

View File

@ -127,6 +127,12 @@ public abstract class MasterKey {
public abstract String siteResult(String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose, public abstract String siteResult(String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext, MPResultType resultType, @Nullable String resultParam); @Nullable String keyContext, MPResultType resultType, @Nullable String resultParam);
protected abstract String sitePasswordFromTemplate(byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
protected abstract String sitePasswordFromCrypt(byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
protected abstract String sitePasswordFromDerive(byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
/** /**
* Encrypt a stateful site token for persistence. * Encrypt a stateful site token for persistence.
* *

View File

@ -25,11 +25,13 @@ import com.lambdaworks.crypto.SCrypt;
import com.lyndir.lhunath.opal.crypto.CryptUtils; import com.lyndir.lhunath.opal.crypto.CryptUtils;
import com.lyndir.lhunath.opal.system.*; import com.lyndir.lhunath.opal.system.*;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
import java.nio.*; import java.nio.*;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Arrays; import java.util.Arrays;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
@ -79,7 +81,6 @@ public class MasterKeyV0 extends MasterKey {
* scrypt: CPU cost parameter. * scrypt: CPU cost parameter.
*/ */
protected static final int scrypt_N = 32768; protected static final int scrypt_N = 32768;
private static final int MP_intLen = 32;
@SuppressWarnings("UnusedDeclaration") @SuppressWarnings("UnusedDeclaration")
private static final Logger logger = Logger.get( MasterKeyV0.class ); private static final Logger logger = Logger.get( MasterKeyV0.class );
@ -108,7 +109,7 @@ public class MasterKeyV0 extends MasterKey {
logger.trc( "fullName: %s", fullName ); logger.trc( "fullName: %s", fullName );
logger.trc( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) ); logger.trc( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) );
String keyScope = MPKeyPurpose.Password.getScope(); String keyScope = MPKeyPurpose.Authentication.getScope();
logger.trc( "keyScope: %s", keyScope ); logger.trc( "keyScope: %s", keyScope );
// Calculate the master key salt. // Calculate the master key salt.
@ -191,33 +192,49 @@ public class MasterKeyV0 extends MasterKey {
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) { @Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) {
byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext ); byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext );
int[] sitePasswordSeed = new int[siteKey.length];
for (int i = 0; i < siteKey.length; ++i) {
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
Arrays.fill( buf.array(), (byte) ((siteKey[i] > 0)? 0x00: 0xFF) );
buf.position( 2 );
buf.put( siteKey[i] ).rewind();
sitePasswordSeed[i] = buf.getInt() & 0xFFFF;
}
logger.trc( "-- mpw_siteResult (algorithm: %u)", getAlgorithmVersion().toInt() ); logger.trc( "-- mpw_siteResult (algorithm: %u)", getAlgorithmVersion().toInt() );
logger.trc( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() ); logger.trc( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() );
logger.trc( "resultParam: %s", resultParam ); logger.trc( "resultParam: %s", resultParam );
switch (resultType.getTypeClass()) {
case Template:
return sitePasswordFromTemplate( siteKey, resultType, resultParam );
case Stateful:
return sitePasswordFromCrypt( siteKey, resultType, resultParam );
case Derive:
return sitePasswordFromDerive( siteKey, resultType, resultParam );
}
throw logger.bug( "Unsupported result type class: %s", resultType.getTypeClass() );
}
@Override
protected String sitePasswordFromTemplate(final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) {
int[] _siteKey = new int[siteKey.length];
for (int i = 0; i < siteKey.length; ++i) {
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder );
Arrays.fill( buf.array(), (byte) ((siteKey[i] > 0)? 0x00: 0xFF) );
buf.position( 2 );
buf.put( siteKey[i] ).rewind();
_siteKey[i] = buf.getInt() & 0xFFFF;
}
// Determine the template. // Determine the template.
Preconditions.checkState( sitePasswordSeed.length > 0 ); Preconditions.checkState( _siteKey.length > 0 );
int templateIndex = sitePasswordSeed[0]; int templateIndex = _siteKey[0];
MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex ); MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex );
logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() ); logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() );
// Encode the password from the seed using the template. // Encode the password from the seed using the template.
StringBuilder password = new StringBuilder( template.length() ); StringBuilder password = new StringBuilder( template.length() );
for (int i = 0; i < template.length(); ++i) { for (int i = 0; i < template.length(); ++i) {
int characterIndex = sitePasswordSeed[i + 1]; int characterIndex = _siteKey[i + 1];
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i ); MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex ); char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
logger.trc( " - class: %c, index: %5u (0x%02hX) => character: %c", logger.trc( " - class: %c, index: %5u (0x%02hX) => character: %c",
characterClass.getIdentifier(), characterIndex, sitePasswordSeed[i + 1], passwordCharacter ); characterClass.getIdentifier(), characterIndex, _siteKey[i + 1], passwordCharacter );
password.append( passwordCharacter ); password.append( passwordCharacter );
} }
@ -226,6 +243,58 @@ public class MasterKeyV0 extends MasterKey {
return password.toString(); return password.toString();
} }
@Override
protected String sitePasswordFromCrypt(final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) {
Preconditions.checkNotNull( resultParam );
Preconditions.checkArgument( !resultParam.isEmpty() );
try {
// Base64-decode
byte[] cipherBuf = CryptUtils.decodeBase64( resultParam );
logger.trc( "b64 decoded: %zu bytes = %s", cipherBuf.length, CodeUtils.encodeHex( cipherBuf ) );
// Decrypt
byte[] plainBuf = CryptUtils.decrypt( cipherBuf, getKey(), true );
String plainText = mpw_charset.decode( ByteBuffer.wrap( plainBuf ) ).toString();
logger.trc( "decrypted -> plainText: %s", plainText );
return plainText;
}
catch (final BadPaddingException e) {
throw Throwables.propagate( e );
}
}
@Override
protected String sitePasswordFromDerive(final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) {
if (resultType == MPResultType.DeriveKey) {
Preconditions.checkNotNull( resultParam );
Preconditions.checkArgument( !resultParam.isEmpty() );
int resultParamInt = ConversionUtils.toIntegerNN( resultParam );
if ((resultParamInt < 128) || (resultParamInt > 512) || ((resultParamInt % 8) != 0))
throw logger.bug( "Parameter is not a valid key size (should be 128 - 512): %s", resultParam );
int keySize = resultParamInt / 8;
logger.trc( "keySize: %u", keySize );
// Derive key
byte[] resultKey = null; // TODO: mpw_kdf_blake2b( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL );
if (resultKey == null)
throw logger.bug( "Could not derive result key." );
// Base64-encode
String b64Key = Verify.verifyNotNull( CryptUtils.encodeBase64( resultKey ) );
logger.trc( "b64 encoded -> key: %s", b64Key );
return b64Key;
}
else
throw logger.bug( "Unsupported derived password type: %s", resultType );
}
@Override @Override
public String siteState(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, public String siteState(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) { @Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) {
@ -252,12 +321,12 @@ public class MasterKeyV0 extends MasterKey {
@Override @Override
protected byte[] bytesForInt(final int number) { protected byte[] bytesForInt(final int number) {
return ByteBuffer.allocate( MP_intLen / Byte.SIZE ).order( mpw_byteOrder ).putInt( number ).array(); return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder ).putInt( number ).array();
} }
@Override @Override
protected byte[] bytesForInt(final UnsignedInteger number) { protected byte[] bytesForInt(final UnsignedInteger number) {
return ByteBuffer.allocate( MP_intLen / Byte.SIZE ).order( mpw_byteOrder ).putInt( number.intValue() ).array(); return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder ).putInt( number.intValue() ).array();
} }
@Override @Override

View File

@ -19,9 +19,7 @@
package com.lyndir.masterpassword; package com.lyndir.masterpassword;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.UnsignedInteger; import com.google.common.primitives.UnsignedInteger;
import com.lyndir.lhunath.opal.system.*;
import com.lyndir.lhunath.opal.system.logging.Logger; import com.lyndir.lhunath.opal.system.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -49,29 +47,26 @@ public class MasterKeyV1 extends MasterKeyV0 {
} }
@Override @Override
public String siteResult(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose, protected String sitePasswordFromTemplate(final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) {
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) {
byte[] sitePasswordSeed = siteKey( siteName, siteCounter, keyPurpose, keyContext );
logger.trc( "-- mpw_siteResult (algorithm: %u)", getAlgorithmVersion().toInt() ); logger.trc( "-- mpw_siteResult (algorithm: %u)", getAlgorithmVersion().toInt() );
logger.trc( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() ); logger.trc( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() );
logger.trc( "resultParam: %s", resultParam ); logger.trc( "resultParam: %s", resultParam );
// Determine the template. // Determine the template.
Preconditions.checkState( sitePasswordSeed.length > 0 ); Preconditions.checkState( siteKey.length > 0 );
int templateIndex = sitePasswordSeed[0] & 0xFF; // Mask the integer's sign. int templateIndex = siteKey[0] & 0xFF; // Convert to unsigned int.
MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex ); MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex );
logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() ); logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() );
// Encode the password from the seed using the template. // Encode the password from the seed using the template.
StringBuilder password = new StringBuilder( template.length() ); StringBuilder password = new StringBuilder( template.length() );
for (int i = 0; i < template.length(); ++i) { for (int i = 0; i < template.length(); ++i) {
int characterIndex = sitePasswordSeed[i + 1] & 0xFF; // Mask the integer's sign. int characterIndex = siteKey[i + 1] & 0xFF; // Convert to unsigned int.
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i ); MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex ); char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
logger.trc( " - class: %c, index: %3u (0x%02hhX) => character: %c", logger.trc( " - class: %c, index: %3u (0x%02hhX) => character: %c",
characterClass.getIdentifier(), characterIndex, sitePasswordSeed[i + 1], passwordCharacter ); characterClass.getIdentifier(), characterIndex, siteKey[i + 1], passwordCharacter );
password.append( passwordCharacter ); password.append( passwordCharacter );
} }

View File

@ -63,7 +63,7 @@ public class MasterKeyV3 extends MasterKeyV2 {
logger.trc( "fullName: %s", fullName ); logger.trc( "fullName: %s", fullName );
logger.trc( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) ); logger.trc( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) );
String keyScope = MPKeyPurpose.Password.getScope(); String keyScope = MPKeyPurpose.Authentication.getScope();
logger.trc( "keyScope: %s", keyScope ); logger.trc( "keyScope: %s", keyScope );
// Calculate the master key salt. // Calculate the master key salt.

View File

@ -14,7 +14,6 @@ import org.joda.time.Instant;
*/ */
public class MPSite { public class MPSite {
public static final MPResultType DEFAULT_TYPE = MPResultType.GeneratedLong;
public static final UnsignedInteger DEFAULT_COUNTER = UnsignedInteger.valueOf( 1 ); public static final UnsignedInteger DEFAULT_COUNTER = UnsignedInteger.valueOf( 1 );
private final MPUser user; private final MPUser user;
@ -27,7 +26,7 @@ public class MPSite {
private String loginName; private String loginName;
public MPSite(final MPUser user, final String siteName) { public MPSite(final MPUser user, final String siteName) {
this( user, siteName, DEFAULT_COUNTER, DEFAULT_TYPE ); this( user, siteName, DEFAULT_COUNTER, MPResultType.DEFAULT );
} }
public MPSite(final MPUser user, final String siteName, final UnsignedInteger siteCounter, final MPResultType resultType) { public MPSite(final MPUser user, final String siteName, final UnsignedInteger siteCounter, final MPResultType resultType) {
@ -53,7 +52,7 @@ public class MPSite {
} }
public String resultFor(final MasterKey masterKey) { public String resultFor(final MasterKey masterKey) {
return resultFor( masterKey, MPKeyPurpose.Password, null ); return resultFor( masterKey, MPKeyPurpose.Authentication, null );
} }
public String resultFor(final MasterKey masterKey, final MPKeyPurpose purpose, @Nullable final String context) { public String resultFor(final MasterKey masterKey, final MPKeyPurpose purpose, @Nullable final String context) {

View File

@ -58,7 +58,7 @@ public class MPSiteUnmarshaller {
String fullName = null; String fullName = null;
int mpVersion = 0, importFormat = 0, avatar = 0; int mpVersion = 0, importFormat = 0, avatar = 0;
boolean clearContent = false, headerStarted = false; boolean clearContent = false, headerStarted = false;
MPResultType defaultType = MPResultType.GeneratedLong; MPResultType defaultType = MPResultType.DEFAULT;
MPSiteUnmarshaller marshaller = null; MPSiteUnmarshaller marshaller = null;
final ImmutableList.Builder<MPSite> sites = ImmutableList.builder(); final ImmutableList.Builder<MPSite> sites = ImmutableList.builder();

View File

@ -33,7 +33,7 @@ public class MPUser implements Comparable<MPUser> {
} }
public MPUser(final String fullName, @Nullable final byte[] keyID) { public MPUser(final String fullName, @Nullable final byte[] keyID) {
this( fullName, keyID, MasterKey.Version.CURRENT, 0, MPResultType.GeneratedLong, new DateTime() ); this( fullName, keyID, MasterKey.Version.CURRENT, 0, MPResultType.DEFAULT, new DateTime() );
} }
public MPUser(final String fullName, @Nullable final byte[] keyID, final MasterKey.Version algorithmVersion, final int avatar, public MPUser(final String fullName, @Nullable final byte[] keyID, final MasterKey.Version algorithmVersion, final int avatar,

View File

@ -54,7 +54,7 @@ public class EmergencyActivity extends Activity {
private final Preferences preferences = Preferences.get( this ); private final Preferences preferences = Preferences.get( this );
private final ListeningExecutorService executor = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() ); private final ListeningExecutorService executor = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() );
private final ImmutableList<MPResultType> allResultTypes = ImmutableList.copyOf( MPResultType.forClass( MPResultTypeClass.Generated ) ); private final ImmutableList<MPResultType> allResultTypes = ImmutableList.copyOf( MPResultType.forClass( MPResultTypeClass.Template ) );
private final ImmutableList<MasterKey.Version> allVersions = ImmutableList.copyOf( MasterKey.Version.values() ); private final ImmutableList<MasterKey.Version> allVersions = ImmutableList.copyOf( MasterKey.Version.values() );
private ListenableFuture<MasterKey> masterKeyFuture; private ListenableFuture<MasterKey> masterKeyFuture;
@ -332,7 +332,7 @@ public class EmergencyActivity extends Activity {
@Override @Override
public void run() { public void run() {
try { try {
sitePassword = masterKeyFuture.get().siteResult( siteName, counter, MPKeyPurpose.Password, null, type, null ); sitePassword = masterKeyFuture.get().siteResult( siteName, counter, MPKeyPurpose.Authentication, null, type, null );
runOnUiThread( new Runnable() { runOnUiThread( new Runnable() {
@Override @Override

View File

@ -148,7 +148,7 @@ public final class Preferences {
@Nonnull @Nonnull
public MPResultType getDefaultResultType() { public MPResultType getDefaultResultType() {
return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, MPResultType.GeneratedLong.ordinal() )]; return MPResultType.values()[prefs().getInt( PREF_RESULT_TYPE, MPResultType.DEFAULT.ordinal() )];
} }
public boolean setDefaultVersion(final MasterKey.Version value) { public boolean setDefaultVersion(final MasterKey.Version value) {

View File

@ -118,7 +118,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
// Site Type & Counter // Site Type & Counter
siteCounterModel = new UnsignedIntegerModel( UnsignedInteger.ONE, UnsignedInteger.ONE ); siteCounterModel = new UnsignedIntegerModel( UnsignedInteger.ONE, UnsignedInteger.ONE );
MPResultType[] types = Iterables.toArray( MPResultType.forClass( MPResultTypeClass.Generated ), MPResultType.class ); MPResultType[] types = Iterables.toArray( MPResultType.forClass( MPResultTypeClass.Template ), MPResultType.class );
JComponent siteSettings = Components.boxLayout( BoxLayout.LINE_AXIS, // JComponent siteSettings = Components.boxLayout( BoxLayout.LINE_AXIS, //
resultTypeField = Components.comboBox( types ), // resultTypeField = Components.comboBox( types ), //
Components.stud(), // Components.stud(), //
@ -127,7 +127,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
siteCounterField = Components.spinner( siteCounterModel ) ); siteCounterField = Components.spinner( siteCounterModel ) );
sitePanel.add( siteSettings ); sitePanel.add( siteSettings );
resultTypeField.setFont( Res.valueFont().deriveFont( 12f ) ); resultTypeField.setFont( Res.valueFont().deriveFont( 12f ) );
resultTypeField.setSelectedItem( MPResultType.GeneratedLong ); resultTypeField.setSelectedItem( MPResultType.DEFAULT );
resultTypeField.addItemListener( new ItemListener() { resultTypeField.addItemListener( new ItemListener() {
@Override @Override
public void itemStateChanged(final ItemEvent e) { public void itemStateChanged(final ItemEvent e) {
@ -240,7 +240,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
public String call() public String call()
throws Exception { throws Exception {
return user.getKey( site.getAlgorithmVersion() ) return user.getKey( site.getAlgorithmVersion() )
.siteResult( site.getSiteName(), site.getSiteCounter(), MPKeyPurpose.Password, null, site.getResultType(), null ); .siteResult( site.getSiteName(), site.getSiteCounter(), MPKeyPurpose.Authentication, null, site.getResultType(), null );
} }
} ); } );
Futures.addCallback( passwordFuture, new FutureCallback<String>() { Futures.addCallback( passwordFuture, new FutureCallback<String>() {