From a39375a742af8e1ade5e771d408efd7179e07568 Mon Sep 17 00:00:00 2001 From: IanHowell Date: Fri, 13 Apr 2018 15:05:52 -0500 Subject: [PATCH] Increase coverage of cadi-aaf Issue-ID: AAF-223 Change-Id: Ie58cec591d7107dc360088657dbcf279c84fe3f7 Signed-off-by: IanHowell --- .../java/org/onap/aaf/cadi/cm/test/JU_Factory.java | 284 +++++++++++++++++++-- cadi/aaf/src/test/resources/exampleCertificate.cer | 59 +++++ 2 files changed, 323 insertions(+), 20 deletions(-) create mode 100755 cadi/aaf/src/test/resources/exampleCertificate.cer diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java index e4eaf7fb..3c72d8ff 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java @@ -27,16 +27,35 @@ import static org.mockito.Mockito.*; import org.junit.*; import org.mockito.*; +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; import java.security.KeyPair; +import java.security.Principal; +import java.security.PrivateKey; import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import javax.crypto.Cipher; +import org.onap.aaf.cadi.cm.CertException; import org.onap.aaf.cadi.cm.Factory; import org.onap.aaf.cadi.cm.Factory.StripperInputStream; +import org.onap.aaf.cadi.cm.Factory.Base64InputStream; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.LogTarget; import org.onap.aaf.misc.env.TimeTaken; @@ -53,24 +72,71 @@ public class JU_Factory { @Mock LogTarget logTargetMock; + @Mock + X509Certificate x509CertMock; + + @Mock + Certificate certMock; + + @Mock + Principal subjectDN; + + private final String resourceDirName = "src/test/resources"; + private File resourceDir; + private File publicKeyFile; + private File privateKeyFile; + private File certFile; + + private static final String message = "The quick brown fox jumps over the lazy dog."; + + private static final String subjectDNText = "subjectDN"; + private static final String certText = "Some text that might be included in a certificate"; + @Before - public void setup() { + public void setup() throws CertificateEncodingException { MockitoAnnotations.initMocks(this); + resourceDir = new File(resourceDirName); + resourceDir.mkdirs(); + publicKeyFile = new File(resourceDirName, "/publicKey"); + privateKeyFile = new File(resourceDirName, "/privateKey"); + publicKeyFile.delete(); + privateKeyFile.delete(); + + certFile = new File(resourceDirName + "/exampleCertificate.cer"); + when(transMock.start(anyString(), anyInt())).thenReturn(timeTakenMock); when(transMock.debug()).thenReturn(logTargetMock); + + when(subjectDN.toString()).thenReturn(subjectDNText); + + when(x509CertMock.getSubjectDN()).thenReturn(subjectDN); + when(x509CertMock.getEncoded()).thenReturn(certText.getBytes()); + + when(certMock.getEncoded()).thenReturn(certText.getBytes()); + } + + @After + public void tearDown() { + publicKeyFile = new File(resourceDirName, "/publicKey"); + privateKeyFile = new File(resourceDirName, "/privateKey"); + publicKeyFile.delete(); + privateKeyFile.delete(); + + if (resourceDir.list().length == 0) { + resourceDir.delete(); + } } @Test public void generateKeyPairTest() throws Exception { - String message = "The quick brown fox jumps over the lazy dog."; - - Cipher encryptor = Cipher.getInstance(Factory.KEY_ALGO); - Cipher decryptor = Cipher.getInstance(Factory.KEY_ALGO); + // This instatiation isn't actually necessary, but it gets coverage + Cipher encryptor = Factory.pkCipher(); + Cipher decryptor = Factory.pkCipher(); KeyPair kp1 = Factory.generateKeyPair(transMock); - encryptor.init(Cipher.ENCRYPT_MODE, kp1.getPublic()); - decryptor.init(Cipher.DECRYPT_MODE, kp1.getPrivate()); + encryptor = Factory.pkCipher(kp1.getPublic(), true); + decryptor = Factory.pkCipher(kp1.getPrivate(), false); byte[] encrypedMessage1 = encryptor.doFinal(message.getBytes(StandardCharsets.UTF_8)); String output1 = new String(decryptor.doFinal(encrypedMessage1)); assertThat(output1, is(message)); @@ -78,35 +144,213 @@ public class JU_Factory { // coverage when(transMock.start("Generate KeyPair", Env.SUB)).thenReturn(null); KeyPair kp2 = Factory.generateKeyPair(transMock); - encryptor.init(Cipher.ENCRYPT_MODE, kp2.getPublic()); - decryptor.init(Cipher.DECRYPT_MODE, kp2.getPrivate()); + encryptor = Factory.pkCipher(kp2.getPublic(), true); + decryptor = Factory.pkCipher(kp2.getPrivate(), false); byte[] encrypedMessage2 = encryptor.doFinal(message.getBytes(StandardCharsets.UTF_8)); String output2 = new String(decryptor.doFinal(encrypedMessage2)); assertThat(output2, is(message)); KeyPair kp3 = Factory.generateKeyPair(null); - encryptor.init(Cipher.ENCRYPT_MODE, kp3.getPublic()); - decryptor.init(Cipher.DECRYPT_MODE, kp3.getPrivate()); + encryptor = Factory.pkCipher(kp3.getPublic(), true); + decryptor = Factory.pkCipher(kp3.getPrivate(), false); byte[] encrypedMessage3 = encryptor.doFinal(message.getBytes(StandardCharsets.UTF_8)); String output3 = new String(decryptor.doFinal(encrypedMessage3)); assertThat(output3, is(message)); } @Test - public void keyToStringTest() throws IOException { + public void keyStringManipTest() throws Exception { KeyPair kp = Factory.generateKeyPair(transMock); String publicKeyString = Factory.toString(transMock, kp.getPublic()); String privateKeyString = Factory.toString(transMock, kp.getPrivate()); - String[] publicKeyLines = publicKeyString.split("\n", 0); - assertThat(publicKeyLines.length, is(9)); - assertThat(publicKeyLines[0], is("-----BEGIN PUBLIC KEY-----")); - assertThat(publicKeyLines[8], is("-----END PUBLIC KEY-----")); + assertThat(publicKeyString.startsWith("-----BEGIN PUBLIC KEY-----"), is(true)); + assertThat(publicKeyString.endsWith("-----END PUBLIC KEY-----\n"), is(true)); + + assertThat(privateKeyString.startsWith("-----BEGIN PRIVATE KEY-----"), is(true)); + assertThat(privateKeyString.endsWith("-----END PRIVATE KEY-----\n"), is(true)); + + PublicKey publicKey = Factory.toPublicKey(transMock, cleanupString(publicKeyString)); + PrivateKey privateKey = Factory.toPrivateKey(transMock, cleanupString(privateKeyString)); + + Cipher encryptor = Factory.pkCipher(publicKey, true); + Cipher decryptor = Factory.pkCipher(privateKey, false); + byte[] encrypedMessage = encryptor.doFinal(message.getBytes(StandardCharsets.UTF_8)); + String output = new String(decryptor.doFinal(encrypedMessage)); + assertThat(output, is(message)); + } + + @Test + public void keyFileManipTest() throws Exception { + KeyPair kp = Factory.generateKeyPair(transMock); + + String privateKeyString = Factory.toString(transMock, kp.getPrivate()); + writeToFile(privateKeyFile, privateKeyString, "Header:this line has a header"); + + PublicKey publicKey = kp.getPublic(); + PrivateKey privateKey = Factory.toPrivateKey(transMock, privateKeyFile); - String[] privateKeyLines = privateKeyString.split("\n", 0); - assertThat(privateKeyLines.length, is(28)); - assertThat(privateKeyLines[0], is("-----BEGIN PRIVATE KEY-----")); - assertThat(privateKeyLines[27], is("-----END PRIVATE KEY-----")); + Cipher encryptor = Factory.pkCipher(publicKey, true); + Cipher decryptor = Factory.pkCipher(privateKey, false); + byte[] encrypedMessage = encryptor.doFinal(message.getBytes(StandardCharsets.UTF_8)); + String output = new String(decryptor.doFinal(encrypedMessage)); + assertThat(output, is(message)); + } + + @Test + public void certToStringTest() throws IOException, CertException, CertificateEncodingException { + String certString; + when(logTargetMock.isLoggable()).thenReturn(true); + + certString = Factory.toString(transMock, x509CertMock); + assertThat(certString.startsWith("-----BEGIN CERTIFICATE-----"), is(true)); + assertThat(certString.endsWith("-----END CERTIFICATE-----\n"), is(true)); + + certString = Factory.toString(transMock, certMock); + assertThat(certString.startsWith("-----BEGIN CERTIFICATE-----"), is(true)); + assertThat(certString.endsWith("-----END CERTIFICATE-----\n"), is(true)); + + try { + certString = Factory.toString(transMock, (Certificate)null); + fail("Should have thrown an exception"); + } catch (CertException e) { + assertThat(e.getMessage(), is("Certificate not built")); + } + + when(certMock.getEncoded()).thenThrow(new CertificateEncodingException()); + try { + certString = Factory.toString(transMock, certMock); + fail("Should have thrown an exception"); + } catch (CertException e) { + } + + // coverage + when(logTargetMock.isLoggable()).thenReturn(false); + certString = Factory.toString(transMock, x509CertMock); } + + @Test + public void toX509Test() throws CertificateException, IOException, CertException { + String output; + Collection certs; + when(logTargetMock.isLoggable()).thenReturn(true); + + String certString = readFromFile(certFile, false); + + certs = Factory.toX509Certificate(certString); + // Contrived way of getting a Certificate out of a Collection + output = Factory.toString(transMock, certs.toArray(new Certificate[0])[0]); + assertThat(output, is(certString)); + + certs = Factory.toX509Certificate(transMock, certFile); + // Contrived way of getting a Certificate out of a Collection + output = Factory.toString(transMock, certs.toArray(new Certificate[0])[0]); + assertThat(output, is(certString)); + + List certStrings = new ArrayList(); + certStrings.add(certString); + certStrings.add(certString); + certs = Factory.toX509Certificate(certStrings); + // Contrived way of getting a Certificate out of a Collection + // it doesn't matter which one we get - they're the same + output = Factory.toString(transMock, certs.toArray(new Certificate[0])[0]); + assertThat(output, is(certString)); + } + + @Test + public void stripperTest() throws Exception { + KeyPair kp = Factory.generateKeyPair(transMock); + String privateKeyString = Factory.toString(transMock, kp.getPrivate()); + writeToFile(privateKeyFile, privateKeyString, "Header:this line has a header"); + + StripperInputStream stripper = new StripperInputStream(privateKeyFile); + + String expected = cleanupString(privateKeyString); + byte[] buffer = new byte[10000]; + stripper.read(buffer); + String output = new String(buffer, 0, expected.length()); + assertThat(output, is(expected)); + stripper.close(); + + // coverage + stripper = new StripperInputStream(new FileInputStream(privateKeyFile)); + stripper.close(); + stripper = new StripperInputStream(new BufferedReader(new FileReader(privateKeyFile))); + stripper.close(); + stripper.close(); // also coverage... + } + + @Test + public void binaryTest() throws IOException { + String output = new String(Factory.binary(certFile)); + String expected = readFromFile(certFile, true); + assertThat(output, is(expected)); + } + + @Test + public void signatureTest() throws Exception { + KeyPair kp = Factory.generateKeyPair(transMock); + String signedString = "Something that needs signing"; + byte[] signedBytes = Factory.sign(transMock, signedString.getBytes(), kp.getPrivate()); + String output = Factory.toSignatureString(signedBytes); + assertThat(output.startsWith("-----BEGIN SIGNATURE-----"), is(true)); + assertThat(output.endsWith("-----END SIGNATURE-----\n"), is(true)); + assertThat(Factory.verify(transMock, signedString.getBytes(), signedBytes, kp.getPublic()), is(true)); + } + + // TODO: Ian - finish these tests + // @Test + // public void base64ISTest() throws Exception { + // KeyPair kp = Factory.generateKeyPair(transMock); + + // String privateKeyString = Factory.toString(transMock, kp.getPrivate()); + // String cleaned = cleanupString(privateKeyString); + // System.out.println(cleaned); + // writeToFile(privateKeyFile, cleaned); + // Base64InputStream b64is = new Base64InputStream(privateKeyFile); + // byte[] buffer = new byte[10000]; + // b64is.read(buffer); + // System.out.println(new String(buffer)); + // b64is.close(); + // } + + // @Test + // public void getSecurityProviderTest() { + // } + + private String cleanupString(String str) { + String[] lines = str.split("\n", 0); + List rawLines = new ArrayList(); + for (int i = 0; i < lines.length - 2; i++) { + rawLines.add(lines[i + 1]); + } + return String.join("", rawLines); + } + + private void writeToFile(File file, String contents) throws Exception { + writeToFile(file, contents, null); + } + + private void writeToFile(File file, String contents, String header) throws Exception { + PrintWriter writer = new PrintWriter(file, "UTF-8"); + if (header != null) { + writer.println(header); + } + writer.println(contents); + writer.close(); + } + + private String readFromFile(File file, boolean addCR) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(file)); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + String lineEnd = (addCR) ? "\r\n" : "\n"; + sb.append(line + lineEnd); + } + br.close(); + return sb.toString(); + } + } diff --git a/cadi/aaf/src/test/resources/exampleCertificate.cer b/cadi/aaf/src/test/resources/exampleCertificate.cer new file mode 100755 index 00000000..76ed12dc --- /dev/null +++ b/cadi/aaf/src/test/resources/exampleCertificate.cer @@ -0,0 +1,59 @@ +-----BEGIN CERTIFICATE----- +MIIKkTCCCXmgAwIBAgIQBO9R08Vvthj6ifmVeLw94DANBgkqhkiG9w0BAQsFADBe +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMR0wGwYDVQQDExRHZW9UcnVzdCBSU0EgQ0EgMjAxODAe +Fw0xODAzMjUwMDAwMDBaFw0xOTA0MjMxMjAwMDBaMIGaMQswCQYDVQQGEwJVUzET +MBEGA1UECBMKQ2FsaWZvcm5pYTEXMBUGA1UEBxMOUmVkd29vZCBTaG9yZXMxGzAZ +BgNVBAoTEk9yYWNsZSBDb3Jwb3JhdGlvbjEnMCUGA1UECxMeQ29udGVudCBNYW5h +Z2VtZW50IFNlcnZpY2VzIElUMRcwFQYDVQQDEw53d3cub3JhY2xlLmNvbTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMWDD1iqkoFspX8qhH6HvcEkOtG7 +x5yQQzGO2qr4FzZxzBUsi4fOm33e+wD+H+zRi2u/5GPKr6f6GNT50IQJR6Bg5ReX +co3nbL0XmqjxMmncM7UkgGwFynzW/AMZ6TobMhtKFiHgCHanXGxMJgZmw9JW0qkf +pHRsTa/OBnxV16tu4cAIHoVb5ZkJH0qSXKSdhj4KKM6Uajr4QxS7YQQTr51MAlDa +Xe3tWTaJv3TjMpzD23a8xfhNRDWp6JiN2l/tK30SiOOS68hEByG1oPA3TRRzzixz +VEf8ANDx6prQfhb+Aior5UcBRFry6IU3h3W4aTSa2k+kBCwGgdNkX0deXqsCAwEA +AaOCBwwwggcIMB8GA1UdIwQYMBaAFJBY/7CcdahRVHex7fKjQxY4nmzFMB0GA1Ud +DgQWBBQ7gL1OQ/z3NZBU4xwB7jtfv1rykzCCBH8GA1UdEQSCBHYwggRygg53d3cu +b3JhY2xlLmNvbYIKb3JhY2xlLmNvbYISc3VwcG9ydC5vcmFjbGUuY29tgg9tYXBz +Lm9yYWNsZS5jb22CFG9yYWNsZWZvdW5kYXRpb24ub3JnghVmdXNpb25oZWxwLm9y +YWNsZS5jb22CFHByZXNzcm9vbS5vcmFjbGUuY29tggt3d3cuZ28uamF2YYIIamF2 +YS5jb22CEXNlYXJjaC5vcmFjbGUuY29tghBibG9ncy5vcmFjbGUuY29tghB3aWtp +cy5vcmFjbGUuY29tggxjbG91ZC5vcmFjbGWCFGNuLmZvcnVtcy5vcmFjbGUuY29t +ghRteWJ1aWxkZXIub3JhY2xlLmNvbYIXZGlnaXRhbG1lZGlhLm9yYWNsZS5jb22C +GGZpbi1mdXNpb25jcm0ub3JhY2xlLmNvbYIRZm9ydW1zLm9yYWNsZS5jb22CEGNs +b3VkLm9yYWNsZS5jb22CG2JpYXBwcy1mdXNpb25jcm0ub3JhY2xlLmNvbYIUY29t +bXVuaXR5Lm9yYWNsZS5jb22CFGRldmVsb3Blci5vcmFjbGUuY29tghRlbG9jYXRp +b24ub3JhY2xlLmNvbYIScHJvZmlsZS5vcmFjbGUuY29tghdpYy1mdXNpb25jcm0u +b3JhY2xlLmNvbYISbXlzaXRlcy5vcmFjbGUuY29tggxtLm9yYWNsZS5jb22CFG15 +cHJvZmlsZS5vcmFjbGUuY29tghFkZXNpZ24ub3JhY2xlLmNvbYILamF2YS5vcmFj +bGWCGGNybS1mdXNpb25jcm0ub3JhY2xlLmNvbYIUZnVzaW9uY3JtLm9yYWNsZS5j +b22CEHNpdGVzLm9yYWNsZS5jb22CD2RvY3Mub3JhY2xlLmNvbYIUbXlwcm9jZXNz +Lm9yYWNsZS5jb22CGGhjbS1mdXNpb25jcm0ub3JhY2xlLmNvbYIRd3d3Lm9yYWNs +ZWltZy5jb22CG2Nsb3VkbWFya2V0cGxhY2Uub3JhY2xlLmNvbYIUZWRlbGl2ZXJ5 +Lm9yYWNsZS5jb22CEGl0d2ViLm9yYWNsZS5jb22CEXN0YXRpYy5vcmFjbGUuY29t +ghRrci5mb3J1bXMub3JhY2xlLmNvbYIMd3d3LmphdmEuY29tghpteXZpc3VhbGl6 +YXRpb24ub3JhY2xlLmNvbYIRZXZlbnRzLm9yYWNsZS5jb22CF2JpLWZ1c2lvbmNy +bS5vcmFjbGUuY29tghh3d3cub3JhY2xlZm91bmRhdGlvbi5vcmeCHHJlc2VsbGVy +ZWR1Y2F0aW9uLm9yYWNsZS5jb22CFGVkdWNhdGlvbi5vcmFjbGUuY29tghhzY20t +ZnVzaW9uY3JtLm9yYWNsZS5jb22CGHByai1mdXNpb25jcm0ub3JhY2xlLmNvbYIW +c2VjdXJlc2l0ZXMub3JhY2xlLmNvbYIYcHJjLWZ1c2lvbmNybS5vcmFjbGUuY29t +ghFwb3J0YWwub3JhY2xlLmNvbYIHZ28uamF2YTAOBgNVHQ8BAf8EBAMCBaAwHQYD +VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMD4GA1UdHwQ3MDUwM6AxoC+GLWh0 +dHA6Ly9jZHAuZ2VvdHJ1c3QuY29tL0dlb1RydXN0UlNBQ0EyMDE4LmNybDBMBgNV +HSAERTBDMDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k +aWdpY2VydC5jb20vQ1BTMAgGBmeBDAECAjB1BggrBgEFBQcBAQRpMGcwJgYIKwYB +BQUHMAGGGmh0dHA6Ly9zdGF0dXMuZ2VvdHJ1c3QuY29tMD0GCCsGAQUFBzAChjFo +dHRwOi8vY2FjZXJ0cy5nZW90cnVzdC5jb20vR2VvVHJ1c3RSU0FDQTIwMTguY3J0 +MAkGA1UdEwQCMAAwggECBgorBgEEAdZ5AgQCBIHzBIHwAO4AdQCkuQmQtBhYFIe7 +E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAWJbje2RAAAEAwBGMEQCICYHgjJanZfY +hZ86nCaMFh4p2qCmO+EUEzsYVbcnihhFAiBTC4OUrYRENk9a3KK3AM3pt8iFfS2j +X18JZGy1cK2h4QB1AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAAB +YluN7x4AAAQDAEYwRAIgNaXytmedMEeBRSCPDye5C2gV4O6uYsYUYx84aLnXRBsC +ICnthPukbEzpfhXC0He5IBOW8OOdsF+Wb5yQE8z5I+5hMA0GCSqGSIb3DQEBCwUA +A4IBAQCC1YtAS4GRpTeQRJnyQfHKkrMemlWCcHIOkUY/d9mIpIlFqMe/jxkhimrX +uM/AfTv+O9fLuknaQ9fYJGJmKlYk1hsKQy0UBfDDFApaBhjpAOkLjASViLzweVMD +aBRWn8Qx5ScgTnMjb8FFizcEM2IMpqXetOkJyn6cu5GtYhDthEOmvdkVJIPpC+cL +i8yesYU8au5Y7ERmHRmJycH7yK6Vl13FYBEUXdR/NoGrc6I3ayiaFiyUf1/HuQEG +HLW0n2oKDk/SVAI9CZh+MuPwqp4eln4YCBIPBdKnGRrgAbaZCCKIkPKmF9k75wNY +7wLi08wEQ4LsvmmLN+H3AZ3IBDbF +-----END CERTIFICATE----- -- 2.16.6