package org.basex;
import static org.junit.Assert.*;
import java.io.*;
import java.security.*;
import org.basex.core.*;
import org.basex.io.serial.*;
import org.junit.*;
/**
* This class tests the functions of the EXPath Cryptographic module. The tests in basex-test
* package are only executable after a java keystore has been created.
*
* @author BaseX Team 2005-17, BSD License
* @author Lukas Kircher
*/
public final class FNCryptoTest extends SandboxTest{
/** User home directory. */
private static final String KEYSTORE_DIR = System.getProperty("user.home");
/** Java home directory. */
private static final String JAVA_HOME = System.getProperty("java.home");
/** Keytool executable. */
private static final String KEYTOOL = JAVA_HOME + "/bin/keytool";
/** Key store file. */
private static final String KEYSTORE = KEYSTORE_DIR + "/keystore.jks";
/** Key alias. */
private static final String ALIAS = "basex";
/** Key store and key password. */
private static final String PASS = "password";
/** Shell command to create java keystore. */
private static final String[] GENKEY_CMD = { KEYTOOL,
"-genkey", "-keyalg", "RSA", "-validity", "360", "-alias", ALIAS,
"-keystore", KEYSTORE, "-storepass", PASS, "-keypass", PASS,
"-dname", "CN=hans wurst, OU=dev, O=basex, L=konstanz, ST=bw, C=de" };
/** Digital certificate element. */
private static final String CT = "<digital-certificate>" +
"<keystore-type>JKS</keystore-type>" +
"<keystore-password>" + PASS + "</keystore-password>" +
"<key-alias>" + ALIAS + "</key-alias>" +
"<private-key-password>" + PASS + "</private-key-password>" +
"<keystore-uri>" + KEYSTORE + "</keystore-uri>" +
"</digital-certificate>";
/**
* Tests whether validate-signature returns true for a certificate created
* with generate-signature.
*/
@Test
public void validateSignatureWithCertificate() {
query("crypto:validate-signature(" +
"crypto:generate-signature(<a/>,'','','','',''," + CT + "))", "true");
}
/**
* Tests whether validate-signature returns true for a certificate created
* with generate-signature.
*/
@Test
public void validateSignatureWithXPathAndCertificate() {
query("crypto:validate-signature(crypto:generate-signature(<a><n/><n/></a>," +
"'','','','','','/a/n'," + CT + "))", "true");
}
/**
* Tests whether validate-signature returns true for a certificate created
* with generate-signature.
*/
@Test
public void validateSignatureFullySpecified() {
query("crypto:validate-signature(crypto:generate-signature(<a><n/></a>," +
"'exclusive','SHA512','RSA_SHA1','myPrefix','enveloped','/a/n'," + CT +
"))", "true");
}
/**
* Test method for crypto:encrypt and crypto:decrypt with asymmetric keys.
*/
@Test
public void encryptionAsym1() {
final String msg = "messagemessagemessagemessagemessagemessagemessage";
PublicKey puk = null;
PrivateKey prk = null;
try {
final KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
final KeyPair kp = gen.generateKeyPair();
puk = kp.getPublic();
prk = kp.getPrivate();
} catch(final NoSuchAlgorithmException e) {
e.printStackTrace();
}
query("let $e := crypto:encrypt('" + msg + "','asymmetric','" + prk + "','RSA')" +
"return crypto:decrypt($e,'asymmetric','" + puk + "','RSA')", msg);
}
/**
* Creates the database context.
* @throws Exception error during keystore generation or database exception
*/
@BeforeClass
public static void start() throws Exception {
new File(KEYSTORE).delete();
final Process proc = Runtime.getRuntime().exec(GENKEY_CMD);
Thread.sleep(2000); // give the keytool some time to finish
if(proc.exitValue() != 0) throw new RuntimeException("Cannot initialize keystore.");
// turn off pretty printing
set(MainOptions.SERIALIZER, SerializerMode.NOINDENT.get());
}
/**
* Removes test databases and closes the database context.
*/
@AfterClass
public static void finish() {
new File(KEYSTORE).delete();
}
/**
* Runs a query and matches the result against the expected output.
* @param query query
* @param expected expected output
*/
private static void query(final String query, final String expected) {
query(null, query, expected);
}
/**
* Runs an updating query and matches the result of the second query
* against the expected output.
* @param first first query
* @param second second query
* @param expected expected output
*/
private static void query(final String first, final String second,
final String expected) {
if(first != null) query(first);
final String result = query(second);
// quotes are replaced by apostrophes to simplify comparison
assertEquals(expected.replaceAll("\"", "'"), result.replaceAll("\"", "'"));
}
}