Skip to content

Commit

Permalink
PR comment changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
James Cover jdcove2 committed Jul 27, 2023
1 parent 80a2739 commit 4f1e2e0
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 61 deletions.
74 changes: 20 additions & 54 deletions src/main/java/emissary/core/IBaseDataObjectXmlCodecs.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import emissary.core.channels.InMemoryChannelFactory;
import emissary.core.channels.SeekableByteChannelFactory;
import emissary.core.channels.SeekableByteChannelHelper;
import emissary.util.ByteUtil;
import emissary.util.xml.AbstractJDOMUtil;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.jdom2.Element;
import org.jdom2.Namespace;
Expand All @@ -14,8 +16,6 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.AbstractMap.SimpleEntry;
import java.util.Base64;
import java.util.Collection;
Expand Down Expand Up @@ -275,7 +275,7 @@ public ElementEncoders(
* Implementation of an XML element decoder that has a boolean value.
*/
public static final ElementDecoder DEFAULT_BOOLEAN_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, boolean.class);
final Method method = getIbdoMethod(ibdoMethodName, boolean.class);

for (final Element element : elements) {
method.invoke(ibdo, Boolean.valueOf(element.getValue()));
Expand All @@ -286,7 +286,7 @@ public ElementEncoders(
* Implementation of an XML element decoder that has a SeekableByteChannel value.
*/
public static final ElementDecoder DEFAULT_SEEKABLE_BYTE_CHANNEL_FACTORY_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, SeekableByteChannelFactory.class);
final Method method = getIbdoMethod(ibdoMethodName, SeekableByteChannelFactory.class);

for (final Element element : elements) {
final String elementValue = element.getValue();
Expand All @@ -300,7 +300,7 @@ public ElementEncoders(
* Implementation of an XML element decoder that has a byte array value.
*/
public static final ElementDecoder DEFAULT_BYTE_ARRAY_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, byte[].class);
final Method method = getIbdoMethod(ibdoMethodName, byte[].class);

for (final Element element : elements) {
final String elementValue = element.getValue();
Expand All @@ -314,7 +314,7 @@ public ElementEncoders(
* Implementation of an XML element decoder that has an integer value.
*/
public static final ElementDecoder DEFAULT_INTEGER_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, int.class);
final Method method = getIbdoMethod(ibdoMethodName, int.class);

for (final Element element : elements) {
method.invoke(ibdo, Integer.decode(element.getValue()));
Expand All @@ -325,7 +325,7 @@ public ElementEncoders(
* Implementation of an XML element decoder that has a string value.
*/
public static final ElementDecoder DEFAULT_STRING_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, String.class);
final Method method = getIbdoMethod(ibdoMethodName, String.class);

for (final Element element : elements) {
final String elementValue = element.getValue();
Expand All @@ -340,7 +340,7 @@ public ElementEncoders(
* array.
*/
public static final ElementDecoder DEFAULT_STRING_BYTE_ARRAY_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, String.class, byte[].class);
final Method method = getIbdoMethod(ibdoMethodName, String.class, byte[].class);

for (final Element element : elements) {
final Element nameElement = element.getChild(NAME_ELEMENT_NAME);
Expand All @@ -361,7 +361,7 @@ public ElementEncoders(
* object.
*/
public static final ElementDecoder DEFAULT_STRING_OBJECT_DECODER = (elements, ibdo, ibdoMethodName) -> {
final Method method = IBaseDataObject.class.getDeclaredMethod(ibdoMethodName, String.class, Object.class);
final Method method = getIbdoMethod(ibdoMethodName, String.class, Object.class);

for (final Element element : elements) {
final Element nameElement = element.getChild(NAME_ELEMENT_NAME);
Expand Down Expand Up @@ -427,9 +427,9 @@ public void encode(final List<SeekableByteChannelFactory> values, final Element
private static Element protectedElementHash(final String name, final byte[] bytes) {
final Element element = new Element(name);

if (hasNonPrintableValues(bytes)) {
if (ByteUtil.hasNonPrintableValues(bytes)) {
element.setAttribute(ENCODING_ATTRIBUTE_NAME, SHA256_ATTRIBUTE_NAME);
element.addContent(sha256Bytes(bytes));
element.addContent(ByteUtil.sha256Bytes(bytes));
} else {
element.addContent(new String(bytes, StandardCharsets.ISO_8859_1));
}
Expand Down Expand Up @@ -465,8 +465,8 @@ public void encode(final List<String> values, final Element parentElement, final
for (int i = values.size() - 1; i >= 0; i--) {
String value = values.get(i);

if (PROCESSING_ERROR_ELEMENT_NAME.equals(childElementName)) {
value = value == null ? null : value.substring(0, value.length() - 1);
if (PROCESSING_ERROR_ELEMENT_NAME.equals(childElementName) && StringUtils.isNotEmpty(value)) {
value = value.substring(0, value.length() - 1);
}

if (value != null) {
Expand Down Expand Up @@ -615,25 +615,6 @@ private static Element protectedElement(final String name, final String string)
return protectedElementBase64(name, string.getBytes(StandardCharsets.UTF_8));
}

/**
* Scans a byte array looking for non-printable values.
*
* @param bytes the bytes to be scanned.
* @return whether or not there were non-printable values.
*/
public static boolean hasNonPrintableValues(final byte[] bytes) {
boolean badCharacters = false;

for (byte aByte : bytes) {
if (aByte < 9 || aByte > 13 && aByte < 32) {
badCharacters = true;
break;
}
}

return badCharacters;
}

/**
* Creates a 'protected' element which can be encoded with base64 if it contains unsafe characters
*
Expand All @@ -646,7 +627,7 @@ public static boolean hasNonPrintableValues(final byte[] bytes) {
private static Element protectedElementBase64(final String name, final byte[] bytes) {
final Element element = new Element(name);

if (hasNonPrintableValues(bytes)) {
if (ByteUtil.hasNonPrintableValues(bytes)) {
String base64String = BASE64_NEW_LINE_STRING +
BASE64_ENCODER.encodeToString(bytes) +
BASE64_NEW_LINE_STRING;
Expand All @@ -661,28 +642,13 @@ private static Element protectedElementBase64(final String name, final byte[] by
}

/**
* Creates a hex string of a sha256 hash for a byte[].
* Gets the requested method object from the IBaseDataObject class.
*
* @param bytes to be hashed
* @return the hex string of a sha256 hash of the bytes.
* @throws SecurityException
* @throws NoSuchMethodException
*/
public static String sha256Bytes(final byte[] bytes) {
try {
final MessageDigest md = MessageDigest.getInstance("SHA-256");
final byte[] hash = md.digest(bytes);

final StringBuilder hexString = new StringBuilder(2 * hash.length);
for (byte b : hash) {
final String hex = Integer.toHexString(0xff & b);

if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
return null;
}
private static Method getIbdoMethod(final String name, final Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return IBaseDataObject.class.getDeclaredMethod(name, parameterTypes);
}
}
47 changes: 47 additions & 0 deletions src/main/java/emissary/util/ByteUtil.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package emissary.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -273,6 +275,51 @@ public static String grabLine(byte[] data, int pos) {
return ret;
}

/**
* Scans a byte array looking for non-printable values.
*
* @param bytes the bytes to be scanned.
* @return whether or not there were non-printable values.
*/
public static boolean hasNonPrintableValues(final byte[] bytes) {
boolean badCharacters = false;

for (byte aByte : bytes) {
if (aByte < 9 || aByte > 13 && aByte < 32) {
badCharacters = true;
break;
}
}

return badCharacters;
}

/**
* Creates a hex string of a sha256 hash for a byte[].
*
* @param bytes to be hashed
* @return the hex string of a sha256 hash of the bytes.
*/
public static String sha256Bytes(final byte[] bytes) {
try {
final MessageDigest md = MessageDigest.getInstance("SHA-256");
final byte[] hash = md.digest(bytes);

final StringBuilder hexString = new StringBuilder(2 * hash.length);
for (byte b : hash) {
final String hex = Integer.toHexString(0xff & b);

if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
return null;
}
}

/** This class is not meant to be instantiated. */
private ByteUtil() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import emissary.core.channels.SeekableByteChannelFactory;
import emissary.kff.KffDataObjectHandler;
import emissary.test.core.junit5.UnitTest;
import emissary.util.ByteUtil;
import emissary.util.PlaceComparisonHelper;

import org.jdom2.Document;
Expand Down Expand Up @@ -146,7 +147,7 @@ void testBase64Conversion() throws Exception {
final IBaseDataObject sha256ActualIbdo = ibdoFromXmlFromIbdo(expectedIbdo, expectedChildren, initialIbdo,
actualChildren, SHA256_ELEMENT_ENCODERS);

expectedIbdo.setData(IBaseDataObjectXmlCodecs.sha256Bytes(bytes).getBytes(StandardCharsets.ISO_8859_1));
expectedIbdo.setData(ByteUtil.sha256Bytes(bytes).getBytes(StandardCharsets.ISO_8859_1));

final String sha256Diff = PlaceComparisonHelper.checkDifferences(expectedIbdo, sha256ActualIbdo, expectedChildren,
actualChildren, "testSha256Conversion", DiffCheckConfiguration.onlyCheckData());
Expand Down
17 changes: 11 additions & 6 deletions src/test/java/emissary/test/core/junit5/RegressionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import emissary.core.IBaseDataObjectXmlCodecs;
import emissary.core.IBaseDataObjectXmlCodecs.ElementDecoders;
import emissary.core.IBaseDataObjectXmlCodecs.ElementEncoders;
import emissary.util.ByteUtil;

import com.google.errorprone.annotations.ForOverride;
import org.jdom2.Document;
Expand Down Expand Up @@ -138,8 +139,12 @@ protected ElementEncoders getEncoders() {
@Override
protected void checkAnswersPreHook(final Document answers, final IBaseDataObject payload, final List<IBaseDataObject> attachments,
final String tname) {
if (payload.data() != null && IBaseDataObjectXmlCodecs.hasNonPrintableValues(payload.data())) {
final String hash = IBaseDataObjectXmlCodecs.sha256Bytes(payload.data());
if (!IBaseDataObjectXmlCodecs.SHA256_ELEMENT_ENCODERS.equals(getEncoders())) {
return;
}

if (payload.data() != null && ByteUtil.hasNonPrintableValues(payload.data())) {
final String hash = ByteUtil.sha256Bytes(payload.data());

if (hash != null) {
payload.setData(hash.getBytes(StandardCharsets.UTF_8));
Expand All @@ -148,8 +153,8 @@ protected void checkAnswersPreHook(final Document answers, final IBaseDataObject

if (payload.getExtractedRecords() != null) {
for (final IBaseDataObject extractedRecord : payload.getExtractedRecords()) {
if (IBaseDataObjectXmlCodecs.hasNonPrintableValues(extractedRecord.data())) {
final String hash = IBaseDataObjectXmlCodecs.sha256Bytes(extractedRecord.data());
if (ByteUtil.hasNonPrintableValues(extractedRecord.data())) {
final String hash = ByteUtil.sha256Bytes(extractedRecord.data());

if (hash != null) {
extractedRecord.setData(hash.getBytes(StandardCharsets.UTF_8));
Expand All @@ -160,8 +165,8 @@ protected void checkAnswersPreHook(final Document answers, final IBaseDataObject

if (attachments != null) {
for (final IBaseDataObject attachment : attachments) {
if (IBaseDataObjectXmlCodecs.hasNonPrintableValues(attachment.data())) {
final String hash = IBaseDataObjectXmlCodecs.sha256Bytes(attachment.data());
if (ByteUtil.hasNonPrintableValues(attachment.data())) {
final String hash = ByteUtil.sha256Bytes(attachment.data());

if (hash != null) {
attachment.setData(hash.getBytes(StandardCharsets.UTF_8));
Expand Down

0 comments on commit 4f1e2e0

Please sign in to comment.