NIFI-13525 Removed unused classes from nifi-security-crypto-key

This closes #9057

- Removed Derived Key Parameter Reader and implementations
- Removed bcrypt and scrypt Derived Key Providers
- Removed unused dependency from nifi-cipher-processors

Signed-off-by: Joseph Witt <joewitt@apache.org>
This commit is contained in:
exceptionfactory 2024-07-06 11:16:51 -05:00 committed by Joseph Witt
parent b2840bd851
commit 62c66a12d1
No known key found for this signature in database
GPG Key ID: 9093BF854F811A1A
22 changed files with 0 additions and 1545 deletions

View File

@ -1,30 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key;
/**
* Abstraction for reading Derived Key Parameter Specifications from serialized parameters
*/
public interface DerivedKeyParameterSpecReader<T extends DerivedKeyParameterSpec> {
/**
* Read serialized parameters and return Derived Key Parameter Specification
*
* @param serializedParameters Serialized parameters
* @return Derived Key Parameter Specification
*/
T read(byte[] serializedParameters);
}

View File

@ -1,80 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.argon2;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpecReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Argon2 implementation reads a US-ASCII string of bytes using the Password-Hashing-Competition String Format specification
*/
public class Argon2DerivedKeyParameterSpecReader implements DerivedKeyParameterSpecReader<Argon2DerivedKeyParameterSpec> {
/** Argon2id hybrid with version 1.3 and 22 character Base64 encoded salt with optional trailing hash parameter */
private static final Pattern PHC_STRING_FORMAT = Pattern.compile("^\\$argon2id\\$v=19\\$m=(\\d+),t=(\\d+),p=(\\d+)\\$([\\w/+]{22})(\\$[\\w/+]+)?$");
private static final int MEMORY_GROUP = 1;
private static final int ITERATIONS_GROUP = 2;
private static final int PARALLELISM_GROUP = 3;
private static final int SALT_GROUP = 4;
private static final Charset PARAMETERS_CHARACTER_SET = StandardCharsets.US_ASCII;
private static final Base64.Decoder decoder = Base64.getDecoder();
/**
* Read serialized parameters parsed from US-ASCII string of bytes
*
* @param serializedParameters Serialized parameters
* @return Argon2 Parameter Specification
*/
@Override
public Argon2DerivedKeyParameterSpec read(final byte[] serializedParameters) {
Objects.requireNonNull(serializedParameters, "Parameters required");
final String parameters = new String(serializedParameters, PARAMETERS_CHARACTER_SET);
final Matcher matcher = PHC_STRING_FORMAT.matcher(parameters);
if (matcher.matches()) {
final String memoryGroup = matcher.group(MEMORY_GROUP);
final String iterationsGroup = matcher.group(ITERATIONS_GROUP);
final String parallelismGroup = matcher.group(PARALLELISM_GROUP);
final String saltGroup = matcher.group(SALT_GROUP);
final int memory = Integer.parseInt(memoryGroup);
final int iterations = Integer.parseInt(iterationsGroup);
final int parallelism = Integer.parseInt(parallelismGroup);
final byte[] salt = decoder.decode(saltGroup);
return new Argon2DerivedKeyParameterSpec(
memory,
iterations,
parallelism,
salt
);
} else {
final String message = String.format("Argon2 serialized parameters [%s] format not matched", parameters);
throw new IllegalArgumentException(message);
}
}
}

View File

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Base64 Decoder translates from bcrypt Base64 characters to RFC 4648 characters
*/
class BcryptBase64Decoder {
/** Alphabet of shared characters following common ordering */
private static final String SHARED_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
/** bcrypt alphabet defined according to the OpenBSD bcrypt function beginning with control characters */
private static final String BCRYPT_ALPHABET = String.format("./%s", SHARED_ALPHABET);
/** Standard alphabet defined according to RFC 4648 ending with control characters */
private static final String STANDARD_ALPHABET = String.format("%s+/", SHARED_ALPHABET);
private static final Map<Character, Character> BCRYPT_STANDARD_CHARACTERS = new LinkedHashMap<>();
private static final Base64.Decoder decoder = Base64.getDecoder();
static {
final char[] bcryptCharacters = BCRYPT_ALPHABET.toCharArray();
final char[] standardCharacters = STANDARD_ALPHABET.toCharArray();
for (int i = 0; i < bcryptCharacters.length; i++) {
final char bcryptCharacter = bcryptCharacters[i];
final char standardCharacter = standardCharacters[i];
BCRYPT_STANDARD_CHARACTERS.put(bcryptCharacter, standardCharacter);
}
}
/**
* Decode bcrypt Base64 encoded ASCII characters to support reading salt and hash strings
*
* @param encoded ASCII string of characters encoded using bcrypt Base64 characters
* @return Decoded bytes
*/
static byte[] decode(final String encoded) {
final int encodedLength = encoded.length();
final byte[] converted = new byte[encodedLength];
for (int i = 0; i < encodedLength; i++) {
final char encodedCharacter = encoded.charAt(i);
final char standardCharacter = getStandardCharacter(encodedCharacter);
converted[i] = (byte) standardCharacter;
}
return decoder.decode(converted);
}
private static char getStandardCharacter(final char encodedCharacter) {
final Character standardCharacter = BCRYPT_STANDARD_CHARACTERS.get(encodedCharacter);
if (standardCharacter == null) {
final String message = String.format("Encoded character [%c] not supported for bcrypt Base64 decoding", encodedCharacter);
throw new IllegalArgumentException(message);
}
return standardCharacter;
}
}

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
/**
* bcrypt key derivation function parameter specification
*/
public class BcryptDerivedKeyParameterSpec implements DerivedKeyParameterSpec {
private final int cost;
private final byte[] salt;
/**
* bcrypt Parameter Specification constructor with required properties
*
* @param cost Cost parameter
* @param salt Array of random salt bytes
*/
public BcryptDerivedKeyParameterSpec(
final int cost,
final byte[] salt
) {
this.cost = cost;
this.salt = salt;
}
@Override
public byte[] getSalt() {
return salt;
}
public int getCost() {
return cost;
}
}

