package gov.samhsa.acs.documentsegmentation.tools;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import gov.samhsa.acs.brms.domain.Confidentiality;
import gov.samhsa.acs.brms.domain.ObligationPolicyDocument;
import gov.samhsa.acs.brms.domain.RefrainPolicy;
import gov.samhsa.acs.brms.domain.RuleExecutionContainer;
import gov.samhsa.acs.brms.domain.RuleExecutionResponse;
import gov.samhsa.acs.brms.domain.Sensitivity;
import gov.samhsa.acs.brms.domain.UsPrivacyLaw;
import gov.samhsa.acs.common.exception.DS4PException;
import gov.samhsa.acs.common.tool.DocumentXmlConverterImpl;
import gov.samhsa.acs.common.tool.FileReaderImpl;
import gov.samhsa.acs.common.util.EncryptTool;
import gov.samhsa.consent2share.commonunit.xml.XmlComparator;
import java.io.IOException;
import java.security.Key;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.apache.xml.security.encryption.EncryptedKey;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class DocumentEncrypterImplTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private static FileReaderImpl fileReader;
private static DocumentXmlConverterImpl documentXmlConverter;
private static String c32;
private static Document c32Document;
private static String testEncrypted;
private static RuleExecutionContainer ruleExecutionContainer;
private static final String ENCRYPTION_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ClinicalDocument xmlns=\"urn:hl7-org:v3\" xmlns:sdtc=\"urn:hl7-org:sdtc\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> <xenc:EncryptedData xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\" Type=\"http://www.w3.org/2001/04/xmlenc#Content\"> <xenc:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#aes128-cbc\"/> <ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><xenc:EncryptedKey xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\"> <xenc:EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#kw-tripledes\"/> <xenc:CipherData> <xenc:CipherValue>/ykRTBcO+EGKwVAniQQd7rJIRZERuhUVEG2RSRVi5SY=</xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedKey> </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue>";
private static DocumentEncrypterImpl documentEncrypter;
@Before
public void setUp() throws Exception {
fileReader = new FileReaderImpl();
documentXmlConverter = new DocumentXmlConverterImpl();
documentEncrypter = new DocumentEncrypterImpl(documentXmlConverter);
c32 = fileReader.readFile("sampleC32/c32.xml");
c32Document = documentXmlConverter.loadDocument(c32);
testEncrypted = fileReader.readFile("testEncrypted.xml");
ruleExecutionContainer = setRuleExecutionContainer();
}
@Test
public void testEncryptElement() {
// Arrange
Key aesSymmetricKey = null;
Key deSedeEncryptKey = null;
EncryptedKey encryptedKey = null;
Element rootElement = null;
try {
aesSymmetricKey = EncryptTool.generateDataEncryptionKey();
deSedeEncryptKey = EncryptTool.generateKeyEncryptionKey();
String algorithmURI = XMLCipher.TRIPLEDES_KeyWrap;
XMLCipher keyCipher = XMLCipher.getInstance(algorithmURI);
keyCipher.init(XMLCipher.WRAP_MODE, deSedeEncryptKey);
encryptedKey = keyCipher.encryptKey(c32Document, aesSymmetricKey);
rootElement = c32Document.getDocumentElement();
String notEncrypted = documentXmlConverter
.convertXmlDocToString(c32Document);
// Act
documentEncrypter.encryptElement(c32Document, aesSymmetricKey,
encryptedKey, rootElement);
String encrypted = documentXmlConverter
.convertXmlDocToString(c32Document);
logger.debug("NOT ENCRYPTED--> " + notEncrypted);
logger.debug("ENCRYPTED--> " + encrypted);
// Assert
assertNotEquals(notEncrypted, encrypted);
assertTrue(XmlComparator.compareXMLs(testEncrypted, encrypted,
Arrays.asList("CipherData")).similar());
} catch (Exception e) {
logger.error(e.getMessage(), e);
fail(e.getMessage().toString());
}
}
@Test
public void testEncryptDocument() throws SAXException, IOException {
// Act
logger.debug("NOT ENCRYPTED--> " + c32);
String encrypted = null;
try {
encrypted = documentEncrypter.encryptDocument(
EncryptTool.generateKeyEncryptionKey(), c32,
ruleExecutionContainer);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
logger.debug("ENCRYPTED--> " + encrypted);
// Assert
assertNotEquals(c32, encrypted);
assertTrue(XmlComparator.compareXMLs(testEncrypted, encrypted,
Arrays.asList("CipherData")).similar());
}
@Test
public void testEncryptDocument_EmptyRuleExecutionContainer() {
// Act
logger.debug("NOT ENCRYPTED--> " + c32);
String encrypted = null;
try {
List<RuleExecutionResponse> list = new LinkedList<RuleExecutionResponse>();
RuleExecutionContainer container = new RuleExecutionContainer();
container.setExecutionResponseList(list);
encrypted = documentEncrypter.encryptDocument(
EncryptTool.generateKeyEncryptionKey(), c32, container);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
logger.debug("ENCRYPTED--> " + encrypted);
// Assert
assertNotEquals(c32, encrypted);
assertNull(encrypted);
}
@Test
public void testEncryptDocument_NoEncryptObligationPolicy() {
// Act
logger.debug("NOT ENCRYPTED--> " + c32);
String encrypted = null;
try {
List<RuleExecutionResponse> list = new LinkedList<RuleExecutionResponse>();
RuleExecutionContainer container = new RuleExecutionContainer();
RuleExecutionResponse resp = new RuleExecutionResponse();
resp.setDocumentRefrainPolicy(RefrainPolicy.NOVIP);
list.add(resp);
container.setExecutionResponseList(list);
encrypted = documentEncrypter.encryptDocument(
EncryptTool.generateKeyEncryptionKey(), c32, container);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
logger.debug("ENCRYPTED--> " + encrypted);
// Assert
assertNotEquals(c32, encrypted);
assertNull(encrypted);
}
@Test(expected = DS4PException.class)
public void testEncryptDocument_Throws_DS4PException()
throws XMLEncryptionException, Exception {
// Empty xml file
documentEncrypter.encryptDocument(
EncryptTool.generateDataEncryptionKey(), "",
ruleExecutionContainer);
}
private static RuleExecutionContainer setRuleExecutionContainer() {
RuleExecutionContainer container = new RuleExecutionContainer();
RuleExecutionResponse r1 = new RuleExecutionResponse();
r1.setC32SectionLoincCode("11450-4");
r1.setC32SectionTitle("Problems");
r1.setCode("66214007");
r1.setCodeSystemName("SNOMED CT");
r1.setDisplayName("Substance Abuse Disorder");
r1.setDocumentObligationPolicy(ObligationPolicyDocument.ENCRYPT);
r1.setDocumentRefrainPolicy(RefrainPolicy.NODSCLCD);
r1.setImpliedConfSection(Confidentiality.R);
r1.setItemAction("REDACT");
r1.setObservationId("e11275e7-67ae-11db-bd13-0800200c9a66b827vs52h7");
r1.setSensitivity(Sensitivity.ETH);
r1.setUSPrivacyLaw(UsPrivacyLaw._42CFRPart2);
RuleExecutionResponse r2 = new RuleExecutionResponse();
r2.setC32SectionLoincCode("11450-4");
r2.setC32SectionTitle("Problems");
r2.setCode("111880001");
r2.setCodeSystemName("SNOMED CT");
r2.setDisplayName("Acute HIV");
r2.setDocumentObligationPolicy(ObligationPolicyDocument.ENCRYPT);
r2.setDocumentRefrainPolicy(RefrainPolicy.NODSCLCD);
r2.setImpliedConfSection(Confidentiality.R);
r2.setItemAction("MASK");
r2.setObservationId("d11275e7-67ae-11db-bd13-0800200c9a66");
r2.setSensitivity(Sensitivity.HIV);
r2.setUSPrivacyLaw(UsPrivacyLaw._42CFRPart2);
List<RuleExecutionResponse> list = new LinkedList<RuleExecutionResponse>();
list.add(r1);
list.add(r2);
container.setExecutionResponseList(list);
return container;
}
}