Standardize mpw-wide constants and explain their purpose, also allow non-home .mpw.d.
This commit is contained in:
parent
0498a245c6
commit
564e5d9084
@ -0,0 +1,74 @@
|
|||||||
|
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
|
||||||
|
*/
|
||||||
|
public class MPConstant {
|
||||||
|
|
||||||
|
/* Environment */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mpw: default user name if one is not provided.
|
||||||
|
*/
|
||||||
|
public static final String env_userName = "MP_USERNAME";
|
||||||
|
/**
|
||||||
|
* mpw: default site type if one is not provided.
|
||||||
|
*
|
||||||
|
* @see MPSiteType#forOption(String)
|
||||||
|
*/
|
||||||
|
public static final String env_siteType = "MP_SITETYPE";
|
||||||
|
/**
|
||||||
|
* mpw: default site counter value if one is not provided.
|
||||||
|
*/
|
||||||
|
public static final String env_siteCounter = "MP_SITECOUNTER";
|
||||||
|
/**
|
||||||
|
* mpw: default path to look for run configuration files if the platform default is not desired.
|
||||||
|
*/
|
||||||
|
public static final String env_rcDir = "MP_RCDIR";
|
||||||
|
/**
|
||||||
|
* mpw: permit automatic update checks.
|
||||||
|
*/
|
||||||
|
public static final String env_checkUpdates = "MP_CHECKUPDATES";
|
||||||
|
|
||||||
|
/* Algorithm */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* scrypt: CPU cost parameter.
|
||||||
|
*/
|
||||||
|
public static final int scrypt_N = 32768;
|
||||||
|
/**
|
||||||
|
* scrypt: Memory cost parameter.
|
||||||
|
*/
|
||||||
|
public static final int scrypt_r = 8;
|
||||||
|
/**
|
||||||
|
* scrypt: Parallelization parameter.
|
||||||
|
*/
|
||||||
|
public static final int scrypt_p = 2;
|
||||||
|
/**
|
||||||
|
* mpw: Master key size (byte).
|
||||||
|
*/
|
||||||
|
public static final int mpw_dkLen = 64;
|
||||||
|
/**
|
||||||
|
* mpw: Input character encoding.
|
||||||
|
*/
|
||||||
|
public static final Charset mpw_charset = Charsets.UTF_8;
|
||||||
|
/**
|
||||||
|
* mpw: Platform-agnostic byte order.
|
||||||
|
*/
|
||||||
|
public static final ByteOrder mpw_byteOrder = ByteOrder.BIG_ENDIAN;
|
||||||
|
/**
|
||||||
|
* mpw: Site digest.
|
||||||
|
*/
|
||||||
|
public static final MessageAuthenticationDigests mpw_digest = MessageAuthenticationDigests.HmacSHA256;
|
||||||
|
/**
|
||||||
|
* mpw: Key ID hash.
|
||||||
|
*/
|
||||||
|
public static final MessageDigests mpw_hash = MessageDigests.SHA256;
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.google.common.primitives.UnsignedInteger;
|
import com.google.common.primitives.UnsignedInteger;
|
||||||
@ -8,7 +7,6 @@ import com.lambdaworks.crypto.SCrypt;
|
|||||||
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 java.nio.*;
|
import java.nio.*;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -25,19 +23,11 @@ import javax.annotation.Nullable;
|
|||||||
*/
|
*/
|
||||||
public class MasterKeyV0 extends MasterKey {
|
public class MasterKeyV0 extends MasterKey {
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
protected final int MP_N = 32768;
|
|
||||||
protected final int MP_r = 8;
|
|
||||||
protected final int MP_p = 2;
|
|
||||||
protected final int MP_dkLen = 64;
|
|
||||||
protected final int MP_intLen = 32;
|
|
||||||
protected final Charset MP_charset = Charsets.UTF_8;
|
|
||||||
protected final ByteOrder MP_byteOrder = ByteOrder.BIG_ENDIAN;
|
|
||||||
protected final MessageDigests MP_hash = MessageDigests.SHA256;
|
|
||||||
protected final MessageAuthenticationDigests MP_mac = MessageAuthenticationDigests.HmacSHA256;
|
|
||||||
|
|
||||||
public MasterKeyV0(final String fullName) {
|
public MasterKeyV0(final String fullName) {
|
||||||
super( fullName );
|
super( fullName );
|
||||||
}
|
}
|
||||||
@ -52,15 +42,15 @@ public class MasterKeyV0 extends MasterKey {
|
|||||||
@Override
|
@Override
|
||||||
protected byte[] deriveKey(final char[] masterPassword) {
|
protected byte[] deriveKey(final char[] masterPassword) {
|
||||||
String fullName = getFullName();
|
String fullName = getFullName();
|
||||||
byte[] fullNameBytes = fullName.getBytes( MP_charset );
|
byte[] fullNameBytes = fullName.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] fullNameLengthBytes = bytesForInt( fullName.length() );
|
byte[] fullNameLengthBytes = bytesForInt( fullName.length() );
|
||||||
|
|
||||||
String mpKeyScope = MPSiteVariant.Password.getScope();
|
String mpKeyScope = MPSiteVariant.Password.getScope();
|
||||||
byte[] masterKeySalt = Bytes.concat( mpKeyScope.getBytes( MP_charset ), fullNameLengthBytes, fullNameBytes );
|
byte[] masterKeySalt = Bytes.concat( mpKeyScope.getBytes( MPConstant.mpw_charset ), fullNameLengthBytes, fullNameBytes );
|
||||||
logger.trc( "key scope: %s", mpKeyScope );
|
logger.trc( "key scope: %s", mpKeyScope );
|
||||||
logger.trc( "masterKeySalt ID: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) );
|
logger.trc( "masterKeySalt ID: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) );
|
||||||
|
|
||||||
ByteBuffer mpBytesBuf = MP_charset.encode( CharBuffer.wrap( masterPassword ) );
|
ByteBuffer mpBytesBuf = MPConstant.mpw_charset.encode( CharBuffer.wrap( masterPassword ) );
|
||||||
byte[] mpBytes = new byte[mpBytesBuf.remaining()];
|
byte[] mpBytes = new byte[mpBytesBuf.remaining()];
|
||||||
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
|
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
|
||||||
Arrays.fill( mpBytesBuf.array(), (byte) 0 );
|
Arrays.fill( mpBytesBuf.array(), (byte) 0 );
|
||||||
@ -71,9 +61,9 @@ public class MasterKeyV0 extends MasterKey {
|
|||||||
protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
|
protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
|
||||||
try {
|
try {
|
||||||
if (isAllowNative())
|
if (isAllowNative())
|
||||||
return SCrypt.scrypt( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
|
return SCrypt.scrypt( mpBytes, masterKeySalt, MPConstant.scrypt_N, MPConstant.scrypt_r, MPConstant.scrypt_p, MPConstant.mpw_dkLen );
|
||||||
else
|
else
|
||||||
return SCrypt.scryptJ( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
|
return SCrypt.scryptJ( mpBytes, masterKeySalt, MPConstant.scrypt_N, MPConstant.scrypt_r, MPConstant.scrypt_p, MPConstant.mpw_dkLen );
|
||||||
}
|
}
|
||||||
catch (GeneralSecurityException e) {
|
catch (GeneralSecurityException e) {
|
||||||
logger.bug( e );
|
logger.bug( e );
|
||||||
@ -99,22 +89,22 @@ public class MasterKeyV0 extends MasterKey {
|
|||||||
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
||||||
|
|
||||||
String siteScope = siteVariant.getScope();
|
String siteScope = siteVariant.getScope();
|
||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
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 ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContextBytes == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeedBytes = MP_mac.of( getKey(), sitePasswordInfo );
|
byte[] sitePasswordSeedBytes = MPConstant.mpw_digest.of( getKey(), sitePasswordInfo );
|
||||||
int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
|
int[] sitePasswordSeed = new int[sitePasswordSeedBytes.length];
|
||||||
for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
|
for (int i = 0; i < sitePasswordSeedBytes.length; ++i) {
|
||||||
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
|
ByteBuffer buf = ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( ByteOrder.BIG_ENDIAN );
|
||||||
@ -146,16 +136,16 @@ 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( MP_byteOrder ).putInt( number ).array();
|
return ByteBuffer.allocate( MP_intLen / Byte.SIZE ).order( MPConstant.mpw_byteOrder ).putInt( number ).array();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] bytesForInt(@Nonnull final UnsignedInteger number) {
|
protected byte[] bytesForInt(@Nonnull final UnsignedInteger number) {
|
||||||
return ByteBuffer.allocate( MP_intLen / Byte.SIZE ).order( MP_byteOrder ).putInt( number.intValue() ).array();
|
return ByteBuffer.allocate( MP_intLen / Byte.SIZE ).order( MPConstant.mpw_byteOrder ).putInt( number.intValue() ).array();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] idForBytes(final byte[] bytes) {
|
protected byte[] idForBytes(final byte[] bytes) {
|
||||||
return MP_hash.of( bytes );
|
return MPConstant.mpw_hash.of( bytes );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,22 +46,22 @@ public class MasterKeyV1 extends MasterKeyV0 {
|
|||||||
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
||||||
|
|
||||||
String siteScope = siteVariant.getScope();
|
String siteScope = siteVariant.getScope();
|
||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
byte[] siteNameLengthBytes = bytesForInt( siteName.length() );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
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 ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContextBytes == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeed = MP_mac.of( getKey(), sitePasswordInfo );
|
byte[] sitePasswordSeed = MPConstant.mpw_digest.of( getKey(), sitePasswordInfo );
|
||||||
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
||||||
|
|
||||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||||
|
@ -45,22 +45,22 @@ public class MasterKeyV2 extends MasterKeyV1 {
|
|||||||
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (300 * 1000)) * 300 );
|
||||||
|
|
||||||
String siteScope = siteVariant.getScope();
|
String siteScope = siteVariant.getScope();
|
||||||
byte[] siteNameBytes = siteName.getBytes( MP_charset );
|
byte[] siteNameBytes = siteName.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
|
byte[] siteNameLengthBytes = bytesForInt( siteNameBytes.length );
|
||||||
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
byte[] siteCounterBytes = bytesForInt( siteCounter );
|
||||||
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MP_charset );
|
byte[] siteContextBytes = siteContext == null || siteContext.isEmpty()? null: siteContext.getBytes( MPConstant.mpw_charset );
|
||||||
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
byte[] siteContextLengthBytes = bytesForInt( siteContextBytes == null? 0: siteContextBytes.length );
|
||||||
logger.trc( "site scope: %s, context: %s", siteScope, siteContextBytes == null? "<empty>": siteContext );
|
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 ),
|
logger.trc( "seed from: hmac-sha256(masterKey, %s | %s | %s | %s | %s | %s)", siteScope, CodeUtils.encodeHex( siteNameLengthBytes ),
|
||||||
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
siteName, CodeUtils.encodeHex( siteCounterBytes ), CodeUtils.encodeHex( siteContextLengthBytes ),
|
||||||
siteContextBytes == null? "(null)": siteContext );
|
siteContextBytes == null? "(null)": siteContext );
|
||||||
|
|
||||||
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MP_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
byte[] sitePasswordInfo = Bytes.concat( siteScope.getBytes( MPConstant.mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
|
||||||
if (siteContextBytes != null)
|
if (siteContextBytes != null)
|
||||||
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
sitePasswordInfo = Bytes.concat( sitePasswordInfo, siteContextLengthBytes, siteContextBytes );
|
||||||
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
logger.trc( "sitePasswordInfo ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordInfo ) ) );
|
||||||
|
|
||||||
byte[] sitePasswordSeed = MP_mac.of( getKey(), sitePasswordInfo );
|
byte[] sitePasswordSeed = MPConstant.mpw_digest.of( getKey(), sitePasswordInfo );
|
||||||
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
logger.trc( "sitePasswordSeed ID: %s", CodeUtils.encodeHex( idForBytes( sitePasswordSeed ) ) );
|
||||||
|
|
||||||
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
Preconditions.checkState( sitePasswordSeed.length > 0 );
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package com.lyndir.masterpassword;
|
package com.lyndir.masterpassword;
|
||||||
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import com.lambdaworks.crypto.SCrypt;
|
|
||||||
import com.lyndir.lhunath.opal.system.CodeUtils;
|
import com.lyndir.lhunath.opal.system.CodeUtils;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.CharBuffer;
|
import java.nio.CharBuffer;
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@ -35,15 +33,15 @@ public class MasterKeyV3 extends MasterKeyV2 {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
protected byte[] deriveKey(final char[] masterPassword) {
|
protected byte[] deriveKey(final char[] masterPassword) {
|
||||||
byte[] fullNameBytes = getFullName().getBytes( MP_charset );
|
byte[] fullNameBytes = getFullName().getBytes( MPConstant.mpw_charset );
|
||||||
byte[] fullNameLengthBytes = bytesForInt( fullNameBytes.length );
|
byte[] fullNameLengthBytes = bytesForInt( fullNameBytes.length );
|
||||||
|
|
||||||
String mpKeyScope = MPSiteVariant.Password.getScope();
|
String mpKeyScope = MPSiteVariant.Password.getScope();
|
||||||
byte[] masterKeySalt = Bytes.concat( mpKeyScope.getBytes( MP_charset ), fullNameLengthBytes, fullNameBytes );
|
byte[] masterKeySalt = Bytes.concat( mpKeyScope.getBytes( MPConstant.mpw_charset ), fullNameLengthBytes, fullNameBytes );
|
||||||
logger.trc( "key scope: %s", mpKeyScope );
|
logger.trc( "key scope: %s", mpKeyScope );
|
||||||
logger.trc( "masterKeySalt ID: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) );
|
logger.trc( "masterKeySalt ID: %s", CodeUtils.encodeHex( idForBytes( masterKeySalt ) ) );
|
||||||
|
|
||||||
ByteBuffer mpBytesBuf = MP_charset.encode( CharBuffer.wrap( masterPassword ) );
|
ByteBuffer mpBytesBuf = MPConstant.mpw_charset.encode( CharBuffer.wrap( masterPassword ) );
|
||||||
byte[] mpBytes = new byte[mpBytesBuf.remaining()];
|
byte[] mpBytes = new byte[mpBytesBuf.remaining()];
|
||||||
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
|
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
|
||||||
Arrays.fill( mpBytesBuf.array(), (byte) 0 );
|
Arrays.fill( mpBytesBuf.array(), (byte) 0 );
|
||||||
|
@ -37,21 +37,17 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class CLI {
|
public class CLI {
|
||||||
|
|
||||||
private static final String ENV_USERNAME = "MP_USERNAME";
|
|
||||||
private static final String ENV_SITETYPE = "MP_SITETYPE";
|
|
||||||
private static final String ENV_SITECOUNTER = "MP_SITECOUNTER";
|
|
||||||
|
|
||||||
public static void main(final String[] args)
|
public static void main(final String[] args)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
// Read information from the environment.
|
// Read information from the environment.
|
||||||
char[] masterPassword;
|
char[] masterPassword;
|
||||||
String siteName = null, context = null;
|
String siteName = null, context = null;
|
||||||
String userName = System.getenv( ENV_USERNAME );
|
String userName = System.getenv( MPConstant.env_userName );
|
||||||
String siteTypeName = ifNotNullElse( System.getenv( ENV_SITETYPE ), "" );
|
String siteTypeName = ifNotNullElse( System.getenv( MPConstant.env_siteType ), "" );
|
||||||
MPSiteType siteType = siteTypeName.isEmpty()? MPSiteType.GeneratedLong: MPSiteType.forOption( siteTypeName );
|
MPSiteType siteType = siteTypeName.isEmpty()? MPSiteType.GeneratedLong: MPSiteType.forOption( siteTypeName );
|
||||||
MPSiteVariant variant = MPSiteVariant.Password;
|
MPSiteVariant variant = MPSiteVariant.Password;
|
||||||
String siteCounterName = ifNotNullElse( System.getenv( ENV_SITECOUNTER ), "" );
|
String siteCounterName = ifNotNullElse( System.getenv( MPConstant.env_siteCounter ), "" );
|
||||||
UnsignedInteger siteCounter = siteCounterName.isEmpty()? UnsignedInteger.valueOf( 1 ): UnsignedInteger.valueOf( siteCounterName );
|
UnsignedInteger siteCounter = siteCounterName.isEmpty()? UnsignedInteger.valueOf( 1 ): UnsignedInteger.valueOf( siteCounterName );
|
||||||
|
|
||||||
// Parse information from option arguments.
|
// Parse information from option arguments.
|
||||||
@ -102,9 +98,9 @@ public class CLI {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.format( "Usage: mpw [-u name] [-t type] [-c counter] site\n\n" );
|
System.out.format( "Usage: mpw [-u name] [-t type] [-c counter] site\n\n" );
|
||||||
System.out.format( " -u name Specify the full name of the user.\n" );
|
System.out.format( " -u name Specify the full name of the user.\n" );
|
||||||
System.out.format( " Defaults to %s in env.\n\n", ENV_USERNAME );
|
System.out.format( " Defaults to %s in env.\n\n", MPConstant.env_userName );
|
||||||
System.out.format( " -t type Specify the password's template.\n" );
|
System.out.format( " -t type Specify the password's template.\n" );
|
||||||
System.out.format( " Defaults to %s in env or 'long' for password, 'name' for login.\n", ENV_SITETYPE );
|
System.out.format( " Defaults to %s in env or 'long' for password, 'name' for login.\n", MPConstant.env_siteType );
|
||||||
|
|
||||||
int optionsLength = 0;
|
int optionsLength = 0;
|
||||||
Map<String, MPSiteType> typeMap = Maps.newLinkedHashMap();
|
Map<String, MPSiteType> typeMap = Maps.newLinkedHashMap();
|
||||||
@ -122,7 +118,7 @@ public class CLI {
|
|||||||
System.out.println();
|
System.out.println();
|
||||||
|
|
||||||
System.out.format( " -c counter The value of the counter.\n" );
|
System.out.format( " -c counter The value of the counter.\n" );
|
||||||
System.out.format( " Defaults to %s in env or '1'.\n\n", ENV_SITECOUNTER );
|
System.out.format( " Defaults to %s in env or '1'.\n\n", MPConstant.env_siteCounter );
|
||||||
System.out.format( " -v variant The kind of content to generate.\n" );
|
System.out.format( " -v variant The kind of content to generate.\n" );
|
||||||
System.out.format( " Defaults to 'password'.\n" );
|
System.out.format( " Defaults to 'password'.\n" );
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.lyndir.masterpassword.gui;
|
package com.lyndir.masterpassword.gui;
|
||||||
|
|
||||||
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||||
|
import com.lyndir.masterpassword.MPConstant;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,6 +16,6 @@ public class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkForUpdates() {
|
public boolean checkForUpdates() {
|
||||||
return ConversionUtils.toBoolean( System.getProperty( "mp.update.check" ) ).or( true );
|
return ConversionUtils.toBoolean( System.getenv( MPConstant.env_checkUpdates ) ).or( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,32 @@
|
|||||||
package com.lyndir.masterpassword.model;
|
package com.lyndir.masterpassword.model;
|
||||||
|
|
||||||
|
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||||
|
|
||||||
import com.google.common.base.*;
|
import com.google.common.base.*;
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.io.CharSink;
|
import com.google.common.io.CharSink;
|
||||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||||
|
import com.lyndir.masterpassword.MPConstant;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.SortedSet;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Manages user data stored in user-specific {@code .mpsites} files under {@code .mpw.d}.
|
||||||
* @author lhunath, 14-12-07
|
* @author lhunath, 14-12-07
|
||||||
*/
|
*/
|
||||||
public class MPUserFileManager extends MPUserManager {
|
public class MPUserFileManager extends MPUserManager {
|
||||||
|
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
private static final Logger logger = Logger.get( MPUserFileManager.class );
|
private static final Logger logger = Logger.get( MPUserFileManager.class );
|
||||||
private static final File mpwd = new File( System.getProperty( "user.home" ), ".mpw.d" );
|
|
||||||
private static final MPUserFileManager instance;
|
private static final MPUserFileManager instance;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
File mpwrc = new File( System.getProperty( "user.home" ), ".mpwrc" );
|
String rcDir = System.getenv( MPConstant.env_rcDir );
|
||||||
if (mpwrc.exists() && !mpwd.exists())
|
if (rcDir != null)
|
||||||
if (!mpwrc.renameTo( mpwd ))
|
instance = create( new File( rcDir ) );
|
||||||
logger.err( "Couldn't migrate: %s -> %s", mpwrc, mpwd );
|
else
|
||||||
|
instance = create( new File( ifNotNullElseNullable( System.getProperty( "user.home" ), System.getenv( "HOME" ) ), ".mpw.d" ) );
|
||||||
instance = create( mpwd );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final File userFilesDirectory;
|
private final File userFilesDirectory;
|
||||||
@ -51,12 +52,7 @@ public class MPUserFileManager extends MPUserManager {
|
|||||||
return ImmutableList.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return FluentIterable.from( ImmutableList.copyOf( userFilesDirectory.listFiles( new FilenameFilter() {
|
return FluentIterable.from( listUserFiles( userFilesDirectory ) ).transform( new Function<File, MPUser>() {
|
||||||
@Override
|
|
||||||
public boolean accept(final File dir, final String name) {
|
|
||||||
return name.endsWith( ".mpsites" );
|
|
||||||
}
|
|
||||||
} ) ) ).transform( new Function<File, MPUser>() {
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public MPUser apply(@Nullable final File file) {
|
public MPUser apply(@Nullable final File file) {
|
||||||
@ -71,6 +67,15 @@ public class MPUserFileManager extends MPUserManager {
|
|||||||
} ).filter( Predicates.notNull() );
|
} ).filter( Predicates.notNull() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ImmutableList<File> listUserFiles(final File userFilesDirectory) {
|
||||||
|
return ImmutableList.copyOf( ifNotNullElse( userFilesDirectory.listFiles( new FilenameFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(final File dir, final String name) {
|
||||||
|
return name.endsWith( ".mpsites" );
|
||||||
|
}
|
||||||
|
} ), new File[0] ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUser(final MPUser user) {
|
public void addUser(final MPUser user) {
|
||||||
super.addUser( user );
|
super.addUser( user );
|
||||||
@ -103,12 +108,7 @@ public class MPUserFileManager extends MPUserManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove deleted users.
|
// Remove deleted users.
|
||||||
for (File userFile : userFilesDirectory.listFiles( new FilenameFilter() {
|
for (File userFile : listUserFiles( userFilesDirectory ))
|
||||||
@Override
|
|
||||||
public boolean accept(final File dir, final String name) {
|
|
||||||
return name.endsWith( ".mpsites" );
|
|
||||||
}
|
|
||||||
} ))
|
|
||||||
if (getUserNamed( userFile.getName().replaceFirst( "\\.mpsites$", "" ) ) == null)
|
if (getUserNamed( userFile.getName().replaceFirst( "\\.mpsites$", "" ) ) == null)
|
||||||
if (!userFile.delete())
|
if (!userFile.delete())
|
||||||
logger.err( "Couldn't delete file: %s", userFile );
|
logger.err( "Couldn't delete file: %s", userFile );
|
||||||
@ -118,6 +118,6 @@ public class MPUserFileManager extends MPUserManager {
|
|||||||
* @return The location on the file system where the user models are stored.
|
* @return The location on the file system where the user models are stored.
|
||||||
*/
|
*/
|
||||||
public File getPath() {
|
public File getPath() {
|
||||||
return mpwd;
|
return userFilesDirectory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user