Harmonize C/Java code more, WIP crypt/derive in Java.
This commit is contained in:
parent
473e3ca11f
commit
ad00ceb4ce
@ -180,7 +180,7 @@ static const char *mpw_sitePasswordFromCrypt_v0(
|
||||
mpw_free( &plainBytes, bufSize );
|
||||
if (!plainText)
|
||||
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;
|
||||
}
|
||||
@ -217,7 +217,7 @@ static const char *mpw_sitePasswordFromDerive_v0(
|
||||
mpw_free_string( &b64Key );
|
||||
}
|
||||
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 );
|
||||
|
||||
return b64Key;
|
||||
@ -248,7 +248,7 @@ static const char *mpw_siteState_v0(
|
||||
mpw_free_string( &cipherText );
|
||||
}
|
||||
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 );
|
||||
|
||||
return cipherText;
|
||||
|
@ -18,12 +18,6 @@
|
||||
|
||||
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
|
||||
|
@ -18,9 +18,7 @@
|
||||
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.Nullable;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@ -31,9 +29,18 @@ import org.jetbrains.annotations.NonNls;
|
||||
* @author lhunath, 14-12-02
|
||||
*/
|
||||
public enum MPKeyPurpose {
|
||||
Password( "authentication", "Generate a key for authentication.", "com.lyndir.masterpassword" ),
|
||||
Login( "identification", "Generate a name for identification.", "com.lyndir.masterpassword.login" ),
|
||||
Answer( "recovery", "Generate an account recovery token.", "com.lyndir.masterpassword.answer" );
|
||||
/**
|
||||
* Generate a key for authentication.
|
||||
*/
|
||||
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 );
|
||||
|
||||
|
@ -32,11 +32,19 @@ import org.jetbrains.annotations.Contract;
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPResultType {
|
||||
// bit 0-3 | MPResultTypeClass | MPSiteFeature
|
||||
|
||||
/**
|
||||
* pg^VMAUBk5x3p%HP%i4=
|
||||
*/
|
||||
GeneratedMaximum( "Maximum", "20 characters, contains symbols.", //
|
||||
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
|
||||
MPResultTypeClass.Generated, 0x0 ),
|
||||
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ),
|
||||
new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
|
||||
MPResultTypeClass.Template, 0x0 ),
|
||||
|
||||
/**
|
||||
* BiroYena8:Kixa
|
||||
*/
|
||||
GeneratedLong( "Long", "Copy-friendly, 14 characters, contains symbols.", //
|
||||
ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
|
||||
new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ),
|
||||
@ -49,40 +57,77 @@ public enum MPResultType {
|
||||
new MPTemplate( "CvcvCvccnoCvcc" ), new MPTemplate( "CvcvCvccCvccno" ),
|
||||
new MPTemplate( "CvccnoCvcvCvcc" ), new MPTemplate( "CvccCvcvnoCvcc" ),
|
||||
new MPTemplate( "CvccCvcvCvccno" ) ), //
|
||||
MPResultTypeClass.Generated, 0x1 ),
|
||||
MPResultTypeClass.Template, 0x1 ),
|
||||
|
||||
/**
|
||||
* BirSuj0-
|
||||
*/
|
||||
GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", //
|
||||
ImmutableList.of( new MPTemplate( "CvcnoCvc" ), new MPTemplate( "CvcCvcno" ) ), //
|
||||
MPResultTypeClass.Generated, 0x2 ),
|
||||
ImmutableList.of( new MPTemplate( "CvcnoCvc" ),
|
||||
new MPTemplate( "CvcCvcno" ) ), //
|
||||
MPResultTypeClass.Template, 0x2 ),
|
||||
|
||||
/**
|
||||
* pO98MoD0
|
||||
*/
|
||||
GeneratedBasic( "Basic", "8 characters, no symbols.", //
|
||||
ImmutableList.of( new MPTemplate( "aaanaaan" ), new MPTemplate( "aannaaan" ), new MPTemplate( "aaannaaa" ) ), //
|
||||
MPResultTypeClass.Generated, 0x3 ),
|
||||
ImmutableList.of( new MPTemplate( "aaanaaan" ),
|
||||
new MPTemplate( "aannaaan" ),
|
||||
new MPTemplate( "aaannaaa" ) ), //
|
||||
MPResultTypeClass.Template, 0x3 ),
|
||||
|
||||
/**
|
||||
* Bir8
|
||||
*/
|
||||
GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", //
|
||||
ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
|
||||
MPResultTypeClass.Generated, 0x4 ),
|
||||
MPResultTypeClass.Template, 0x4 ),
|
||||
|
||||
/**
|
||||
* 2798
|
||||
*/
|
||||
GeneratedPIN( "PIN", "4 numbers.", //
|
||||
ImmutableList.of( new MPTemplate( "nnnn" ) ), //
|
||||
MPResultTypeClass.Generated, 0x5 ),
|
||||
MPResultTypeClass.Template, 0x5 ),
|
||||
|
||||
/**
|
||||
* birsujano
|
||||
*/
|
||||
GeneratedName( "Name", "9 letter name.", //
|
||||
ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
|
||||
MPResultTypeClass.Generated, 0xE ),
|
||||
MPResultTypeClass.Template, 0xE ),
|
||||
|
||||
/**
|
||||
* bir yennoquce fefi
|
||||
*/
|
||||
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" ) ), //
|
||||
MPResultTypeClass.Generated, 0xF ),
|
||||
MPResultTypeClass.Template, 0xF ),
|
||||
|
||||
/**
|
||||
* Custom saved password.
|
||||
*/
|
||||
StoredPersonal( "Personal", "AES-encrypted, exportable.", //
|
||||
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.", //
|
||||
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 );
|
||||
|
||||
@ -185,14 +230,15 @@ 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) {
|
||||
|
||||
int typeMask = mask & ~0xF;
|
||||
ImmutableList.Builder<MPResultType> types = ImmutableList.builder();
|
||||
int typeMask = mask & ~0xF; // Ignore resultType bit 0-3
|
||||
|
||||
ImmutableList.Builder<MPResultType> types = ImmutableList.builder();
|
||||
for (final MPResultType resultType : values())
|
||||
if (((resultType.getType() & ~0xF) & typeMask) != 0)
|
||||
types.add( resultType );
|
||||
|
@ -24,8 +24,20 @@ package com.lyndir.masterpassword;
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPResultTypeClass {
|
||||
Generated( 1 << 4 ),
|
||||
Stored( 1 << 5 );
|
||||
// bit 4 - 9
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
@ -24,6 +24,7 @@ package com.lyndir.masterpassword;
|
||||
* @author lhunath
|
||||
*/
|
||||
public enum MPSiteFeature {
|
||||
// bit 10 - 15
|
||||
|
||||
/**
|
||||
* Export the key-protected content data.
|
||||
@ -33,7 +34,12 @@ public enum MPSiteFeature {
|
||||
/**
|
||||
* 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) {
|
||||
this.mask = mask;
|
||||
|
@ -127,6 +127,12 @@ public abstract class MasterKey {
|
||||
public abstract String siteResult(String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
|
||||
@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.
|
||||
*
|
||||
|
@ -25,11 +25,13 @@ 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 com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||
import java.nio.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Arrays;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
|
||||
|
||||
@ -79,7 +81,6 @@ public class MasterKeyV0 extends MasterKey {
|
||||
* scrypt: CPU cost parameter.
|
||||
*/
|
||||
protected static final int scrypt_N = 32768;
|
||||
private static final int MP_intLen = 32;
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
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( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) );
|
||||
|
||||
String keyScope = MPKeyPurpose.Password.getScope();
|
||||
String keyScope = MPKeyPurpose.Authentication.getScope();
|
||||
logger.trc( "keyScope: %s", keyScope );
|
||||
|
||||
// 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) {
|
||||
|
||||
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( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() );
|
||||
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.
|
||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||
int templateIndex = sitePasswordSeed[0];
|
||||
Preconditions.checkState( _siteKey.length > 0 );
|
||||
int templateIndex = _siteKey[0];
|
||||
MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex );
|
||||
logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() );
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
StringBuilder password = new StringBuilder( template.length() );
|
||||
for (int i = 0; i < template.length(); ++i) {
|
||||
int characterIndex = sitePasswordSeed[i + 1];
|
||||
int characterIndex = _siteKey[i + 1];
|
||||
MPTemplateCharacterClass characterClass = template.getCharacterClassAtIndex( i );
|
||||
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
|
||||
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 );
|
||||
}
|
||||
@ -226,6 +243,58 @@ public class MasterKeyV0 extends MasterKey {
|
||||
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
|
||||
public String siteState(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
|
||||
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) {
|
||||
@ -252,12 +321,12 @@ public class MasterKeyV0 extends MasterKey {
|
||||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
|
@ -19,9 +19,7 @@
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.UnsignedInteger;
|
||||
import com.lyndir.lhunath.opal.system.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -49,29 +47,26 @@ public class MasterKeyV1 extends MasterKeyV0 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String siteResult(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
|
||||
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam) {
|
||||
|
||||
byte[] sitePasswordSeed = siteKey( siteName, siteCounter, keyPurpose, keyContext );
|
||||
protected String sitePasswordFromTemplate(final byte[] siteKey, final MPResultType resultType, @Nullable final String resultParam) {
|
||||
|
||||
logger.trc( "-- mpw_siteResult (algorithm: %u)", getAlgorithmVersion().toInt() );
|
||||
logger.trc( "resultType: %d (%s)", resultType.toInt(), resultType.getShortName() );
|
||||
logger.trc( "resultParam: %s", resultParam );
|
||||
|
||||
// Determine the template.
|
||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||
int templateIndex = sitePasswordSeed[0] & 0xFF; // Mask the integer's sign.
|
||||
Preconditions.checkState( siteKey.length > 0 );
|
||||
int templateIndex = siteKey[0] & 0xFF; // Convert to unsigned int.
|
||||
MPTemplate template = resultType.getTemplateAtRollingIndex( templateIndex );
|
||||
logger.trc( "template: %u => %s", templateIndex, template.getTemplateString() );
|
||||
|
||||
// Encode the password from the seed using the template.
|
||||
StringBuilder password = new StringBuilder( template.length() );
|
||||
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 );
|
||||
char passwordCharacter = characterClass.getCharacterAtRollingIndex( characterIndex );
|
||||
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 );
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class MasterKeyV3 extends MasterKeyV2 {
|
||||
logger.trc( "fullName: %s", fullName );
|
||||
logger.trc( "masterPassword.id: %s", (Object) idForBytes( mpBytesBuf.array() ) );
|
||||
|
||||
String keyScope = MPKeyPurpose.Password.getScope();
|
||||
String keyScope = MPKeyPurpose.Authentication.getScope();
|
||||
logger.trc( "keyScope: %s", keyScope );
|
||||
|
||||
// Calculate the master key salt.
|
||||
|
@ -14,7 +14,6 @@ import org.joda.time.Instant;
|
||||
*/
|
||||
public class MPSite {
|
||||
|
||||
public static final MPResultType DEFAULT_TYPE = MPResultType.GeneratedLong;
|
||||
public static final UnsignedInteger DEFAULT_COUNTER = UnsignedInteger.valueOf( 1 );
|
||||
|
||||
private final MPUser user;
|
||||
@ -27,7 +26,7 @@ public class MPSite {
|
||||
private String loginName;
|
||||
|
||||
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) {
|
||||
@ -53,7 +52,7 @@ public class MPSite {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -58,7 +58,7 @@ public class MPSiteUnmarshaller {
|
||||
String fullName = null;
|
||||
int mpVersion = 0, importFormat = 0, avatar = 0;
|
||||
boolean clearContent = false, headerStarted = false;
|
||||
MPResultType defaultType = MPResultType.GeneratedLong;
|
||||
MPResultType defaultType = MPResultType.DEFAULT;
|
||||
MPSiteUnmarshaller marshaller = null;
|
||||
final ImmutableList.Builder<MPSite> sites = ImmutableList.builder();
|
||||
|
||||
|
@ -33,7 +33,7 @@ public class MPUser implements Comparable<MPUser> {
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -54,7 +54,7 @@ public class EmergencyActivity extends Activity {
|
||||
|
||||
private final Preferences preferences = Preferences.get( this );
|
||||
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 ListenableFuture<MasterKey> masterKeyFuture;
|
||||
@ -332,7 +332,7 @@ public class EmergencyActivity extends Activity {
|
||||
@Override
|
||||
public void run() {
|
||||
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() {
|
||||
@Override
|
||||
|
@ -148,7 +148,7 @@ public final class Preferences {
|
||||
|
||||
@Nonnull
|
||||
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) {
|
||||
|
@ -118,7 +118,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
|
||||
// Site Type & Counter
|
||||
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, //
|
||||
resultTypeField = Components.comboBox( types ), //
|
||||
Components.stud(), //
|
||||
@ -127,7 +127,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
siteCounterField = Components.spinner( siteCounterModel ) );
|
||||
sitePanel.add( siteSettings );
|
||||
resultTypeField.setFont( Res.valueFont().deriveFont( 12f ) );
|
||||
resultTypeField.setSelectedItem( MPResultType.GeneratedLong );
|
||||
resultTypeField.setSelectedItem( MPResultType.DEFAULT );
|
||||
resultTypeField.addItemListener( new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(final ItemEvent e) {
|
||||
@ -240,7 +240,7 @@ public class PasswordFrame extends JFrame implements DocumentListener {
|
||||
public String call()
|
||||
throws Exception {
|
||||
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>() {
|
||||
|
Loading…
Reference in New Issue
Block a user