2
0

Apply 'Lhunath' code inspection fixes and improvements.

This commit is contained in:
Maarten Billemont
2017-04-04 20:39:18 -04:00
parent 86f956571d
commit b478691980
59 changed files with 452 additions and 320 deletions

View File

@@ -10,7 +10,7 @@ import java.nio.charset.Charset;
/**
* @author lhunath, 2016-10-29
*/
public class MPConstant {
public final class MPConstant {
/* Environment */
@@ -58,17 +58,24 @@ public class MPConstant {
/**
* mpw: Input character encoding.
*/
public static final Charset mpw_charset = Charsets.UTF_8;
public static final Charset mpw_charset = Charsets.UTF_8;
/**
* mpw: Platform-agnostic byte order.
*/
public static final ByteOrder mpw_byteOrder = ByteOrder.BIG_ENDIAN;
public static final ByteOrder mpw_byteOrder = ByteOrder.BIG_ENDIAN;
/**
* mpw: Site digest.
*/
public static final MessageAuthenticationDigests mpw_digest = MessageAuthenticationDigests.HmacSHA256;
public static final MessageAuthenticationDigests mpw_digest = MessageAuthenticationDigests.HmacSHA256;
/**
* mpw: Key ID hash.
*/
public static final MessageDigests mpw_hash = MessageDigests.SHA256;
public static final MessageDigests mpw_hash = MessageDigests.SHA256;
/**
* mpw: validity for the time-based rolling counter.
*/
public static final int mpw_counter_timeout = 5 * 60 /* s */;
public static final int MS_PER_S = 1000;
}

View File

@@ -19,12 +19,12 @@ public class MPIdenticon {
private static final Logger logger = Logger.get( MPIdenticon.class );
private static final Charset charset = Charsets.UTF_8;
private static final Color[] colors = new Color[]{
private static final Color[] colors = {
Color.RED, Color.GREEN, Color.YELLOW, Color.BLUE, Color.MAGENTA, Color.CYAN, Color.MONO };
private static final char[] leftArm = new char[]{ '╔', '╚', '╰', '═' };
private static final char[] rightArm = new char[]{ '╗', '╝', '╯', '═' };
private static final char[] body = new char[]{ '█', '░', '▒', '▓', '☺', '☻' };
private static final char[] accessory = new char[]{
private static final char[] leftArm = { '╔', '╚', '╰', '═' };
private static final char[] rightArm = { '╗', '╝', '╯', '═' };
private static final char[] body = { '█', '░', '▒', '▓', '☺', '☻' };
private static final char[] accessory = {
'◈', '◎', '◐', '◑', '◒', '◓', '☀', '☁', '☂', '☃', '☄', '★', '☆', '☎', '☏', '⎈', '⌂', '☘', '☢', '☣', '☕', '⌚', '⌛', '⏰', '⚡',
'⛄', '⛅', '☔', '♔', '♕', '♖', '♗', '♘', '♙', '♚', '♛', '♜', '♝', '♞', '♟', '♨', '♩', '♪', '♫', '⚐', '⚑', '⚔', '⚖', '⚙', '⚠',
'⌘', '⏎', '✄', '✆', '✈', '✉', '✌' };
@@ -33,11 +33,12 @@ public class MPIdenticon {
private final Color color;
private final String text;
public MPIdenticon(String fullName, String masterPassword) {
public MPIdenticon(final String fullName, final String masterPassword) {
this( fullName, masterPassword.toCharArray() );
}
public MPIdenticon(String fullName, char[] masterPassword) {
@SuppressWarnings("MethodCanBeVariableArityMethod")
public MPIdenticon(final String fullName, final char[] masterPassword) {
this.fullName = fullName;
byte[] masterPasswordBytes = charset.encode( CharBuffer.wrap( masterPassword ) ).array();

View File

@@ -3,10 +3,10 @@ package com.lyndir.masterpassword;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.lyndir.lhunath.opal.system.logging.Logger;
import java.util.List;
import java.util.Set;
import java.util.*;
import javax.annotation.Nullable;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
/**
@@ -17,12 +17,12 @@ import org.jetbrains.annotations.Contract;
public enum MPSiteType {
GeneratedMaximum( "Max", "20 characters, contains symbols.", //
ImmutableList.of( "x", "max", "maximum" ), //
ImmutableList.of( "x", "max", "maximum" ), // NON-NLS
ImmutableList.of( new MPTemplate( "anoxxxxxxxxxxxxxxxxx" ), new MPTemplate( "axxxxxxxxxxxxxxxxxno" ) ), //
MPSiteTypeClass.Generated, 0x0 ),
GeneratedLong( "Long", "Copy-friendly, 14 characters, contains symbols.", //
ImmutableList.of( "l", "long" ), //
ImmutableList.of( "l", "long" ), // NON-NLS
ImmutableList.of( new MPTemplate( "CvcvnoCvcvCvcv" ), new MPTemplate( "CvcvCvcvnoCvcv" ),
new MPTemplate( "CvcvCvcvCvcvno" ), new MPTemplate( "CvccnoCvcvCvcv" ),
new MPTemplate( "CvccCvcvnoCvcv" ), new MPTemplate( "CvccCvcvCvcvno" ),
@@ -37,43 +37,43 @@ public enum MPSiteType {
MPSiteTypeClass.Generated, 0x1 ),
GeneratedMedium( "Medium", "Copy-friendly, 8 characters, contains symbols.", //
ImmutableList.of( "m", "med", "medium" ), //
ImmutableList.of( "m", "med", "medium" ), // NON-NLS
ImmutableList.of( new MPTemplate( "CvcnoCvc" ), new MPTemplate( "CvcCvcno" ) ), //
MPSiteTypeClass.Generated, 0x2 ),
GeneratedBasic( "Basic", "8 characters, no symbols.", //
ImmutableList.of( "b", "basic" ), //
ImmutableList.of( "b", "basic" ), // NON-NLS
ImmutableList.of( new MPTemplate( "aaanaaan" ), new MPTemplate( "aannaaan" ), new MPTemplate( "aaannaaa" ) ), //
MPSiteTypeClass.Generated, 0x3 ),
GeneratedShort( "Short", "Copy-friendly, 4 characters, no symbols.", //
ImmutableList.of( "s", "short" ), //
ImmutableList.of( "s", "short" ), // NON-NLS
ImmutableList.of( new MPTemplate( "Cvcn" ) ), //
MPSiteTypeClass.Generated, 0x4 ),
GeneratedPIN( "PIN", "4 numbers.", //
ImmutableList.of( "i", "pin" ), //
ImmutableList.of( "i", "pin" ), // NON-NLS
ImmutableList.of( new MPTemplate( "nnnn" ) ), //
MPSiteTypeClass.Generated, 0x5 ),
GeneratedName( "Name", "9 letter name.", //
ImmutableList.of( "n", "name" ), //
ImmutableList.of( "n", "name" ), // NON-NLS
ImmutableList.of( new MPTemplate( "cvccvcvcv" ) ), //
MPSiteTypeClass.Generated, 0xE ),
GeneratedPhrase( "Phrase", "20 character sentence.", //
ImmutableList.of( "p", "phrase" ), //
ImmutableList.of( "p", "phrase" ), // NON-NLS
ImmutableList.of( new MPTemplate( "cvcc cvc cvccvcv cvc" ), new MPTemplate( "cvc cvccvcvcv cvcv" ),
new MPTemplate( "cv cvccv cvc cvcvccv" ) ), //
MPSiteTypeClass.Generated, 0xF ),
StoredPersonal( "Personal", "AES-encrypted, exportable.", //
ImmutableList.of( "personal" ), //
ImmutableList.of( "personal" ), // NON-NLS
ImmutableList.<MPTemplate>of(), //
MPSiteTypeClass.Stored, 0x0, MPSiteFeature.ExportContent ),
StoredDevicePrivate( "Device", "AES-encrypted, not exported.", //
ImmutableList.of( "device" ), //
ImmutableList.of( "device" ), // NON-NLS
ImmutableList.<MPTemplate>of(), //
MPSiteTypeClass.Stored, 0x1, MPSiteFeature.DevicePrivate );
@@ -129,7 +129,7 @@ public enum MPSiteType {
public int getType() {
int mask = typeIndex | typeClass.getMask();
for (MPSiteFeature typeFeature : typeFeatures)
for (final MPSiteFeature typeFeature : typeFeatures)
mask |= typeFeature.getMask();
return mask;
@@ -143,7 +143,7 @@ public enum MPSiteType {
public static MPSiteType forOption(final String option) {
for (final MPSiteType type : values())
if (type.getOptions().contains( option.toLowerCase() ))
if (type.getOptions().contains( option.toLowerCase( Locale.ROOT ) ))
return type;
throw logger.bug( "No type for option: %s", option );
@@ -154,7 +154,7 @@ public enum MPSiteType {
*
* @return The type registered with the given name.
*/
@Contract("!null -> !null, null -> null")
@Contract("!null -> !null")
public static MPSiteType forName(@Nullable final String name) {
if (name == null)
@@ -189,7 +189,7 @@ public enum MPSiteType {
*/
public static MPSiteType forType(final int type) {
for (MPSiteType siteType : values())
for (final MPSiteType siteType : values())
if (siteType.getType() == type)
return siteType;
@@ -205,7 +205,7 @@ public enum MPSiteType {
int typeMask = mask & ~0xF;
ImmutableList.Builder<MPSiteType> types = ImmutableList.builder();
for (MPSiteType siteType : values())
for (final MPSiteType siteType : values())
if (((siteType.getType() & ~0xF) & typeMask) != 0)
types.add( siteType );

View File

@@ -3,8 +3,10 @@ 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;
import org.jetbrains.annotations.NonNls;
/**
@@ -12,11 +14,11 @@ import org.jetbrains.annotations.Contract;
*/
public enum MPSiteVariant {
Password( "Generate a key for authentication.", "Doesn't currently use a context.", //
ImmutableList.of( "p", "password" ), "com.lyndir.masterpassword" ),
ImmutableList.of( "p", "password" ), "com.lyndir.masterpassword" ), // NON-NLS
Login( "Generate a name for identification.", "Doesn't currently use a context.", //
ImmutableList.of( "l", "login" ), "com.lyndir.masterpassword.login" ),
ImmutableList.of( "l", "login" ), "com.lyndir.masterpassword.login" ), // NON-NLS
Answer( "Generate an answer to a security question.", "Empty for a universal site answer or\nthe most significant word(s) of the question.", //
ImmutableList.of( "a", "answer" ), "com.lyndir.masterpassword.answer" );
ImmutableList.of( "a", "answer" ), "com.lyndir.masterpassword.answer" ); // NON-NLS
static final Logger logger = Logger.get( MPSiteType.class );
@@ -25,7 +27,7 @@ public enum MPSiteVariant {
private final List<String> options;
private final String scope;
MPSiteVariant(final String description, final String contextDescription, final List<String> options, final String scope) {
MPSiteVariant(final String description, final String contextDescription, final List<String> options, @NonNls final String scope) {
this.contextDescription = contextDescription;
this.options = options;
@@ -57,7 +59,7 @@ public enum MPSiteVariant {
public static MPSiteVariant forOption(final String option) {
for (final MPSiteVariant variant : values())
if (variant.getOptions().contains( option.toLowerCase() ))
if (variant.getOptions().contains( option.toLowerCase( Locale.ROOT ) ))
return variant;
throw logger.bug( "No variant for option: %s", option );
@@ -67,7 +69,7 @@ public enum MPSiteVariant {
*
* @return The variant registered with the given name.
*/
@Contract("!null -> !null, null -> null")
@Contract("!null -> !null")
public static MPSiteVariant forName(@Nullable final String name) {
if (name == null)

View File

@@ -4,7 +4,9 @@ import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
import com.google.common.collect.ImmutableList;
import com.lyndir.lhunath.opal.system.util.MetaObject;
import java.io.Serializable;
import java.util.List;
import org.jetbrains.annotations.NonNls;
/**
@@ -12,12 +14,14 @@ import java.util.List;
*
* @author lhunath
*/
public class MPTemplate extends MetaObject {
public class MPTemplate extends MetaObject implements Serializable {
private final String templateString;
private static final long serialVersionUID = 1L;
private final String templateString;
private final List<MPTemplateCharacterClass> template;
MPTemplate(final String templateString) {
MPTemplate(@NonNls final String templateString) {
ImmutableList.Builder<MPTemplateCharacterClass> builder = ImmutableList.builder();
for (int i = 0; i < templateString.length(); ++i)

View File

@@ -1,6 +1,7 @@
package com.lyndir.masterpassword;
import com.lyndir.lhunath.opal.system.logging.Logger;
import org.jetbrains.annotations.NonNls;
/**
@@ -27,7 +28,7 @@ public enum MPTemplateCharacterClass {
private final char identifier;
private final char[] characters;
MPTemplateCharacterClass(final char identifier, final String characters) {
MPTemplateCharacterClass(final char identifier, @NonNls final String characters) {
this.identifier = identifier;
this.characters = characters.toCharArray();
@@ -44,7 +45,7 @@ public enum MPTemplateCharacterClass {
}
public static MPTemplateCharacterClass forIdentifier(final char identifier) {
for (MPTemplateCharacterClass characterClass : values())
for (final MPTemplateCharacterClass characterClass : values())
if (characterClass.getIdentifier() == identifier)
return characterClass;

View File

@@ -1,5 +1,7 @@
package com.lyndir.masterpassword;
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.lhunath.opal.system.*;
@@ -7,7 +9,6 @@ import com.lyndir.lhunath.opal.system.logging.Logger;
import java.util.Arrays;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
/**
@@ -26,13 +27,15 @@ public abstract class MasterKey {
@Nullable
private byte[] masterKey;
@SuppressWarnings("MethodCanBeVariableArityMethod")
public static MasterKey create(final String fullName, final char[] masterPassword) {
return create( Version.CURRENT, fullName, masterPassword );
}
@Nonnull
public static MasterKey create(Version version, final String fullName, final char[] masterPassword) {
@SuppressWarnings("MethodCanBeVariableArityMethod")
public static MasterKey create(final Version version, final String fullName, final char[] masterPassword) {
switch (version) {
case V0:
@@ -45,7 +48,7 @@ public abstract class MasterKey {
return new MasterKeyV3( fullName ).revalidate( masterPassword );
}
throw new UnsupportedOperationException( "Unsupported version: " + version );
throw new UnsupportedOperationException( strf( "Unsupported version: %s", version ) );
}
public static boolean isAllowNativeByDefault() {
@@ -65,18 +68,19 @@ public abstract class MasterKey {
allowNativeByDefault = allowNative;
}
protected MasterKey(@NotNull final String fullName) {
protected MasterKey(@Nonnull final String fullName) {
this.fullName = fullName;
logger.trc( "fullName: %s", fullName );
}
@Nullable
protected abstract byte[] deriveKey(final char[] masterPassword);
@SuppressWarnings("MethodCanBeVariableArityMethod")
protected abstract byte[] deriveKey(char[] masterPassword);
public abstract Version getAlgorithmVersion();
@NotNull
@Nonnull
public String getFullName() {
return fullName;
@@ -103,8 +107,8 @@ public abstract class MasterKey {
return idForBytes( getKey() );
}
public abstract String encode(@Nonnull final String siteName, final MPSiteType siteType, @Nonnull final UnsignedInteger siteCounter,
final MPSiteVariant siteVariant, @Nullable final String siteContext);
public abstract String encode(@Nonnull String siteName, MPSiteType siteType, @Nonnull UnsignedInteger siteCounter,
MPSiteVariant siteVariant, @Nullable String siteContext);
public boolean isValid() {
return masterKey != null;
@@ -118,6 +122,7 @@ public abstract class MasterKey {
}
}
@SuppressWarnings("MethodCanBeVariableArityMethod")
public MasterKey revalidate(final char[] masterPassword) {
invalidate();
@@ -127,19 +132,19 @@ public abstract class MasterKey {
masterKey = deriveKey( masterPassword );
if (masterKey == null)
logger.dbg( "masterKey calculation failed after %.2fs.", (System.currentTimeMillis() - start) / 1000D );
logger.dbg( "masterKey calculation failed after %.2fs.", (double)(System.currentTimeMillis() - start) / MPConstant.MS_PER_S );
else
logger.trc( "masterKey ID: %s (derived in %.2fs)", CodeUtils.encodeHex( idForBytes( masterKey ) ),
(System.currentTimeMillis() - start) / 1000D );
(double)(System.currentTimeMillis() - start) / MPConstant.MS_PER_S );
return this;
}
protected abstract byte[] bytesForInt(final int number);
protected abstract byte[] bytesForInt(int number);
protected abstract byte[] bytesForInt(@Nonnull final UnsignedInteger number);
protected abstract byte[] bytesForInt(@Nonnull UnsignedInteger number);
protected abstract byte[] idForBytes(final byte[] bytes);
protected abstract byte[] idForBytes(byte[] bytes);
public enum Version {
/**
@@ -190,7 +195,7 @@ public abstract class MasterKey {
return "2.2";
}
throw new UnsupportedOperationException( "Unsupported version: " + this );
throw new UnsupportedOperationException( strf( "Unsupported version: %s", this ) );
}
}
}

View File

@@ -58,6 +58,7 @@ public class MasterKeyV0 extends MasterKey {
return scrypt( masterKeySalt, mpBytes );
}
@Nullable
protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
try {
if (isAllowNative())
@@ -65,7 +66,7 @@ public class MasterKeyV0 extends MasterKey {
else
return SCrypt.scryptJ( mpBytes, masterKeySalt, MPConstant.scrypt_N, MPConstant.scrypt_r, MPConstant.scrypt_p, MPConstant.mpw_dkLen );
}
catch (GeneralSecurityException e) {
catch (final GeneralSecurityException e) {
logger.bug( e );
return null;
}
@@ -86,18 +87,18 @@ public class MasterKeyV0 extends MasterKey {
logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
if (siteCounter.longValue() == 0)
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
String siteScope = siteVariant.getScope();
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
byte[] siteCounterBytes = bytesForInt( siteCounter );
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
siteContextBytes == null? "(null)": siteContext );
(siteContextBytes == null)? "(null)": siteContext );
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
if (siteContextBytes != null)
@@ -108,7 +109,7 @@ public class MasterKeyV0 extends MasterKey {
int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
Arrays.fill( buf.array(), sitePasswordSeedBytes[i] > 0? (byte) 0x00: (byte) 0xFF );
Arrays.fill( buf.array(), (byte) ((sitePasswordSeedBytes[i] > 0)? 0x00: 0xFF) );
buf.position( 2 );
buf.put( sitePasswordSeedBytes[i] ).rewind();
sitePasswordSeed[i] = buf.getInt() & 0xFFFF;

View File

@@ -43,18 +43,18 @@ public class MasterKeyV1 extends MasterKeyV0 {
logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
if (siteCounter.longValue() == 0)
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
String siteScope = siteVariant.getScope();
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
byte[] siteCounterBytes = bytesForInt( siteCounter );
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
siteContextBytes == null? "(null)": siteContext );
(siteContextBytes == null)? "(null)": siteContext );
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
if (siteContextBytes != null)

View File

@@ -42,18 +42,18 @@ public class MasterKeyV2 extends MasterKeyV1 {
logger.trc( "siteType: %d (%s)", siteType.ordinal(), siteType );
if (siteCounter.longValue() == 0)
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (MPConstant.mpw_counter_timeout * 1000)) * MPConstant.mpw_counter_timeout );
String siteScope = siteVariant.getScope();
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
byte[] siteCounterBytes = bytesForInt( siteCounter );
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
byte[] siteContextBytes = ((siteContext == null) || siteContext.isEmpty())? null: siteContext.getBytes( MPConstant.mpw_charset );
byte[] siteContextLengthBytes = bytesForInt( (siteContextBytes == null)? 0: siteContextBytes.length );
logger.trc( "site scope: %s, context: %s", siteScope, (siteContextBytes == null)? "<empty>": siteContext );
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
siteContextBytes == null? "(null)": siteContext );
(siteContextBytes == null)? "(null)": siteContext );
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
if (siteContextBytes != null)