View File

@ -1,65 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpecReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* bcrypt implementation reads a US-ASCII string of bytes using the Modular Crypt Format specification as added in NiFi 0.5.0
*/
public class BcryptDerivedKeyParameterSpecReader implements DerivedKeyParameterSpecReader<BcryptDerivedKeyParameterSpec> {
/** Modular Crypt Format containing the cost as a zero-padded number with a trailing bcrypt-Base64 encoded 16 byte salt and optional hash */
private static final Pattern MODULAR_CRYPT_FORMAT = Pattern.compile("^\\$2[abxy]\\$(\\d{2})\\$([\\w/.]{22})([\\w/.]{31})?$");
private static final int COST_GROUP = 1;
private static final int SALT_GROUP = 2;
private static final Charset PARAMETERS_CHARACTER_SET = StandardCharsets.US_ASCII;
/**
* Read serialized parameters parsed from US-ASCII string of bytes
*
* @param serializedParameters Serialized parameters
* @return bcrypt Parameter Specification
*/
@Override
public BcryptDerivedKeyParameterSpec read(final byte[] serializedParameters) {
Objects.requireNonNull(serializedParameters, "Parameters required");
final String parameters = new String(serializedParameters, PARAMETERS_CHARACTER_SET);
final Matcher matcher = MODULAR_CRYPT_FORMAT.matcher(parameters);
if (matcher.matches()) {
final String costGroup = matcher.group(COST_GROUP);
final String saltGroup = matcher.group(SALT_GROUP);
final int cost = Integer.parseInt(costGroup);
final byte[] salt = BcryptBase64Decoder.decode(saltGroup);
return new BcryptDerivedKeyParameterSpec(cost, salt);
} else {
final String message = String.format("bcrypt serialized parameters [%s] format not matched", parameters);
throw new IllegalArgumentException(message);
}
}
}

View File

@ -1,83 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeyProvider;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.DerivedSecretKey;
import org.bouncycastle.crypto.generators.OpenBSDBCrypt;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
* bcrypt implementation of Derived Key Provider based on Bouncy Castle bcrypt components with SHA-512 digest for derived key
*/
public class BcryptDerivedKeyProvider implements DerivedKeyProvider<BcryptDerivedKeyParameterSpec> {
private static final Charset SERIALIZED_CHARACTER_SET = StandardCharsets.US_ASCII;
private static final int SERIALIZED_HASH_START_INDEX = 29;
private static final String DIGEST_ALGORITHM = "SHA-512";
private static final String BCRYPT_VERSION = "2a";
/**
* Get Derived Key using bcrypt version 2a and provided specification with SHA-512 digest of encoded raw hash bytes
*
* @param derivedKeySpec Derived Key Specification
* @return Derived Secret Key
*/
@Override
public DerivedKey getDerivedKey(final DerivedKeySpec<BcryptDerivedKeyParameterSpec> derivedKeySpec) {
final String serialized = getHashMessage(derivedKeySpec);
final byte[] hashMessage = serialized.getBytes(SERIALIZED_CHARACTER_SET);
final byte[] encodedRawHash = Arrays.copyOfRange(hashMessage, SERIALIZED_HASH_START_INDEX, hashMessage.length);
final byte[] derivedKeyBytes = getDerivedKeyBytes(encodedRawHash, derivedKeySpec.getDerivedKeyLength());
return new DerivedSecretKey(derivedKeyBytes, derivedKeySpec.getAlgorithm(), serialized);
}
private String getHashMessage(final DerivedKeySpec<BcryptDerivedKeyParameterSpec> derivedKeySpec) {
final BcryptDerivedKeyParameterSpec parameterSpec = derivedKeySpec.getParameterSpec();
final int cost = parameterSpec.getCost();
final byte[] salt = parameterSpec.getSalt();
final char[] password = derivedKeySpec.getPassword();
return OpenBSDBCrypt.generate(BCRYPT_VERSION, password, salt, cost);
}
private byte[] getDerivedKeyBytes(final byte[] hash, final int derivedKeyLength) {
final MessageDigest messageDigest = getMessageDigest();
final byte[] digested = messageDigest.digest(hash);
return Arrays.copyOf(digested, derivedKeyLength);
}
private MessageDigest getMessageDigest() {
try {
return MessageDigest.getInstance(DIGEST_ALGORITHM);
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(DIGEST_ALGORITHM, e);
}
}
}

