diff --git a/.classpath b/.classpath deleted file mode 100644 index fae1a2b..0000000 --- a/.classpath +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.gitignore b/.gitignore index 1ebf457..b878ed4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ target/ *.iml .idea/ +.classpath +.settings +.vscode + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 29abf99..0000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/test/java=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 714351a..0000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f..0000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/README.md b/README.md index cef324b..9eaf2af 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,20 @@ -# Warning: Current release of eXist crypto lib 5.3.0 has known fatal issues. See https://github.com/eXist-db/crypto-exist-java-lib/issues/33. +# eXist-db implementation for EXPath Cryptographic Module -## eXist implementation for EXPath Cryptographic Module +This is an eXist-db implementation of the [EXPath HTTP Crypto Module specification](http://expath.org/spec/crypto). +## Building from source +Requires: +* Java 1.8 or newer +* Maven 3.6 or newer + +```bash +$ git clone https://github.com/eXist-db/crypto-exist-java-lib +$ cd crypto-exist-java-lib +$ mvn clean package +``` + +This will create a "expath-crypto-module-.xar" file in the target folder. The .xar file can be uploaded to any eXist-db version > 5.3.0 via the Dashboard. + ### Currently implemented functions * crypto:hash() diff --git a/pom.xml b/pom.xml index 9a697e4..5442993 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.exist-db.xquery.extensions.expath expath-crypto-module - 1.1.0-SNAPSHOT + 6.0.0-SNAPSHOT eXist-db EXPath Cryptographic library eXist-db wrapper for EXPath Cryptographic Java library @@ -27,15 +27,15 @@ - https://github.com/exist-db/crypto-exist-java-lib.git + scm:git://github.com/exist-db/crypto-exist-java-lib.git scm:git:https://github.com/exist-db/crypto-exist-java-lib.git scm:git:https://github.com/exist-db/crypto-exist-java-lib.git HEAD - Kuberam - http://kuberam.ro + exist-db Project + https://exist-db.org @@ -44,6 +44,11 @@ Claudius Teodorescu claudius.teodorescu@gmail.com + + olaf + Olaf Schreck + olaf@existsolutions.com + @@ -51,12 +56,16 @@ Adam Retter adam@exist-db.org + + Juri Leino + juri@existsolutions.com + EXPath Cryptographic Module Implementation - 1.5 - 5.2.0 + 1.8.0 + 5.3.0 http://expath.org/ns/crypto crypto ${crypto.module.ns} @@ -64,8 +73,8 @@ - ro.kuberam.libs.java - crypto + org.expath.crypto + crypto-java ${crypto.java.lib.version} @@ -134,7 +143,7 @@ 2.3.0 - package + prepare-package generate @@ -144,26 +153,9 @@ ${project.basedir} ${project.basedir}/build/header.html ${project.basedir}/build/footer.html + index.html - - com.coderplus.maven.plugins - copy-rename-maven-plugin - 1.0.1 - - - rename-readme-file - package - - rename - - - ${project.build.directory}/html/README.html - ${project.build.directory}/html/index.html - - - - ro.kuberam.maven.plugins kuberam-expath-plugin @@ -197,6 +189,34 @@ @{project.version} + + de.jutzig + github-release-plugin + 1.4.0 + + + github-upload + deploy + + release + + false + + eXist implementation for EXPath Cryptographic Module + v6.0.0 + ${project.version} + + + ${project.build.directory} + + ${project.artifactId}*.xar + + + + + + + diff --git a/src/main/java/org/expath/exist/crypto/EXpathCryptoException.java b/src/main/java/org/expath/exist/crypto/EXpathCryptoException.java index 3be3ab7..5b940b0 100644 --- a/src/main/java/org/expath/exist/crypto/EXpathCryptoException.java +++ b/src/main/java/org/expath/exist/crypto/EXpathCryptoException.java @@ -30,7 +30,7 @@ public class EXpathCryptoException extends XPathException { private static final long serialVersionUID = -6789727720893604433L; public EXpathCryptoException(Expression expr, CryptoError cryptoError) { - super(expr, new ExpathCryptoErrorCode(cryptoError), ExpathCryptoErrorCode.getDescription(cryptoError)); + super(expr, new ExpathCryptoErrorCode(cryptoError), cryptoError.getDescription()); } public EXpathCryptoException(Expression expr, Exception exception) { diff --git a/src/main/java/org/expath/exist/crypto/ExpathCryptoErrorCode.java b/src/main/java/org/expath/exist/crypto/ExpathCryptoErrorCode.java index a21fe0d..6eddf21 100644 --- a/src/main/java/org/expath/exist/crypto/ExpathCryptoErrorCode.java +++ b/src/main/java/org/expath/exist/crypto/ExpathCryptoErrorCode.java @@ -5,24 +5,12 @@ import ro.kuberam.libs.java.crypto.CryptoError; -import java.lang.reflect.Field; - public class ExpathCryptoErrorCode extends ErrorCode { public ExpathCryptoErrorCode(String code, String description) { super(new QName(code, ExistExpathCryptoModule.NAMESPACE_URI, ExistExpathCryptoModule.PREFIX), description); } public ExpathCryptoErrorCode(CryptoError cryptoError) { - super(new QName(cryptoError.name(), ExistExpathCryptoModule.NAMESPACE_URI, ExistExpathCryptoModule.PREFIX), getDescription(cryptoError)); - } - - public static String getDescription(final CryptoError cryptoError) { - try { - final Field field = cryptoError.getClass().getDeclaredField("description"); - field.setAccessible(true); - return (String) field.get(cryptoError); - } catch (final NoSuchFieldException | IllegalAccessException e) { - return "UNKNOWN"; - } + super(new QName(cryptoError.getCode(), ExistExpathCryptoModule.NAMESPACE_URI, ExistExpathCryptoModule.PREFIX), cryptoError.getDescription()); } } diff --git a/src/main/java/org/expath/exist/crypto/digest/HashFunction.java b/src/main/java/org/expath/exist/crypto/digest/HashFunction.java index c103362..e81b14d 100644 --- a/src/main/java/org/expath/exist/crypto/digest/HashFunction.java +++ b/src/main/java/org/expath/exist/crypto/digest/HashFunction.java @@ -27,7 +27,6 @@ import java.io.IOException; import java.io.InputStream; -import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -73,8 +72,12 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro final int inputType = args[0].itemAt(0).getType(); final String hashAlgorithm = args[1].getStringValue(); - final String encoding = Optional.ofNullable(args[2].getStringValue()).filter(str -> !str.isEmpty()) - .orElse("base64"); + final String encoding; + if (args.length == 2) { + encoding = "base64"; + } else { + encoding = args[2].getStringValue().isEmpty() ? "base64" : args[2].getStringValue(); + } LOG.debug("encoding = {}", () -> encoding); final Sequence result; diff --git a/src/main/java/org/expath/exist/crypto/digest/HmacFunction.java b/src/main/java/org/expath/exist/crypto/digest/HmacFunction.java index ce74504..72ff548 100644 --- a/src/main/java/org/expath/exist/crypto/digest/HmacFunction.java +++ b/src/main/java/org/expath/exist/crypto/digest/HmacFunction.java @@ -28,7 +28,6 @@ import java.io.IOException; import java.io.InputStream; -import java.util.Optional; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -101,9 +100,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro result = Conversion.byteArrayToIntegerSequence(resultBytes); } else if (argsLength == 4) { - - final String encoding = Optional.ofNullable(args[3].getStringValue()).filter(str -> !str.isEmpty()) - .orElse("base64"); + final String encoding = args[3].getStringValue().isEmpty() ? "base64" : args[3].getStringValue(); LOG.debug("encoding = {}", () -> encoding); final String resultString; diff --git a/src/main/java/org/expath/exist/crypto/digitalSignature/GenerateSignatureFunction.java b/src/main/java/org/expath/exist/crypto/digitalSignature/GenerateSignatureFunction.java index 261e227..ccbb4c5 100644 --- a/src/main/java/org/expath/exist/crypto/digitalSignature/GenerateSignatureFunction.java +++ b/src/main/java/org/expath/exist/crypto/digitalSignature/GenerateSignatureFunction.java @@ -19,10 +19,17 @@ */ package org.expath.exist.crypto.digitalSignature; +import static org.exist.xquery.FunctionDSL.arities; +import static org.exist.xquery.FunctionDSL.arity; +import static org.exist.xquery.FunctionDSL.param; +import static org.exist.xquery.FunctionDSL.returns; +import static org.expath.exist.crypto.ExistExpathCryptoModule.functionSignatures; + import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.URISyntaxException; +import java.security.PrivateKey; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.parsers.DocumentBuilder; @@ -36,10 +43,13 @@ import org.exist.Namespaces; import org.exist.dom.memtree.SAXAdapter; import org.exist.dom.persistent.BinaryDocument; +import org.exist.dom.persistent.DocumentImpl; import org.exist.dom.persistent.LockedDocument; import org.exist.security.PermissionDeniedException; -import org.exist.storage.lock.Lock; +import org.exist.storage.lock.Lock.LockMode; import org.exist.storage.serializers.Serializer; +import org.exist.storage.txn.TransactionException; +import org.exist.storage.txn.Txn; import org.exist.validation.internal.node.NodeInputStream; import org.exist.xmldb.XmldbURI; import org.exist.xquery.BasicFunction; @@ -49,9 +59,9 @@ import org.exist.xquery.value.FunctionParameterSequenceType; import org.exist.xquery.value.NodeValue; import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; import org.expath.exist.crypto.EXpathCryptoException; -import org.expath.exist.crypto.ExpathCryptoErrorCode; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -63,9 +73,8 @@ import ro.kuberam.libs.java.crypto.CryptoException; import ro.kuberam.libs.java.crypto.ExpathCryptoModule; import ro.kuberam.libs.java.crypto.digitalSignature.GenerateXmlSignature; - -import static org.exist.xquery.FunctionDSL.*; -import static org.expath.exist.crypto.ExistExpathCryptoModule.*; +import ro.kuberam.libs.java.crypto.digitalSignature.SignatureForString; +import ro.kuberam.libs.java.crypto.keyManagement.Load; /** * @author Claudius Teodorescu (claudius.teodorescu@gmail.com) @@ -75,8 +84,9 @@ public class GenerateSignatureFunction extends BasicFunction { private static final Logger LOG = LogManager.getLogger(GenerateSignatureFunction.class); private static String FS_GENERATE_SIGNATURE_NAME = "generate-signature"; - private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_DATA = param("data", Type.NODE, - "The document to be signed."); + + private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_DATA = param("data", Type.ITEM, + "The data to be signed."); private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM = param( "canonicalization-algorithm", Type.STRING, "Canonicalization Algorithm."); private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM = param( @@ -85,36 +95,53 @@ public class GenerateSignatureFunction extends BasicFunction { "signature-algorithm", Type.STRING, ExpathCryptoModule.SIGNATURE_ALGORITHM); private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX = param( "signature-namespace-prefix", Type.STRING, "The namespace prefix for signature."); - private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE = param( - "signature-type", Type.STRING, ExpathCryptoModule.SIGNATURE_TYPE); + private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE = param("signature-type", + Type.STRING, ExpathCryptoModule.SIGNATURE_TYPE); private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_DIGITAL_CERTIFICATE = param( "digital-certificate", Type.ANY_TYPE, ExpathCryptoModule.digitalCertificateDetailsDescription); + private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_PRIVATE_KEY = param("private-key", + Type.STRING, "The private key needed for a digital signature."); + private static FunctionParameterSequenceType FS_GENERATE_SIGNATURE_PARAM_XPATH = param("xpath-expression", Type.ANY_TYPE, "The XPath expression used for selecting the subset to be signed."); public static final FunctionSignature FS_GENERATE_SIGNATURE[] = functionSignatures(FS_GENERATE_SIGNATURE_NAME, "Generate an XML digital signature based on generated key pair. This signature is for the whole document.", - returns(Type.NODE, "the signed document (or signature) as node()."), - arities(arity(FS_GENERATE_SIGNATURE_PARAM_DATA, FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE), - arity(FS_GENERATE_SIGNATURE_PARAM_DATA, FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, FS_GENERATE_SIGNATURE_PARAM_XPATH), - arity(FS_GENERATE_SIGNATURE_PARAM_DATA, FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, - FS_GENERATE_SIGNATURE_PARAM_DIGITAL_CERTIFICATE), - arity(FS_GENERATE_SIGNATURE_PARAM_DATA, FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, - FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, FS_GENERATE_SIGNATURE_PARAM_XPATH, - FS_GENERATE_SIGNATURE_PARAM_DIGITAL_CERTIFICATE))); + returns(Type.ITEM, "the signed document (or signature) as item()."), + arities( + arity(FS_GENERATE_SIGNATURE_PARAM_DATA, + FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE), + arity(FS_GENERATE_SIGNATURE_PARAM_DATA, + FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, + FS_GENERATE_SIGNATURE_PARAM_XPATH), + /* + arity(FS_GENERATE_SIGNATURE_PARAM_DATA, + FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, + FS_GENERATE_SIGNATURE_PARAM_DIGITAL_CERTIFICATE), + */ + arity(FS_GENERATE_SIGNATURE_PARAM_DATA, + FS_GENERATE_SIGNATURE_PARAM_CANONICALIZATION_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_DIGEST_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_NAMESPACE_PREFIX, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_TYPE, + FS_GENERATE_SIGNATURE_PARAM_XPATH, + FS_GENERATE_SIGNATURE_PARAM_DIGITAL_CERTIFICATE), + arity(FS_GENERATE_SIGNATURE_PARAM_DATA, + FS_GENERATE_SIGNATURE_PARAM_PRIVATE_KEY, + FS_GENERATE_SIGNATURE_PARAM_SIGNATURE_ALGORITHM))); private static final String certificateRootElementName = "digital-certificate"; private static final String[] certificateChildElementNames = { "keystore-type", "keystore-password", "key-alias", @@ -126,72 +153,91 @@ public GenerateSignatureFunction(final XQueryContext context, final FunctionSign @Override public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException { - Serializer serializer = context.getBroker().getSerializer(); - NodeValue inputNode = (NodeValue) args[0].itemAt(0); - Document inputDOMDoc; - - try (InputStream inputNodeStream = new NodeInputStream(context.getBroker().getBrokerPool(), serializer, inputNode)) { - inputDOMDoc = inputStreamToDocument(inputNodeStream); - } catch (IOException e) { - throw new EXpathCryptoException(this, e); - } - - String canonicalizationAlgorithm = args[1].getStringValue(); - String digestAlgorithm = args[2].getStringValue(); - String signatureAlgorithm = args[3].getStringValue(); - String signatureNamespacePrefix = args[4].getStringValue(); - String signatureType = args[5].getStringValue(); - - String signatureString = null; - Document signatureDocument = null; + if (args.length == 3) { + String input = args[0].getStringValue(); + String base64PrivateKey = args[1].getStringValue(); + String signatureAlgorithm = args[2].getStringValue(); + String output = null; + + String algorithm = "RSA"; + PrivateKey privateKey; + try { + privateKey = Load.privateKey(base64PrivateKey, algorithm, null); + output = SignatureForString.generate(input, privateKey, signatureAlgorithm); + } catch (Exception e) { + e.printStackTrace(); + } - // get the XPath expression and/or the certificate's details - String xpathExprString = null; - String[] certificateDetails = new String[5]; - certificateDetails[0] = ""; - InputStream keyStoreInputStream = null; + return new StringValue(output); + } else { + Serializer serializer = context.getBroker().getSerializer(); + NodeValue inputNode = (NodeValue) args[0].itemAt(0); + Document inputDOMDoc; + + try (InputStream inputNodeStream = new NodeInputStream(context.getBroker().getBrokerPool(), serializer, + inputNode)) { + inputDOMDoc = inputStreamToDocument(inputNodeStream); + } catch (IOException e) { + throw new EXpathCryptoException(this, e); + } - try { + String canonicalizationAlgorithm = args[1].getStringValue(); + String digestAlgorithm = args[2].getStringValue(); + String signatureAlgorithm = args[3].getStringValue(); + String signatureNamespacePrefix = args[4].getStringValue(); + String signatureType = args[5].getStringValue(); + + String signatureString = null; + Document signatureDocument = null; + + // get the XPath expression and/or the certificate's details + String xpathExprString = null; + String[] certificateDetails = new String[5]; + certificateDetails[0] = ""; + InputStream keyStoreInputStream = null; + + try { + + // signature with 7 arguments + if (args.length == 7) { + if (args[6].itemAt(0).getType() == 22) { + xpathExprString = args[6].getStringValue(); + } else if (args[6].itemAt(0).getType() == 1) { + final Node certificateDetailsNode = ((NodeValue) args[6].itemAt(0)).getNode(); + // get the certificate details + certificateDetails = getDigitalCertificateDetails(certificateDetails, certificateDetailsNode); + // get the keystore InputStream + keyStoreInputStream = getKeyStoreInputStream(certificateDetails[4]); + } + } - // function with 7 arguments - if (args.length == 7) { - if (args[6].itemAt(0).getType() == 22) { + // signature with 8 arguments + if (args.length == 8) { xpathExprString = args[6].getStringValue(); - } else if (args[6].itemAt(0).getType() == 1) { - final Node certificateDetailsNode = ((NodeValue) args[6].itemAt(0)).getNode(); + final Node certificateDetailsNode = ((NodeValue) args[7].itemAt(0)).getNode(); // get the certificate details certificateDetails = getDigitalCertificateDetails(certificateDetails, certificateDetailsNode); // get the keystore InputStream keyStoreInputStream = getKeyStoreInputStream(certificateDetails[4]); } - } - - // function with 8 arguments - if (args.length == 8) { - xpathExprString = args[6].getStringValue(); - final Node certificateDetailsNode = ((NodeValue) args[7].itemAt(0)).getNode(); - // get the certificate details - certificateDetails = getDigitalCertificateDetails(certificateDetails, certificateDetailsNode); - // get the keystore InputStream - keyStoreInputStream = getKeyStoreInputStream(certificateDetails[4]); - } - signatureString = GenerateXmlSignature.generate(inputDOMDoc, canonicalizationAlgorithm, digestAlgorithm, - signatureAlgorithm, signatureNamespacePrefix, signatureType, xpathExprString, certificateDetails, - keyStoreInputStream); - keyStoreInputStream.close(); - - signatureDocument = stringToDocument(signatureString); - - return (Sequence) signatureDocument; - } catch (CryptoException | IOException | XMLSignatureException e) { - throw new EXpathCryptoException(this, e); - } finally { - if (keyStoreInputStream != null) { - try { - keyStoreInputStream.close(); - } catch (final IOException e) { - throw new EXpathCryptoException(this, e); + signatureString = GenerateXmlSignature.generate(inputDOMDoc, canonicalizationAlgorithm, digestAlgorithm, + signatureAlgorithm, signatureNamespacePrefix, signatureType, xpathExprString, + certificateDetails, keyStoreInputStream); + keyStoreInputStream.close(); + + signatureDocument = stringToDocument(signatureString); + + return (Sequence) signatureDocument; + } catch (CryptoException | IOException | XMLSignatureException e) { + throw new EXpathCryptoException(this, e); + } finally { + if (keyStoreInputStream != null) { + try { + keyStoreInputStream.close(); + } catch (final IOException e) { + throw new EXpathCryptoException(this, e); + } } } } @@ -243,26 +289,29 @@ private String[] getDigitalCertificateDetails(final String[] certificateDetails, } private InputStream getKeyStoreInputStream(final String keystoreURI) throws CryptoException { - // get the keystore as InputStream - try { - try(final LockedDocument lockedKeyStoreDoc = context.getBroker().getXMLResource(XmldbURI.xmldbUriFor(keystoreURI), Lock.LockMode.READ_LOCK)) { - if (lockedKeyStoreDoc == null) { - throw new CryptoException(CryptoError.UNREADABLE_KEYSTORE); - } + try (final LockedDocument keyStoreLockedDoc = context.getBroker() + .getXMLResource(XmldbURI.xmldbUriFor(keystoreURI), LockMode.READ_LOCK);) { + if (keyStoreLockedDoc == null) { + throw new CryptoException(CryptoError.UNREADABLE_KEYSTORE); + } - final BinaryDocument keyStoreBinaryDoc = (BinaryDocument) lockedKeyStoreDoc.getDocument(); - try { - return context.getBroker().getBinaryResource(keyStoreBinaryDoc); - } catch (final IOException e) { - throw new CryptoException(CryptoError.UNREADABLE_KEYSTORE, e); - } + final DocumentImpl doc = keyStoreLockedDoc.getDocument(); + + try (final Txn transaction = context.getBroker().continueOrBeginTransaction()) { + final BinaryDocument bin = (BinaryDocument) doc; + final InputStream is = context.getBroker().getBinaryResource(transaction, bin); - } catch (final PermissionDeniedException e) { - LOG.error(ExpathCryptoErrorCode.getDescription(CryptoError.DENIED_KEYSTORE)); - return null; + transaction.commit(); + + return is; } } catch (final URISyntaxException e) { - LOG.error(ExpathCryptoErrorCode.getDescription(CryptoError.KEYSTORE_URL)); + LOG.error(CryptoError.KEYSTORE_URL.getDescription()); + return null; + } catch (final IOException | TransactionException e) { + throw new CryptoException(CryptoError.UNREADABLE_KEYSTORE, e); + } catch (final PermissionDeniedException e) { + LOG.error(CryptoError.DENIED_KEYSTORE.getDescription()); return null; } } @@ -287,4 +336,4 @@ private Document inputStreamToDocument(final InputStream inputStream) { return document; } -} \ No newline at end of file +} diff --git a/src/main/java/org/expath/exist/crypto/encrypt/EncryptionFunctions.java b/src/main/java/org/expath/exist/crypto/encrypt/EncryptionFunctions.java index 872abaf..e62028c 100644 --- a/src/main/java/org/expath/exist/crypto/encrypt/EncryptionFunctions.java +++ b/src/main/java/org/expath/exist/crypto/encrypt/EncryptionFunctions.java @@ -33,7 +33,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.exist.util.io.FastByteArrayInputStream; import org.exist.xquery.BasicFunction; import org.exist.xquery.FunctionSignature; import org.exist.xquery.XPathException; @@ -122,13 +121,11 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro private Sequence encrypt(byte[] data, CryptType encryptType, String secretKey, String algorithm, @Nullable String iv, @Nullable String provider) throws XPathException { try { - String resultBytes = null; + byte[] resultBytes = null; switch (encryptType) { case SYMMETRIC: - try (final FastByteArrayInputStream is = new FastByteArrayInputStream(data)) { - resultBytes = SymmetricEncryption.encrypt(is, secretKey, algorithm, iv, provider); - } + resultBytes = SymmetricEncryption.encrypt(data, secretKey, algorithm, iv, provider); break; case ASYMMETRIC: @@ -138,7 +135,7 @@ private Sequence encrypt(byte[] data, CryptType encryptType, String secretKey, S default: throw new EXpathCryptoException(this, CryptoError.ENCRYPTION_TYPE); } - String result = Base64.getEncoder().encodeToString(resultBytes.getBytes()); + String result = Base64.getEncoder().encodeToString(resultBytes); LOG.debug("encrypt result = {}", () -> result); return new StringValue(result); @@ -154,13 +151,11 @@ private Sequence encrypt(byte[] data, CryptType encryptType, String secretKey, S private Sequence decrypt(byte[] data, CryptType decryptType, String secretKey, String algorithm, @Nullable String iv, @Nullable String provider) throws XPathException { try { - String resultBytes = null; + byte[] resultBytes = null; switch (decryptType) { case SYMMETRIC: - try (final FastByteArrayInputStream is = new FastByteArrayInputStream(data)) { - resultBytes = SymmetricEncryption.decrypt(is, secretKey, algorithm, iv, provider); - } + resultBytes = SymmetricEncryption.decrypt(data, secretKey, algorithm, iv, provider); break; case ASYMMETRIC: @@ -172,7 +167,7 @@ private Sequence decrypt(byte[] data, CryptType decryptType, String secretKey, S throw new EXpathCryptoException(this, CryptoError.DECRYPTION_TYPE); } - String result = new String(resultBytes.getBytes(), UTF_8); + String result = new String(resultBytes, UTF_8); LOG.debug("decrypt result = {}", () -> result); return new StringValue(result); diff --git a/src/main/java/org/expath/exist/crypto/utils/Conversion.java b/src/main/java/org/expath/exist/crypto/utils/Conversion.java index c884493..25b1ebc 100644 --- a/src/main/java/org/expath/exist/crypto/utils/Conversion.java +++ b/src/main/java/org/expath/exist/crypto/utils/Conversion.java @@ -8,7 +8,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.exist.util.io.FastByteArrayOutputStream; import org.exist.xquery.XPathException; import org.exist.xquery.value.BinaryValue; import org.exist.xquery.value.IntegerValue; @@ -18,6 +17,8 @@ import org.exist.xquery.value.Type; import org.exist.xquery.value.ValueSequence; +import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; + import com.evolvedbinary.j8fu.Either; import ro.kuberam.libs.java.crypto.utils.Buffer; @@ -36,7 +37,7 @@ public static byte[] toByteArray(@Nullable final Either dat return data.right().get(); } else { try (final InputStream is = data.left().get(); - final FastByteArrayOutputStream baos = new FastByteArrayOutputStream()) { + final UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream()) { final byte[] buf = new byte[Buffer.TRANSFER_SIZE]; int read = -1; @@ -77,11 +78,11 @@ public static Either sequence2javaTypes(final Sequence sequ return null; } } else { - final FastByteArrayOutputStream baos = new FastByteArrayOutputStream(); + final UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(); for (final SequenceIterator iterator = sequence.iterate(); iterator.hasNext();) { baos.write(((NumericValue) iterator.nextItem()).getInt()); } - return Either.Left(baos.toFastByteInputStream()); + return Either.Left(baos.toInputStream()); } } diff --git a/xar-assembly.xml b/xar-assembly.xml index 1bbe1be..9203c5a 100644 --- a/xar-assembly.xml +++ b/xar-assembly.xml @@ -22,8 +22,8 @@ ${project.artifactId}-exist-java-lib-${project.version}.jar - ro.kuberam.libs.java - crypto + org.expath.crypto + crypto-java ${crypto.java.lib.version} crypto-java-lib-${crypto.java.lib.version}.jar