2
0

Replace Version API with MPAlgorithm, make configuration instance-specific.

This commit is contained in:
Maarten Billemont
2018-04-26 15:56:12 -04:00
parent 33f2e0edda
commit 82e2d0b5ac
29 changed files with 397 additions and 226 deletions

View File

@@ -30,89 +30,102 @@ import javax.annotation.Nullable;
/**
* @see MPMasterKey.Version
*/
public interface MPAlgorithm {
@SuppressWarnings({ "FieldMayBeStatic", "NewMethodNamingConvention" })
public abstract class MPAlgorithm {
public abstract byte[] masterKey(String fullName, char[] masterPassword);
public abstract byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext);
public abstract String siteResult(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext, MPResultType resultType, @Nullable String resultParam);
public abstract String sitePasswordFromTemplate(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
public abstract String sitePasswordFromCrypt(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
public abstract String sitePasswordFromDerive(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
public abstract String siteState(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext, MPResultType resultType, String resultParam);
// Configuration
public abstract MPMasterKey.Version version();
/**
* mpw: defaults: password result type.
*/
MPResultType mpw_default_type = MPResultType.GeneratedLong;
public abstract MPResultType mpw_default_type();
/**
* mpw: defaults: initial counter value.
*/
UnsignedInteger mpw_default_counter = UnsignedInteger.ONE;
public abstract UnsignedInteger mpw_default_counter();
/**
* mpw: validity for the time-based rolling counter.
* mpw: validity for the time-based rolling counter (s).
*/
int mpw_otp_window = 5 * 60 /* s */;
public abstract long mpw_otp_window();
/**
* mpw: Key ID hash.
*/
MessageDigests mpw_hash = MessageDigests.SHA256;
public abstract MessageDigests mpw_hash();
/**
* mpw: Site digest.
*/
MessageAuthenticationDigests mpw_digest = MessageAuthenticationDigests.HmacSHA256;
public abstract MessageAuthenticationDigests mpw_digest();
/**
* mpw: Platform-agnostic byte order.
*/
ByteOrder mpw_byteOrder = ByteOrder.BIG_ENDIAN;
public abstract ByteOrder mpw_byteOrder();
/**
* mpw: Input character encoding.
*/
Charset mpw_charset = Charsets.UTF_8;
public abstract Charset mpw_charset();
/**
* mpw: Master key size (byte).
*/
int mpw_dkLen = 64;
public abstract int mpw_dkLen();
/**
* mpw: Minimum size for derived keys (bit).
*/
public abstract int mpw_keySize_min();
/**
* mpw: Maximum size for derived keys (bit).
*/
public abstract int mpw_keySize_max();
/**
* scrypt: Parallelization parameter.
*/
int scrypt_p = 2;
public abstract int scrypt_p();
/**
* scrypt: Memory cost parameter.
*/
int scrypt_r = 8;
public abstract int scrypt_r();
/**
* scrypt: CPU cost parameter.
*/
int scrypt_N = 32768;
MPMasterKey.Version getAlgorithmVersion();
byte[] masterKey(String fullName, char[] masterPassword);
byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext);
String siteResult(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext, MPResultType resultType, @Nullable String resultParam);
String sitePasswordFromTemplate(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
String sitePasswordFromCrypt(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
String sitePasswordFromDerive(byte[] masterKey, byte[] siteKey, MPResultType resultType, @Nullable String resultParam);
String siteState(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter, MPKeyPurpose keyPurpose,
@Nullable String keyContext, MPResultType resultType, String resultParam);
public abstract int scrypt_N();
// Utilities
byte[] toBytes(int number);
abstract byte[] toBytes(int number);
byte[] toBytes(UnsignedInteger number);
abstract byte[] toBytes(UnsignedInteger number);
byte[] toBytes(char[] characters);
abstract byte[] toBytes(char[] characters);
byte[] toID(byte[] bytes);
abstract byte[] toID(byte[] bytes);
}

View File

@@ -18,17 +18,16 @@
package com.lyndir.masterpassword;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.base.*;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.UnsignedInteger;
import com.lambdaworks.crypto.SCrypt;
import com.lyndir.lhunath.opal.crypto.CryptUtils;
import com.lyndir.lhunath.opal.system.CodeUtils;
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.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.*;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.annotation.Nullable;
@@ -40,20 +39,17 @@ import javax.crypto.IllegalBlockSizeException;
* @author lhunath, 2014-08-30
* @see MPMasterKey.Version#V0
*/
public class MPAlgorithmV0 implements MPAlgorithm {
@SuppressWarnings("NewMethodNamingConvention")
public class MPAlgorithmV0 extends MPAlgorithm {
public final MPMasterKey.Version version = MPMasterKey.Version.V0;
protected final Logger logger = Logger.get( getClass() );
@Override
public MPMasterKey.Version getAlgorithmVersion() {
return MPMasterKey.Version.V0;
}
@Override
public byte[] masterKey(final String fullName, final char[] masterPassword) {
byte[] fullNameBytes = fullName.getBytes( mpw_charset );
byte[] fullNameBytes = fullName.getBytes( mpw_charset() );
byte[] fullNameLengthBytes = toBytes( fullName.length() );
String keyScope = MPKeyPurpose.Authentication.getScope();
@@ -62,12 +58,12 @@ public class MPAlgorithmV0 implements MPAlgorithm {
// Calculate the master key salt.
logger.trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s",
keyScope, CodeUtils.encodeHex( fullNameLengthBytes ), fullName );
byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( mpw_charset ), fullNameLengthBytes, fullNameBytes );
byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( mpw_charset() ), fullNameLengthBytes, fullNameBytes );
logger.trc( " => masterKeySalt.id: %s", CodeUtils.encodeHex( toID( masterKeySalt ) ) );
// Calculate the master key.
logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )",
scrypt_N, scrypt_r, scrypt_p );
scrypt_N(), scrypt_r(), scrypt_p() );
byte[] masterPasswordBytes = toBytes( masterPassword );
byte[] masterKey = scrypt( masterKeySalt, masterPasswordBytes );
Arrays.fill( masterKeySalt, (byte) 0 );
@@ -79,7 +75,7 @@ public class MPAlgorithmV0 implements MPAlgorithm {
protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
try {
return SCrypt.scrypt( mpBytes, masterKeySalt, scrypt_N, scrypt_r, scrypt_p, mpw_dkLen );
return SCrypt.scrypt( mpBytes, masterKeySalt, scrypt_N(), scrypt_r(), scrypt_p(), mpw_dkLen() );
}
catch (final GeneralSecurityException e) {
throw logger.bug( e );
@@ -95,25 +91,25 @@ public class MPAlgorithmV0 implements MPAlgorithm {
// OTP counter value.
if (siteCounter.longValue() == 0)
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (mpw_otp_window * 1000)) * mpw_otp_window );
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (mpw_otp_window() * 1000)) * mpw_otp_window() );
// Calculate the site seed.
byte[] siteNameBytes = siteName.getBytes( mpw_charset );
byte[] siteNameBytes = siteName.getBytes( mpw_charset() );
byte[] siteNameLengthBytes = toBytes( siteName.length() );
byte[] siteCounterBytes = toBytes( siteCounter );
byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( mpw_charset );
byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( mpw_charset() );
byte[] keyContextLengthBytes = (keyContextBytes == null)? null: toBytes( keyContextBytes.length );
logger.trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s",
keyScope, CodeUtils.encodeHex( siteNameLengthBytes ), siteName, CodeUtils.encodeHex( siteCounterBytes ),
(keyContextLengthBytes == null)? null: CodeUtils.encodeHex( keyContextLengthBytes ), keyContext );
byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( mpw_charset() ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
if (keyContextBytes != null)
sitePasswordInfo = Bytes.concat( sitePasswordInfo, keyContextLengthBytes, keyContextBytes );
logger.trc( " => siteSalt.id: %s", CodeUtils.encodeHex( toID( sitePasswordInfo ) ) );
logger.trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", CodeUtils.encodeHex( toID( masterKey ) ) );
byte[] sitePasswordSeedBytes = mpw_digest.of( masterKey, sitePasswordInfo );
byte[] sitePasswordSeedBytes = mpw_digest().of( masterKey, sitePasswordInfo );
logger.trc( " => siteKey.id: %s", CodeUtils.encodeHex( toID( sitePasswordSeedBytes ) ) );
return sitePasswordSeedBytes;
@@ -142,7 +138,7 @@ public class MPAlgorithmV0 implements MPAlgorithm {
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 );
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();
@@ -185,7 +181,7 @@ public class MPAlgorithmV0 implements MPAlgorithm {
// Decrypt
byte[] plainBuf = CryptUtils.decrypt( cipherBuf, masterKey, true );
String plainText = mpw_charset.decode( ByteBuffer.wrap( plainBuf ) ).toString();
String plainText = mpw_charset().decode( ByteBuffer.wrap( plainBuf ) ).toString();
logger.trc( "decrypted -> plainText: %d bytes = %s = %s", plainBuf.length, plainText, CodeUtils.encodeHex( plainBuf ) );
return plainText;
@@ -202,14 +198,14 @@ public class MPAlgorithmV0 implements MPAlgorithm {
if (resultType == MPResultType.DeriveKey) {
int resultParamInt = ConversionUtils.toIntegerNN( resultParam );
if (resultParamInt == 0)
resultParamInt = 512;
if ((resultParamInt < 128) || (resultParamInt > 512) || ((resultParamInt % 8) != 0))
resultParamInt = mpw_keySize_max();
if ((resultParamInt < mpw_keySize_min()) || (resultParamInt > mpw_keySize_max()) || ((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: %d", keySize );
// Derive key
byte[] resultKey = null; // TODO: mpw_kdf_blake2b( keySize, siteKey, MPSiteKeySize, NULL, 0, 0, NULL );
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." );
@@ -229,7 +225,7 @@ public class MPAlgorithmV0 implements MPAlgorithm {
try {
// Encrypt
byte[] cipherBuf = CryptUtils.encrypt( resultParam.getBytes( mpw_charset ), masterKey, true );
byte[] cipherBuf = CryptUtils.encrypt( resultParam.getBytes( mpw_charset() ), masterKey, true );
logger.trc( "cipherBuf: %d bytes = %s", cipherBuf.length, CodeUtils.encodeHex( cipherBuf ) );
// Base64-encode
@@ -243,21 +239,139 @@ public class MPAlgorithmV0 implements MPAlgorithm {
}
}
// Configuration
@Override
public MPMasterKey.Version version() {
return MPMasterKey.Version.V0;
}
/**
* mpw: defaults: password result type.
*/
@Override
public MPResultType mpw_default_type() {
return MPResultType.GeneratedLong;
}
/**
* mpw: defaults: initial counter value.
*/
@Override
public UnsignedInteger mpw_default_counter() {
return UnsignedInteger.ONE;
}
/**
* mpw: validity for the time-based rolling counter.
*/
@Override
@SuppressWarnings("MagicNumber")
public long mpw_otp_window() {
return 5 * 60 /* s */;
}
/**
* mpw: Key ID hash.
*/
@Override
public MessageDigests mpw_hash() {
return MessageDigests.SHA256;
}
/**
* mpw: Site digest.
*/
@Override
public MessageAuthenticationDigests mpw_digest() {
return MessageAuthenticationDigests.HmacSHA256;
}
/**
* mpw: Platform-agnostic byte order.
*/
@Override
public ByteOrder mpw_byteOrder() {
return ByteOrder.BIG_ENDIAN;
}
/**
* mpw: Input character encoding.
*/
@Override
public Charset mpw_charset() {
return Charsets.UTF_8;
}
/**
* mpw: Master key size (byte).
*/
@Override
@SuppressWarnings("MagicNumber")
public int mpw_dkLen() {
return 64;
}
/**
* mpw: Minimum size for derived keys (bit).
*/
@Override
@SuppressWarnings("MagicNumber")
public int mpw_keySize_min() {
return 128;
}
/**
* mpw: Maximum size for derived keys (bit).
*/
@Override
@SuppressWarnings("MagicNumber")
public int mpw_keySize_max() {
return 512;
}
/**
* scrypt: Parallelization parameter.
*/
@Override
@SuppressWarnings("MagicNumber")
public int scrypt_p() {
return 2;
}
/**
* scrypt: Memory cost parameter.
*/
@Override
@SuppressWarnings("MagicNumber")
public int scrypt_r() {
return 8;
}
/**
* scrypt: CPU cost parameter.
*/
@Override
@SuppressWarnings("MagicNumber")
public int scrypt_N() {
return 32768;
}
// Utilities
@Override
public byte[] toBytes(final int number) {
return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder ).putInt( number ).array();
return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder() ).putInt( number ).array();
}
@Override
public byte[] toBytes(final UnsignedInteger number) {
return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder ).putInt( number.intValue() ).array();
return ByteBuffer.allocate( Integer.SIZE / Byte.SIZE ).order( mpw_byteOrder() ).putInt( number.intValue() ).array();
}
@Override
public byte[] toBytes(final char[] characters) {
ByteBuffer byteBuffer = mpw_charset.encode( CharBuffer.wrap( characters ) );
ByteBuffer byteBuffer = mpw_charset().encode( CharBuffer.wrap( characters ) );
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get( bytes );
@@ -268,6 +382,6 @@ public class MPAlgorithmV0 implements MPAlgorithm {
@Override
public byte[] toID(final byte[] bytes) {
return mpw_hash.of( bytes );
return mpw_hash().of( bytes );
}
}

View File

@@ -29,12 +29,6 @@ import javax.annotation.Nullable;
*/
public class MPAlgorithmV1 extends MPAlgorithmV0 {
@Override
public MPMasterKey.Version getAlgorithmVersion() {
return MPMasterKey.Version.V1;
}
@Override
public String sitePasswordFromTemplate(final byte[] masterKey, final byte[] siteKey, final MPResultType resultType,
@Nullable final String resultParam) {
@@ -60,4 +54,11 @@ public class MPAlgorithmV1 extends MPAlgorithmV0 {
return password.toString();
}
// Configuration
@Override
public MPMasterKey.Version version() {
return MPMasterKey.Version.V1;
}
}

View File

@@ -30,12 +30,6 @@ import javax.annotation.Nullable;
*/
public class MPAlgorithmV2 extends MPAlgorithmV1 {
@Override
public MPMasterKey.Version getAlgorithmVersion() {
return MPMasterKey.Version.V2;
}
@Override
public byte[] siteKey(final byte[] masterKey, final String siteName, UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
@Nullable final String keyContext) {
@@ -45,27 +39,34 @@ public class MPAlgorithmV2 extends MPAlgorithmV1 {
// OTP counter value.
if (siteCounter.longValue() == 0)
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (mpw_otp_window * 1000)) * mpw_otp_window );
siteCounter = UnsignedInteger.valueOf( (System.currentTimeMillis() / (mpw_otp_window() * 1000)) * mpw_otp_window() );
// Calculate the site seed.
byte[] siteNameBytes = siteName.getBytes( mpw_charset );
byte[] siteNameBytes = siteName.getBytes( mpw_charset() );
byte[] siteNameLengthBytes = toBytes( siteNameBytes.length );
byte[] siteCounterBytes = toBytes( siteCounter );
byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( mpw_charset );
byte[] keyContextBytes = ((keyContext == null) || keyContext.isEmpty())? null: keyContext.getBytes( mpw_charset() );
byte[] keyContextLengthBytes = (keyContextBytes == null)? null: toBytes( keyContextBytes.length );
logger.trc( "siteSalt: keyScope=%s | #siteName=%s | siteName=%s | siteCounter=%s | #keyContext=%s | keyContext=%s",
keyScope, CodeUtils.encodeHex( siteNameLengthBytes ), siteName, CodeUtils.encodeHex( siteCounterBytes ),
(keyContextLengthBytes == null)? null: CodeUtils.encodeHex( keyContextLengthBytes ), keyContext );
byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( mpw_charset ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
byte[] sitePasswordInfo = Bytes.concat( keyScope.getBytes( mpw_charset() ), siteNameLengthBytes, siteNameBytes, siteCounterBytes );
if (keyContextBytes != null)
sitePasswordInfo = Bytes.concat( sitePasswordInfo, keyContextLengthBytes, keyContextBytes );
logger.trc( " => siteSalt.id: %s", CodeUtils.encodeHex( toID( sitePasswordInfo ) ) );
logger.trc( "siteKey: hmac-sha256( masterKey.id=%s, siteSalt )", CodeUtils.encodeHex( toID( masterKey ) ) );
byte[] sitePasswordSeedBytes = mpw_digest.of( masterKey, sitePasswordInfo );
byte[] sitePasswordSeedBytes = mpw_digest().of( masterKey, sitePasswordInfo );
logger.trc( " => siteKey.id: %s", CodeUtils.encodeHex( toID( sitePasswordSeedBytes ) ) );
return sitePasswordSeedBytes;
}
// Configuration
@Override
public MPMasterKey.Version version() {
return MPMasterKey.Version.V2;
}
}

View File

@@ -29,16 +29,10 @@ import java.util.Arrays;
*/
public class MPAlgorithmV3 extends MPAlgorithmV2 {
@Override
public MPMasterKey.Version getAlgorithmVersion() {
return MPMasterKey.Version.V3;
}
@Override
public byte[] masterKey(final String fullName, final char[] masterPassword) {
byte[] fullNameBytes = fullName.getBytes( mpw_charset );
byte[] fullNameBytes = fullName.getBytes( mpw_charset() );
byte[] fullNameLengthBytes = toBytes( fullNameBytes.length );
String keyScope = MPKeyPurpose.Authentication.getScope();
@@ -47,12 +41,12 @@ public class MPAlgorithmV3 extends MPAlgorithmV2 {
// Calculate the master key salt.
logger.trc( "masterKeySalt: keyScope=%s | #fullName=%s | fullName=%s",
keyScope, CodeUtils.encodeHex( fullNameLengthBytes ), fullName );
byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( mpw_charset ), fullNameLengthBytes, fullNameBytes );
byte[] masterKeySalt = Bytes.concat( keyScope.getBytes( mpw_charset() ), fullNameLengthBytes, fullNameBytes );
logger.trc( " => masterKeySalt.id: %s", CodeUtils.encodeHex( toID( masterKeySalt ) ) );
// Calculate the master key.
logger.trc( "masterKey: scrypt( masterPassword, masterKeySalt, N=%d, r=%d, p=%d )",
scrypt_N, scrypt_r, scrypt_p );
scrypt_N(), scrypt_r(), scrypt_p() );
byte[] mpBytes = toBytes( masterPassword );
byte[] masterKey = scrypt( masterKeySalt, mpBytes );
Arrays.fill( masterKeySalt, (byte) 0 );
@@ -61,4 +55,11 @@ public class MPAlgorithmV3 extends MPAlgorithmV2 {
return masterKey;
}
// Configuration
@Override
public MPMasterKey.Version version() {
return MPMasterKey.Version.V3;
}
}

View File

@@ -21,6 +21,8 @@ package com.lyndir.masterpassword;
import static com.lyndir.lhunath.opal.system.util.StringUtils.*;
import com.google.common.base.Charsets;
import com.google.common.primitives.UnsignedBytes;
import com.google.common.primitives.UnsignedInteger;
import com.lyndir.lhunath.opal.system.MessageAuthenticationDigests;
import com.lyndir.lhunath.opal.system.logging.Logger;
import java.nio.*;
@@ -66,7 +68,7 @@ public class MPIdenticon {
IntBuffer identiconSeedBuffer = IntBuffer.allocate( identiconSeedBytes.capacity() );
while (identiconSeedBytes.hasRemaining())
identiconSeedBuffer.put( identiconSeedBytes.get() & 0xFF );
identiconSeedBuffer.put( UnsignedBytes.toInt( identiconSeedBytes.get() ) );
int[] identiconSeed = identiconSeedBuffer.array();
color = colors[identiconSeed[4] % colors.length];

View File

@@ -58,21 +58,21 @@ public class MPMasterKey {
*
* @throws MPInvalidatedException {@link #invalidate()} has been called on this object.
*/
private byte[] masterKey(final Version algorithmVersion)
private byte[] masterKey(final MPAlgorithm algorithm)
throws MPInvalidatedException {
Preconditions.checkArgument( masterPassword.length > 0 );
if (invalidated)
throw new MPInvalidatedException();
byte[] key = keyByVersion.get( algorithmVersion );
byte[] key = keyByVersion.get( algorithm.version() );
if (key == null) {
logger.trc( "-- mpw_masterKey (algorithm: %d)", algorithmVersion.toInt() );
logger.trc( "-- mpw_masterKey (algorithm: %s)", algorithm );
logger.trc( "fullName: %s", fullName );
logger.trc( "masterPassword.id: %s", CodeUtils.encodeHex(
algorithmVersion.getAlgorithm().toID( algorithmVersion.getAlgorithm().toBytes( masterPassword ) ) ) );
algorithm.toID( algorithm.toBytes( masterPassword ) ) ) );
keyByVersion.put( algorithmVersion, key = algorithmVersion.getAlgorithm().masterKey( fullName, masterPassword ) );
keyByVersion.put( algorithm.version(), key = algorithm.masterKey( fullName, masterPassword ) );
}
return key;
@@ -84,19 +84,19 @@ public class MPMasterKey {
* @throws MPInvalidatedException {@link #invalidate()} has been called on this object.
*/
private byte[] siteKey(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
@Nullable final String keyContext, final Version algorithmVersion)
@Nullable final String keyContext, final MPAlgorithm algorithm)
throws MPInvalidatedException {
Preconditions.checkArgument( !siteName.isEmpty() );
byte[] masterKey = masterKey( algorithmVersion );
byte[] masterKey = masterKey( algorithm );
logger.trc( "-- mpw_siteKey (algorithm: %d)", algorithmVersion.toInt() );
logger.trc( "-- mpw_siteKey (algorithm: %s)", algorithm );
logger.trc( "siteName: %s", siteName );
logger.trc( "siteCounter: %s", siteCounter );
logger.trc( "keyPurpose: %d (%s)", keyPurpose.toInt(), keyPurpose.getShortName() );
logger.trc( "keyContext: %s", keyContext );
return algorithmVersion.getAlgorithm().siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext );
return algorithm.siteKey( masterKey, siteName, siteCounter, keyPurpose, keyContext );
}
/**
@@ -108,23 +108,23 @@ public class MPMasterKey {
* @param keyContext A site-scoped result modifier.
* @param resultType The type of result to generate.
* @param resultParam A parameter for the resultType. For stateful result types, the output of
* {@link #siteState(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, Version)}.
* {@link #siteState(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, MPAlgorithm)}.
*
* @throws MPInvalidatedException {@link #invalidate()} has been called on this object.
*/
public String siteResult(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam,
final Version algorithmVersion)
final MPAlgorithm algorithm)
throws MPInvalidatedException {
byte[] masterKey = masterKey( algorithmVersion );
byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithmVersion );
byte[] masterKey = masterKey( algorithm );
byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithm );
logger.trc( "-- mpw_siteResult (algorithm: %d)", algorithmVersion.toInt() );
logger.trc( "-- mpw_siteResult (algorithm: %s)", algorithm );
logger.trc( "resultType: %d (%s)", resultType.getType(), resultType.getShortName() );
logger.trc( "resultParam: %s", resultParam );
return algorithmVersion.getAlgorithm().siteResult(
return algorithm.siteResult(
masterKey, siteKey, siteName, siteCounter, keyPurpose, keyContext, resultType, resultParam );
}
@@ -137,26 +137,26 @@ public class MPMasterKey {
* @param keyContext A site-scoped key modifier.
* @param resultType The type of result token to encrypt.
* @param resultParam The result token desired from
* {@link #siteResult(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, Version)}.
* {@link #siteResult(String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String, MPAlgorithm)}.
*
* @throws MPInvalidatedException {@link #invalidate()} has been called on this object.
*/
public String siteState(final String siteName, final UnsignedInteger siteCounter, final MPKeyPurpose keyPurpose,
@Nullable final String keyContext, final MPResultType resultType, @Nullable final String resultParam,
final Version algorithmVersion)
final MPAlgorithm algorithm)
throws MPInvalidatedException {
Preconditions.checkNotNull( resultParam );
Preconditions.checkArgument( !resultParam.isEmpty() );
byte[] masterKey = masterKey( algorithmVersion );
byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithmVersion );
byte[] masterKey = masterKey( algorithm );
byte[] siteKey = siteKey( siteName, siteCounter, keyPurpose, keyContext, algorithm );
logger.trc( "-- mpw_siteState (algorithm: %d)", algorithmVersion.toInt() );
logger.trc( "-- mpw_siteState (algorithm: %s)", algorithm );
logger.trc( "resultType: %d (%s)", resultType.getType(), resultType.getShortName() );
logger.trc( "resultParam: %d bytes = %s", resultParam.getBytes( MPAlgorithm.mpw_charset ).length, resultParam );
logger.trc( "resultParam: %d bytes = %s", resultParam.getBytes( algorithm.mpw_charset() ).length, resultParam );
return algorithmVersion.getAlgorithm().siteState(
return algorithm.siteState(
masterKey, siteKey, siteName, siteCounter, keyPurpose, keyContext, resultType, resultParam );
}
@@ -171,10 +171,10 @@ public class MPMasterKey {
*
* @throws MPInvalidatedException {@link #invalidate()} has been called on this object.
*/
public byte[] getKeyID(final Version algorithmVersion)
public byte[] getKeyID(final MPAlgorithm algorithm)
throws MPInvalidatedException {
return algorithmVersion.getAlgorithm().toID( masterKey( algorithmVersion ) );
return algorithm.toID( masterKey( algorithm ) );
}
/**

View File

@@ -31,6 +31,7 @@ import org.jetbrains.annotations.Contract;
*
* @author lhunath
*/
@SuppressWarnings("RedundantTypeArguments" /* IDEA-191043 */)
public enum MPResultType {
// bit 0-3 | MPResultTypeClass | MPSiteFeature
@@ -134,7 +135,7 @@ public enum MPResultType {
private final List<MPTemplate> templates;
private final MPResultTypeClass typeClass;
private final int typeIndex;
private final Set<MPSiteFeature> typeFeatures;
private final ImmutableSet<MPSiteFeature> typeFeatures;
MPResultType(final String shortName, final String description, final List<MPTemplate> templates,
final MPResultTypeClass typeClass, final int typeIndex, final MPSiteFeature... typeFeatures) {
@@ -166,7 +167,8 @@ public enum MPResultType {
return typeClass;
}
public Set<MPSiteFeature> getTypeFeatures() {
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType" /* IDEA-191042 */ )
public ImmutableSet<MPSiteFeature> getTypeFeatures() {
return typeFeatures;
}
@@ -232,6 +234,7 @@ public enum MPResultType {
*
* @return All types that support the given mask's class & features.
*/
@SuppressWarnings({ "MagicNumber", "UnnecessaryParentheses" /* IDEA-191040 */ })
public static ImmutableList<MPResultType> forMask(final int mask) {
int typeMask = mask & ~0xF; // Ignore resultType bit 0-3