View File

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.detection;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpecReader;
import org.apache.nifi.security.crypto.key.argon2.Argon2DerivedKeyParameterSpecReader;
import org.apache.nifi.security.crypto.key.bcrypt.BcryptDerivedKeyParameterSpecReader;
import org.apache.nifi.security.crypto.key.io.ByteBufferSearch;
import org.apache.nifi.security.crypto.key.pbkdf2.Pbkdf2DerivedKeyParameterSpecReader;
import org.apache.nifi.security.crypto.key.scrypt.ScryptDerivedKeyParameterSpecReader;
import java.nio.ByteBuffer;
/**
* Delegating implementation capable of selecting a reader based on detected header bytes of serialized parameters
*/
public class DetectedDerivedKeyParameterSpecReader implements DerivedKeyParameterSpecReader<DerivedKeyParameterSpec> {
/** Argon2id header as implemented in NiFi 1.12.0 */
private static final byte[] ARGON2_ID_DELIMITER = {'$', 'a', 'r', 'g', 'o', 'n', '2', 'i', 'd', '$'};
/** bcrypt 2a header as implemented in NiFi 0.5.0 */
private static final byte[] BCRYPT_2A_DELIMITER = {'$', '2', 'a', '$'};
/** scrypt header as implemented in NiFi 0.5.0 */
private static final byte[] SCRYPT_DELIMITER = {'$', 's', '0', '$'};
private static final Argon2DerivedKeyParameterSpecReader argon2Reader = new Argon2DerivedKeyParameterSpecReader();
private static final BcryptDerivedKeyParameterSpecReader bcryptReader = new BcryptDerivedKeyParameterSpecReader();
private static final ScryptDerivedKeyParameterSpecReader scryptReader = new ScryptDerivedKeyParameterSpecReader();
private static final Pbkdf2DerivedKeyParameterSpecReader pbkdf2Reader = new Pbkdf2DerivedKeyParameterSpecReader();
/**
* Read Parameter Specification selects a Reader based on header bytes defaulting to PBKDF2 in absence of a matched pattern
*
* @param serializedParameters Serialized parameters
* @return Derived Key Parameter Specification read from serialized parameters
*/
@Override
public DerivedKeyParameterSpec read(final byte[] serializedParameters) {
final ByteBuffer buffer = ByteBuffer.wrap(serializedParameters);
final DerivedKeyParameterSpecReader<? extends DerivedKeyParameterSpec> reader = getReader(buffer);
return reader.read(serializedParameters);
}
private DerivedKeyParameterSpecReader<? extends DerivedKeyParameterSpec> getReader(final ByteBuffer buffer) {
final DerivedKeyParameterSpecReader<? extends DerivedKeyParameterSpec> reader;
if (ByteBufferSearch.indexOf(buffer, ARGON2_ID_DELIMITER) == 0) {
reader = argon2Reader;
} else if (ByteBufferSearch.indexOf(buffer, BCRYPT_2A_DELIMITER) == 0) {
reader = bcryptReader;
} else if (ByteBufferSearch.indexOf(buffer, SCRYPT_DELIMITER) == 0) {
reader = scryptReader;
} else {
reader = pbkdf2Reader;
}
return reader;
}
}

View File

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.detection;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.DerivedKeyProvider;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.argon2.Argon2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.argon2.Argon2DerivedKeyProvider;
import org.apache.nifi.security.crypto.key.bcrypt.BcryptDerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.bcrypt.BcryptDerivedKeyProvider;
import org.apache.nifi.security.crypto.key.pbkdf2.Pbkdf2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.pbkdf2.Pbkdf2DerivedKeyProvider;
import org.apache.nifi.security.crypto.key.scrypt.ScryptDerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.scrypt.ScryptDerivedKeyProvider;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
/**
* Provider delegating to configured implementations based on Parameter Specification class
*/
public class DetectedDerivedKeyProvider implements DerivedKeyProvider<DerivedKeyParameterSpec> {
private static final Map<Class<? extends DerivedKeyParameterSpec>, DerivedKeyProvider<? extends DerivedKeyParameterSpec>> providers = new LinkedHashMap<>();
static {
providers.put(Argon2DerivedKeyParameterSpec.class, new Argon2DerivedKeyProvider());
providers.put(BcryptDerivedKeyParameterSpec.class, new BcryptDerivedKeyProvider());
providers.put(ScryptDerivedKeyParameterSpec.class, new ScryptDerivedKeyProvider());
providers.put(Pbkdf2DerivedKeyParameterSpec.class, new Pbkdf2DerivedKeyProvider());
}
/**
* Get Derived Key using implementation selected based on assignable Parameter Specification class mapped to Provider
*
* @param derivedKeySpec Derived Key Specification
* @return Derived Key
*/
@Override
public DerivedKey getDerivedKey(final DerivedKeySpec<DerivedKeyParameterSpec> derivedKeySpec) {
Objects.requireNonNull(derivedKeySpec, "Specification required");
final Class<? extends DerivedKeyParameterSpec> parameterSpecClass = derivedKeySpec.getParameterSpec().getClass();
final DerivedKeyProvider<DerivedKeyParameterSpec> derivedKeyProvider = findProvider(parameterSpecClass);
return derivedKeyProvider.getDerivedKey(derivedKeySpec);
}
@SuppressWarnings("unchecked")
private DerivedKeyProvider<DerivedKeyParameterSpec> findProvider(final Class<? extends DerivedKeyParameterSpec> parameterSpecClass) {
final Class<? extends DerivedKeyParameterSpec> foundSpecClass = providers.keySet()
.stream()
.filter(specClass -> specClass.isAssignableFrom(parameterSpecClass))
.findFirst()
.orElseThrow(() -> new UnsupportedOperationException(String.format("Parameter Specification [%s] not supported", parameterSpecClass)));
final DerivedKeyProvider<? extends DerivedKeyParameterSpec> derivedKeyProvider = providers.get(foundSpecClass);
return (DerivedKeyProvider<DerivedKeyParameterSpec>) derivedKeyProvider;
}
}

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.io;
import java.nio.ByteBuffer;
/**
* Byte Buffer Search utilities
*/
public class ByteBufferSearch {
private static final int END_OF_FILE = -1;
/**
* Get starting index of delimiter in buffer
*
* @param buffer Byte Buffer to be searched
* @param delimiter Delimiter
* @return Starting index of delimiter or -1 when not found
*/
public static int indexOf(final ByteBuffer buffer, final byte[] delimiter) {
final int bufferSearchLength = buffer.limit() - delimiter.length + 1;
bufferSearch:
for (int i = 0; i < bufferSearchLength; i++) {
for (int j = 0; j < delimiter.length; j++) {
final int bufferIndex = i + j;
final byte indexByte = buffer.get(bufferIndex);
final byte delimiterByte = delimiter[j];
if (indexByte != delimiterByte) {
continue bufferSearch;
}
}
return i;
}
return END_OF_FILE;
}
}

View File

@ -1,40 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.pbkdf2;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpecReader;
import java.util.Objects;
/**
* PBKDF2 implementation uses the serialized parameters as the salt with a hard-coded number of iterations as defined in NiFi 0.5.0
*/
public class Pbkdf2DerivedKeyParameterSpecReader implements DerivedKeyParameterSpecReader<Pbkdf2DerivedKeyParameterSpec> {
protected static final int VERSION_0_5_0_ITERATIONS = 160000;
/**
* Read serialized parameters and return as salt bytes with 160,000 iterations as defined in NiFi 0.5.0
*
* @param serializedParameters Serialized parameters
* @return PBKDF2 Parameter Specification
*/
@Override
public Pbkdf2DerivedKeyParameterSpec read(final byte[] serializedParameters) {
Objects.requireNonNull(serializedParameters, "Parameters required");
return new Pbkdf2DerivedKeyParameterSpec(VERSION_0_5_0_ITERATIONS, serializedParameters);
}
}

View File

@ -1,69 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.scrypt;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
/**
* scrypt key derivation function parameter specification
*/
public class ScryptDerivedKeyParameterSpec implements DerivedKeyParameterSpec {
private final int cost;
private final int blockSize;
private final int parallelization;
private final byte[] salt;
/**
* scrypt Parameter Specification constructor with required properties
*
* @param cost CPU and memory cost parameter
* @param blockSize Block size parameter
* @param parallelization Parallelization parameter
* @param salt Array of random salt bytes
*/
public ScryptDerivedKeyParameterSpec(
final int cost,
final int blockSize,
final int parallelization,
final byte[] salt
) {
this.cost = cost;
this.blockSize = blockSize;
this.parallelization = parallelization;
this.salt = salt;
}
@Override
public byte[] getSalt() {
return salt;
}
public int getCost() {
return cost;
}
public int getBlockSize() {
return blockSize;
}
public int getParallelization() {
return parallelization;
}
}

View File

@ -1,82 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.scrypt;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpecReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* scrypt implementation reads a US-ASCII string of bytes using a Modular Crypt Format defined according to the com.lambdaworks:scrypt library
*/
public class ScryptDerivedKeyParameterSpecReader implements DerivedKeyParameterSpecReader<ScryptDerivedKeyParameterSpec> {
/** Modular Crypt Format containing the parameters encoded as a 32-bit hexadecimal number with a trailing Base64 encoded salt and optional hash */
private static final Pattern MODULAR_CRYPT_FORMAT = Pattern.compile("^\\$s0\\$([a-f0-9]{5,})\\$([\\w/=+]{11,64})\\$?([\\w/=+]{1,256})?$");
private static final int PARAMETERS_GROUP = 1;
private static final int SALT_GROUP = 2;
private static final Charset PARAMETERS_CHARACTER_SET = StandardCharsets.US_ASCII;
private static final int HEXADECIMAL_RADIX = 16;
private static final int LOG_BASE_2 = 2;
private static final int COST_BITS = 16;
private static final int SIZE_BITS = 8;
private static final int SIXTEEN_BIT_SHIFT = 0xffff;
private static final int EIGHT_BIT_SHIFT = 0xff;
private static final Base64.Decoder decoder = Base64.getDecoder();
@Override
public ScryptDerivedKeyParameterSpec read(final byte[] serializedParameters) {
Objects.requireNonNull(serializedParameters, "Parameters required");
final String parameters = new String(serializedParameters, PARAMETERS_CHARACTER_SET);
final Matcher matcher = MODULAR_CRYPT_FORMAT.matcher(parameters);
if (matcher.matches()) {
final String parametersGroup = matcher.group(PARAMETERS_GROUP);
final String saltGroup = matcher.group(SALT_GROUP);
return readParameters(parametersGroup, saltGroup);
} else {
final String message = String.format("scrypt serialized parameters [%s] format not matched", parameters);
throw new IllegalArgumentException(message);
}
}
private ScryptDerivedKeyParameterSpec readParameters(final String parametersEncoded, final String saltEncoded) {
final long parameters = Long.parseLong(parametersEncoded, HEXADECIMAL_RADIX);
final long costExponent = parameters >> COST_BITS & SIXTEEN_BIT_SHIFT;
final int cost = (int) Math.pow(LOG_BASE_2, costExponent);
final int blockSize = (int) parameters >> SIZE_BITS & EIGHT_BIT_SHIFT;
final int parallelization = (int) parameters & EIGHT_BIT_SHIFT;
final byte[] salt = decoder.decode(saltEncoded);
return new ScryptDerivedKeyParameterSpec(cost, blockSize, parallelization, salt);
}
}

View File

@ -1,96 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.scrypt;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeyProvider;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.DerivedSecretKey;
import org.bouncycastle.crypto.generators.SCrypt;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* scrypt implementation of Derived Key Provider based on Bouncy Castle scrypt components described in RFC 7914
*/
public class ScryptDerivedKeyProvider implements DerivedKeyProvider<ScryptDerivedKeyParameterSpec> {
private static final String SERIALIZED_FORMAT = "$s0$%s$%s$%s";
private static final int HEXADECIMAL_RADIX = 16;
private static final int LOG_BASE_2 = 2;
private static final int COST_BITS = 16;
private static final int SIZE_BITS = 8;
private static final Charset PASSWORD_CHARACTER_SET = StandardCharsets.UTF_8;
private static final Base64.Encoder encoder = Base64.getEncoder().withoutPadding();
/**
* Get Derived Key using scrypt and provided specification
*
* @param derivedKeySpec Derived Key Specification
* @return Derived Secret Key
*/
@Override
public DerivedKey getDerivedKey(final DerivedKeySpec<ScryptDerivedKeyParameterSpec> derivedKeySpec) {
final byte[] password = new String(derivedKeySpec.getPassword()).getBytes(PASSWORD_CHARACTER_SET);
final ScryptDerivedKeyParameterSpec parameterSpec = derivedKeySpec.getParameterSpec();
final byte[] salt = parameterSpec.getSalt();
final int cost = parameterSpec.getCost();
final int blockSize = parameterSpec.getBlockSize();
final int parallelization = parameterSpec.getParallelization();
final int derivedKeyLength = derivedKeySpec.getDerivedKeyLength();
final byte[] derivedKeyBytes = SCrypt.generate(password, salt, cost, blockSize, parallelization, derivedKeyLength);
final String serialized = getSerialized(derivedKeyBytes, parameterSpec);
return new DerivedSecretKey(derivedKeyBytes, derivedKeySpec.getAlgorithm(), serialized);
}
private String getSerialized(final byte[] derivedKeyBytes, final ScryptDerivedKeyParameterSpec parameterSpec) {
final String parametersEncoded = getParametersEncoded(parameterSpec);
final String derivedKeyEncoded = encoder.encodeToString(derivedKeyBytes);
final String saltEncoded = encoder.encodeToString(parameterSpec.getSalt());
return String.format(
SERIALIZED_FORMAT,
parametersEncoded,
saltEncoded,
derivedKeyEncoded
);
}
private String getParametersEncoded(final ScryptDerivedKeyParameterSpec parameterSpec) {
final long cost = log2(parameterSpec.getCost()) << COST_BITS;
final long blockSize = parameterSpec.getBlockSize() << SIZE_BITS;
final long parallelization = parameterSpec.getParallelization();
final long parameters = cost | blockSize | parallelization;
return Long.toString(parameters, HEXADECIMAL_RADIX);
}
private long log2(final int number) {
final double log = Math.log(number);
final double logBase2 = Math.log(LOG_BASE_2);
final double log2 = log / logBase2;
return Math.round(log2);
}
}

View File

@ -1,86 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.argon2;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
class Argon2DerivedKeyParameterSpecReaderTest {
private static final byte[] STRING_PARAMETERS = String.class.getSimpleName().getBytes(StandardCharsets.US_ASCII);
private static final int MEMORY = 65536;
private static final int ITERATIONS = 2;
private static final int PARALLELISM = 1;
private static final String ARGON2_SALT_STRING = "QXJnb24yU2FsdFN0cmluZw";
private static final String PARAMETERS = String.format("$argon2id$v=19$m=%d,t=%d,p=%d$%s", MEMORY, ITERATIONS, PARALLELISM, ARGON2_SALT_STRING);
private static final String PARAMETERS_HASH = String.format("%s$6LOmoOXYJV0tXBJtxtD1Mg", PARAMETERS);
Base64.Decoder decoder = Base64.getDecoder();
Argon2DerivedKeyParameterSpecReader reader;
@BeforeEach
void setReader() {
reader = new Argon2DerivedKeyParameterSpecReader();
}
@Test
void testReadException() {
assertThrows(IllegalArgumentException.class, () -> reader.read(STRING_PARAMETERS));
}
@Test
void testRead() {
final byte[] serializedParameters = PARAMETERS.getBytes(StandardCharsets.US_ASCII);
final Argon2DerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
@Test
void testReadHash() {
final byte[] serializedParameters = PARAMETERS_HASH.getBytes(StandardCharsets.US_ASCII);
final Argon2DerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
private void assertParameterSpecEquals(final Argon2DerivedKeyParameterSpec parameterSpec) {
assertNotNull(parameterSpec);
assertEquals(MEMORY, parameterSpec.getMemory());
assertEquals(ITERATIONS, parameterSpec.getIterations());
assertEquals(PARALLELISM, parameterSpec.getParallelism());
final byte[] salt = decoder.decode(ARGON2_SALT_STRING);
assertArrayEquals(salt, parameterSpec.getSalt());
}
}

View File

@ -1,79 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
class BcryptDerivedKeyParameterSpecReaderTest {
private static final byte[] STRING_PARAMETERS = String.class.getSimpleName().getBytes(StandardCharsets.US_ASCII);
private static final int COST = 12;
private static final String SALT_ENCODED = "R9h/cIPz0gi.URNNX3kh2O";
private static final String HASH = "PST9/PgBkqquzi.Ss7KIUgO2t0jWMUW";
private static final String SERIALIZED = String.format("$2a$%d$%s", COST, SALT_ENCODED);
private static final String SERIALIZED_HASH = String.format("%s%s", SERIALIZED, HASH);
BcryptDerivedKeyParameterSpecReader reader;
@BeforeEach
void setReader() {
reader = new BcryptDerivedKeyParameterSpecReader();
}
@Test
void testReadException() {
assertThrows(IllegalArgumentException.class, () -> reader.read(STRING_PARAMETERS));
}
@Test
void testRead() {
final byte[] serializedParameters = SERIALIZED.getBytes(StandardCharsets.US_ASCII);
final BcryptDerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
@Test
void testReadHash() {
final byte[] serializedParameters = SERIALIZED_HASH.getBytes(StandardCharsets.US_ASCII);
final BcryptDerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
private void assertParameterSpecEquals(final BcryptDerivedKeyParameterSpec parameterSpec) {
assertNotNull(parameterSpec);
assertEquals(COST, parameterSpec.getCost());
final byte[] salt = BcryptBase64Decoder.decode(SALT_ENCODED);
assertArrayEquals(salt, parameterSpec.getSalt());
}
}

View File

@ -1,97 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.bcrypt;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.StandardDerivedKeySpec;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class BcryptDerivedKeyProviderTest {
private static final String PASSWORD = "abc123xyz";
private static final int COST = 12;
private static final String SALT_ENCODED = "R9h/cIPz0gi.URNNX3kh2O";
private static final String HASH = "PST9/PgBkqquzi.Ss7KIUgO2t0jWMUW";
private static final String SERIALIZED = String.format("$2a$%d$%s%s", COST, SALT_ENCODED, HASH);
private static final Charset SERIALIZED_CHARACTER_SET = StandardCharsets.US_ASCII;
private static final int DERIVED_KEY_LENGTH = 16;
private static final String ALGORITHM = "AES";
private static final String DIGEST_ALGORITHM = "SHA-512";
BcryptDerivedKeyProvider provider;
@BeforeEach
void setProvider() {
provider = new BcryptDerivedKeyProvider();
}
@Test
void testGetDerivedKey() {
final byte[] salt = BcryptBase64Decoder.decode(SALT_ENCODED);
final BcryptDerivedKeyParameterSpec parameterSpec = new BcryptDerivedKeyParameterSpec(COST, salt);
final DerivedKeySpec<BcryptDerivedKeyParameterSpec> derivedKeySpec = new StandardDerivedKeySpec<>(
PASSWORD.toCharArray(),
DERIVED_KEY_LENGTH,
ALGORITHM,
parameterSpec
);
final DerivedKey derivedKey = provider.getDerivedKey(derivedKeySpec);
assertNotNull(derivedKey);
assertEquals(ALGORITHM, derivedKey.getAlgorithm());
assertEquals(SERIALIZED, derivedKey.getSerialized());
final byte[] encodedHashBytes = HASH.getBytes(SERIALIZED_CHARACTER_SET);
final byte[] digestedDerivedKey = getDerivedKeyBytes(encodedHashBytes);
assertArrayEquals(digestedDerivedKey, derivedKey.getEncoded());
}
private byte[] getDerivedKeyBytes(final byte[] hash) {
final MessageDigest messageDigest = getMessageDigest();
final byte[] digested = messageDigest.digest(hash);
return Arrays.copyOf(digested, DERIVED_KEY_LENGTH);
}
private MessageDigest getMessageDigest() {
try {
return MessageDigest.getInstance(DIGEST_ALGORITHM);
} catch (final NoSuchAlgorithmException e) {
throw new UnsupportedOperationException(DIGEST_ALGORITHM, e);
}
}
}

View File

@ -1,75 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.detection;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.argon2.Argon2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.bcrypt.BcryptDerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.pbkdf2.Pbkdf2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.scrypt.ScryptDerivedKeyParameterSpec;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
class DetectedDerivedKeyParameterSpecReaderTest {
private static final String UNSPECIFIED_PARAMETERS = "unspecified";
private static final String ARGON2_PARAMETERS = "$argon2id$v=19$m=65536,t=2,p=1$QXJnb24yU2FsdFN0cmluZw";
private static final String BCRYPT_PARAMETERS = "$2a$12$R9h/cIPz0gi.URNNX3kh2O";
private static final String SCRYPT_PARAMETERS = "$s0$e0801$epIxT/h6HbbwHaehFnh/bw";
DetectedDerivedKeyParameterSpecReader reader;
@BeforeEach
void setReader() {
reader = new DetectedDerivedKeyParameterSpecReader();
}
@Test
void testArgon2() {
assertParameterSpecInstanceOf(Argon2DerivedKeyParameterSpec.class, ARGON2_PARAMETERS);
}
@Test
void testBcrypt() {
assertParameterSpecInstanceOf(BcryptDerivedKeyParameterSpec.class, BCRYPT_PARAMETERS);
}
@Test
void testScrypt() {
assertParameterSpecInstanceOf(ScryptDerivedKeyParameterSpec.class, SCRYPT_PARAMETERS);
}
@Test
void testPbkdf2() {
assertParameterSpecInstanceOf(Pbkdf2DerivedKeyParameterSpec.class, UNSPECIFIED_PARAMETERS);
}
private void assertParameterSpecInstanceOf(final Class<? extends DerivedKeyParameterSpec> parameterSpecClass, final String parameters) {
final byte[] serializedParameters = parameters.getBytes(StandardCharsets.UTF_8);
final DerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertInstanceOf(parameterSpecClass, parameterSpec);
}
}

View File

@ -1,112 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.detection;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.StandardDerivedKeySpec;
import org.apache.nifi.security.crypto.key.argon2.Argon2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.bcrypt.BcryptDerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.pbkdf2.Pbkdf2DerivedKeyParameterSpec;
import org.apache.nifi.security.crypto.key.scrypt.ScryptDerivedKeyParameterSpec;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@ExtendWith(MockitoExtension.class)
class DetectedDerivedKeyProviderTest {
private static final char[] PASSWORD = {'w', 'o', 'r', 'd'};
private static final int DERIVED_KEY_LENGTH = 16;
private static final String ALGORITHM = "AES";
private static final byte[] SALT = {'N', 'i', 'F', 'i', 'S', 'A', 'L', 'T'};
private static final int MINIMUM_ITERATIONS = 1;
private static final int MINIMUM_ARGON2_MEMORY = 2;
private static final int MINIMUM_PARALLELISM = 1;
private static final int MINIMUM_BCRYPT_COST = 4;
private static final byte[] BCRYPT_SALT = {'S', 'I', 'X', 'T', 'E', 'E', 'N', 'B', 'Y', 'T', 'E', 'S', 'S', 'A', 'L', 'T'};
private static final int MINIMUM_SCRYPT_COST = 2;
private static final int SCRYPT_BLOCK_SIZE = 16;
@Mock
DerivedKeyParameterSpec unsupportedDerivedKeyParameterSpec;
DetectedDerivedKeyProvider provider;
@BeforeEach
void setProvider() {
provider = new DetectedDerivedKeyProvider();
}
@Test
void testArgon2() {
final Argon2DerivedKeyParameterSpec parameterSpec = new Argon2DerivedKeyParameterSpec(MINIMUM_ARGON2_MEMORY, MINIMUM_ITERATIONS, MINIMUM_PARALLELISM, SALT);
assertDerivedKey(parameterSpec);
}
@Test
void testBcrypt() {
final BcryptDerivedKeyParameterSpec parameterSpec = new BcryptDerivedKeyParameterSpec(MINIMUM_BCRYPT_COST, BCRYPT_SALT);
assertDerivedKey(parameterSpec);
}
@Test
void testPbkdf2() {
final Pbkdf2DerivedKeyParameterSpec parameterSpec = new Pbkdf2DerivedKeyParameterSpec(MINIMUM_ITERATIONS, SALT);
assertDerivedKey(parameterSpec);
}
@Test
void testScrypt() {
final ScryptDerivedKeyParameterSpec parameterSpec = new ScryptDerivedKeyParameterSpec(MINIMUM_SCRYPT_COST, SCRYPT_BLOCK_SIZE, MINIMUM_PARALLELISM, SALT);
assertDerivedKey(parameterSpec);
}
@Test
void testUnsupported() {
final DerivedKeySpec<DerivedKeyParameterSpec> derivedKeySpec = getDerivedKeySpec(unsupportedDerivedKeyParameterSpec);
assertThrows(UnsupportedOperationException.class, () -> provider.getDerivedKey(derivedKeySpec));
}
private <T extends DerivedKeyParameterSpec> DerivedKeySpec<T> getDerivedKeySpec(final T parameterSpec) {
return new StandardDerivedKeySpec<>(PASSWORD, DERIVED_KEY_LENGTH, ALGORITHM, parameterSpec);
}
private <T extends DerivedKeyParameterSpec> void assertDerivedKey(final T parameterSpec) {
final DerivedKeySpec<DerivedKeyParameterSpec> derivedKeySpec = getDerivedKeySpec(parameterSpec);
final DerivedKey derivedKey = provider.getDerivedKey(derivedKeySpec);
assertNotNull(derivedKey);
}
}

View File

@ -1,48 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.pbkdf2;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class Pbkdf2DerivedKeyParameterSpecReaderTest {
private static final String STRING_PARAMETERS = String.class.getName();
Pbkdf2DerivedKeyParameterSpecReader reader;
@BeforeEach
void setReader() {
reader = new Pbkdf2DerivedKeyParameterSpecReader();
}
@Test
void testRead() {
final byte[] serializedParameters = STRING_PARAMETERS.getBytes(StandardCharsets.US_ASCII);
final Pbkdf2DerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertNotNull(parameterSpec);
assertEquals(Pbkdf2DerivedKeyParameterSpecReader.VERSION_0_5_0_ITERATIONS, parameterSpec.getIterations());
assertArrayEquals(serializedParameters, parameterSpec.getSalt());
}
}

View File

@ -1,88 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.scrypt;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
class ScryptDerivedKeyParameterSpecReaderTest {
private static final byte[] STRING_PARAMETERS = String.class.getSimpleName().getBytes(StandardCharsets.US_ASCII);
private static final int COST = 16384;
private static final int BLOCK_SIZE = 8;
private static final int PARALLELIZATION = 1;
private static final String SALT_ENCODED = "epIxT/h6HbbwHaehFnh/bw";
private static final String HASH = "7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0";
private static final String SERIALIZED = String.format("$s0$e0801$%s", SALT_ENCODED);
private static final String SERIALIZED_HASH = String.format("%s$%s", SERIALIZED, HASH);
private static final Base64.Decoder decoder = Base64.getDecoder();
ScryptDerivedKeyParameterSpecReader reader;
@BeforeEach
void setReader() {
reader = new ScryptDerivedKeyParameterSpecReader();
}
@Test
void testReadException() {
assertThrows(IllegalArgumentException.class, () -> reader.read(STRING_PARAMETERS));
}
@Test
void testRead() {
final byte[] serializedParameters = SERIALIZED.getBytes(StandardCharsets.US_ASCII);
final ScryptDerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
@Test
void testReadHash() {
final byte[] serializedParameters = SERIALIZED_HASH.getBytes(StandardCharsets.US_ASCII);
final ScryptDerivedKeyParameterSpec parameterSpec = reader.read(serializedParameters);
assertParameterSpecEquals(parameterSpec);
}
private void assertParameterSpecEquals(final ScryptDerivedKeyParameterSpec parameterSpec) {
assertNotNull(parameterSpec);
assertEquals(COST, parameterSpec.getCost());
assertEquals(BLOCK_SIZE, parameterSpec.getBlockSize());
assertEquals(PARALLELIZATION, parameterSpec.getParallelization());
final byte[] salt = decoder.decode(SALT_ENCODED);
assertArrayEquals(salt, parameterSpec.getSalt());
}
}

View File

@ -1,80 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.security.crypto.key.scrypt;
import org.apache.nifi.security.crypto.key.DerivedKey;
import org.apache.nifi.security.crypto.key.DerivedKeySpec;
import org.apache.nifi.security.crypto.key.StandardDerivedKeySpec;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Base64;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
class ScryptDerivedKeyProviderTest {
private static final String PASSWORD = "secret";
private static final int COST = 16384;
private static final int BLOCK_SIZE = 8;
private static final int PARALLELIZATION = 1;
private static final String SALT_ENCODED = "epIxT/h6HbbwHaehFnh/bw";
private static final String HASH = "7H0vsXlY8UxxyW/BWx/9GuY7jEvGjT71GFd6O4SZND0";
private static final String SERIALIZED = String.format("$s0$e0801$%s$%s", SALT_ENCODED, HASH);
private static final int DERIVED_KEY_LENGTH = 32;
private static final String ALGORITHM = "AES";
private static final Base64.Decoder decoder = Base64.getDecoder();
ScryptDerivedKeyProvider provider;
@BeforeEach
void setProvider() {
provider = new ScryptDerivedKeyProvider();
}
@Test
void testGetDerivedKey() {
final byte[] salt = decoder.decode(SALT_ENCODED);
final ScryptDerivedKeyParameterSpec parameterSpec = new ScryptDerivedKeyParameterSpec(COST, BLOCK_SIZE, PARALLELIZATION, salt);
final DerivedKeySpec<ScryptDerivedKeyParameterSpec> derivedKeySpec = new StandardDerivedKeySpec<>(
PASSWORD.toCharArray(),
DERIVED_KEY_LENGTH,
ALGORITHM,
parameterSpec
);
final DerivedKey derivedKey = provider.getDerivedKey(derivedKeySpec);
assertNotNull(derivedKey);
assertEquals(ALGORITHM, derivedKey.getAlgorithm());
assertEquals(SERIALIZED, derivedKey.getSerialized());
final byte[] hashBytes = decoder.decode(HASH);
assertArrayEquals(hashBytes, derivedKey.getEncoded());
}
}

View File

@ -30,11 +30,6 @@
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-utils</artifactId>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-security-crypto-key</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opentest4j</groupId>
<artifactId>opentest4j</artifactId>