use of com.helger.phase4.servlet.soap.Phase4KeyStoreCallbackHandler in project phase4 by phax.
the class SOAPHeaderElementProcessorWSS4J method _verifyAndDecrypt.
@Nonnull
private ESuccess _verifyAndDecrypt(@Nonnull final Document aSOAPDoc, @Nonnull final ICommonsList<WSS4JAttachment> aAttachments, @Nonnull final AS4MessageState aState, @Nonnull final ErrorList aErrorList, @Nonnull final Supplier<WSSConfig> aWSSConfigSupplier) {
// Default is Leg 1, gets overwritten when a reference to a message id
// exists and then uses leg2
final Locale aLocale = aState.getLocale();
// Signing verification and Decryption
try {
// Convert to WSS4J attachments
final Phase4KeyStoreCallbackHandler aKeyStoreCallback = new Phase4KeyStoreCallbackHandler(m_aCryptoFactory);
final WSS4JAttachmentCallbackHandler aAttachmentCallbackHandler = new WSS4JAttachmentCallbackHandler(aAttachments, aState.getResourceHelper());
// Resolve the WSS config here to ensure the context matches
final WSSConfig aWSSConfig = aWSSConfigSupplier.get();
// Configure RequestData needed for the check / decrypt process!
final RequestData aRequestData = new RequestData();
aRequestData.setCallbackHandler(aKeyStoreCallback);
if (aAttachments.isNotEmpty())
aRequestData.setAttachmentCallbackHandler(aAttachmentCallbackHandler);
aRequestData.setSigVerCrypto(m_aCryptoFactory.getCrypto());
aRequestData.setDecCrypto(m_aCryptoFactory.getCrypto());
aRequestData.setWssConfig(aWSSConfig);
// Upon success, the SOAP document contains the decrypted content
// afterwards!
final WSSecurityEngine aSecurityEngine = new WSSecurityEngine();
aSecurityEngine.setWssConfig(aWSSConfig);
final WSHandlerResult aHdlRes = aSecurityEngine.processSecurityHeader(aSOAPDoc, aRequestData);
final List<WSSecurityEngineResult> aResults = aHdlRes.getResults();
// Collect all unique used certificates
final ICommonsSet<X509Certificate> aCertSet = new CommonsHashSet<>();
// Preferred certificate from BinarySecurityToken
X509Certificate aPreferredCert = null;
int nWSS4JSecurityActions = 0;
for (final WSSecurityEngineResult aResult : aResults) {
if (LOGGER.isDebugEnabled())
LOGGER.debug("WSSecurityEngineResult: " + aResult);
final Integer aAction = (Integer) aResult.get(WSSecurityEngineResult.TAG_ACTION);
final int nAction = aAction != null ? aAction.intValue() : 0;
nWSS4JSecurityActions |= nAction;
final X509Certificate aCert = (X509Certificate) aResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
if (aCert != null) {
aCertSet.add(aCert);
if (nAction == WSConstants.BST && aPreferredCert == null)
aPreferredCert = aCert;
}
}
// this determines if a signature check or a decryption happened
aState.setSoapWSS4JSecurityActions(nWSS4JSecurityActions);
final X509Certificate aUsedCert;
if (aCertSet.size() > 1) {
if (aPreferredCert == null) {
LOGGER.warn("Found " + aCertSet.size() + " different certificates in message. Using the first one.");
if (LOGGER.isDebugEnabled())
LOGGER.debug("All gathered certificates: " + aCertSet);
aUsedCert = aCertSet.getAtIndex(0);
} else
aUsedCert = aPreferredCert;
} else if (aCertSet.size() == 1)
aUsedCert = aCertSet.getAtIndex(0);
else
aUsedCert = null;
// Remember in State
aState.setUsedCertificate(aUsedCert);
aState.setDecryptedSoapDocument(aSOAPDoc);
// Decrypting the Attachments
final ICommonsList<WSS4JAttachment> aResponseAttachments = aAttachmentCallbackHandler.getAllResponseAttachments();
for (final WSS4JAttachment aResponseAttachment : aResponseAttachments) {
// Always copy to a temporary file, so that decrypted content can be
// read more than once. By default the stream can only be read once
// Not nice, but working :)
final File aTempFile = aState.getResourceHelper().createTempFile();
StreamHelper.copyInputStreamToOutputStreamAndCloseOS(aResponseAttachment.getSourceStream(), FileHelper.getBufferedOutputStream(aTempFile));
aResponseAttachment.setSourceStreamProvider(HasInputStream.multiple(() -> FileHelper.getBufferedInputStream(aTempFile)));
}
// Remember in State
aState.setDecryptedAttachments(aResponseAttachments);
return ESuccess.SUCCESS;
} catch (final IndexOutOfBoundsException | IllegalStateException | WSSecurityException ex) {
// Decryption or Signature check failed
LOGGER.error("Error processing the WSSSecurity Header", ex);
/**
* Error processing the WSSSecurity Header
*
* <pre>
* java.lang.IndexOutOfBoundsException: null
* at java.io.ByteArrayInputStream.read(ByteArrayInputStream.java:180) ~[?:1.8.0_242]
* at org.apache.wss4j.common.util.AttachmentUtils$1.initCipher(AttachmentUtils.java:501) ~[wss4j-ws-security-common-2.3.0.jar:2.3.0]
* at org.apache.wss4j.common.util.AttachmentUtils$1.read(AttachmentUtils.java:535) ~[wss4j-ws-security-common-2.3.0.jar:2.3.0]
* at com.helger.commons.io.stream.StreamHelper._copyInputStreamToOutputStream(StreamHelper.java:218) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.commons.io.stream.StreamHelper.copyInputStreamToOutputStream(StreamHelper.java:312) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.commons.io.stream.StreamHelper.copyInputStreamToOutputStreamAndCloseOS(StreamHelper.java:429) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorWSS4J._verifyAndDecrypt(SOAPHeaderElementProcessorWSS4J.java:187) ~[classes/:?]
* </pre>
*
* Failed to close object org.apache.wss4j.common.util.AttachmentUtils$1
*
* <pre>
* java.lang.IllegalStateException: Cipher not initialized
* at javax.crypto.Cipher.checkCipherState(Cipher.java:1749) ~[?:1.8.0_242]
* at javax.crypto.Cipher.doFinal(Cipher.java:2044) ~[?:1.8.0_242]
* at javax.crypto.CipherInputStream.close(CipherInputStream.java:330) ~[?:1.8.0_242]
* at com.helger.commons.io.stream.StreamHelper.close(StreamHelper.java:163) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.commons.io.stream.StreamHelper.copyInputStreamToOutputStream(StreamHelper.java:337) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.commons.io.stream.StreamHelper.copyInputStreamToOutputStreamAndCloseOS(StreamHelper.java:429) ~[ph-commons-9.4.7.jar:9.4.7]
* at com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorWSS4J._verifyAndDecrypt(SOAPHeaderElementProcessorWSS4J.java:187) ~[classes/:?]
* </pre>
*
* Error processing the WSSSecurity Header
*
* <pre>
* org.apache.wss4j.common.ext.WSSecurityException: Error during certificate path validation: No trusted certs found
* at org.apache.wss4j.common.crypto.Merlin.verifyTrust(Merlin.java:816) ~[task/:?]
* at org.apache.wss4j.common.crypto.Merlin.verifyTrust(Merlin.java:906) ~[task/:?]
* at org.apache.wss4j.dom.validate.SignatureTrustValidator.verifyTrustInCerts(SignatureTrustValidator.java:109) ~[task/:?]
* at org.apache.wss4j.dom.validate.SignatureTrustValidator.validate(SignatureTrustValidator.java:64) ~[task/:?]
* at org.apache.wss4j.dom.processor.SignatureProcessor.handleToken(SignatureProcessor.java:189) ~[task/:?]
* at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340) ~[task/:?]
* at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:251) ~[task/:?]
* at com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorWSS4J._verifyAndDecrypt(SOAPHeaderElementProcessorWSS4J.java:128) ~[task/:?]
* </pre>
*
* If the SMP provided AP certificate does not match the configured one:
*
* <pre>
* org.apache.wss4j.common.ext.WSSecurityException: Cannot find key for certificate
* at org.apache.wss4j.dom.processor.EncryptedKeyProcessor.getPrivateKey(EncryptedKeyProcessor.java:269) ~[wss4j-ws-security-dom-2.3.1.jar:2.3.1]
* at org.apache.wss4j.dom.processor.EncryptedKeyProcessor.handleToken(EncryptedKeyProcessor.java:225) ~[wss4j-ws-security-dom-2.3.1.jar:2.3.1]
* at org.apache.wss4j.dom.processor.EncryptedKeyProcessor.handleToken(EncryptedKeyProcessor.java:90) ~[wss4j-ws-security-dom-2.3.1.jar:2.3.1]
* at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340) ~[wss4j-ws-security-dom-2.3.1.jar:2.3.1]
* at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:251) ~[wss4j-ws-security-dom-2.3.1.jar:2.3.1]
* at com.helger.phase4.servlet.soap.SOAPHeaderElementProcessorWSS4J._verifyAndDecrypt(SOAPHeaderElementProcessorWSS4J.java:128) ~[phase4-lib-1.3.1.jar:1.3.1]
* </pre>
*/
// TODO we need a way to distinct
// signature and decrypt WSSecurityException provides no such thing
aErrorList.add(EEbmsError.EBMS_FAILED_DECRYPTION.getAsError(aLocale));
aState.setSoapWSS4JException(ex);
return ESuccess.FAILURE;
} catch (final IOException ex) {
// Decryption or Signature check failed
LOGGER.error("IO error processing the WSSSecurity Header", ex);
aErrorList.add(EEbmsError.EBMS_OTHER.getAsError(aLocale));
aState.setSoapWSS4JException(ex);
return ESuccess.FAILURE;
}
}
use of com.helger.phase4.servlet.soap.Phase4KeyStoreCallbackHandler in project phase4 by phax.
the class MainVerifySignature method _verifyAndDecrypt.
@Nonnull
private static ESuccess _verifyAndDecrypt(@Nonnull final IAS4CryptoFactory aCryptoFactory, @Nonnull final Document aSOAPDoc, @Nonnull final Locale aLocale, @Nonnull final AS4ResourceHelper aResHelper, @Nonnull final ICommonsList<WSS4JAttachment> aAttachments, @Nonnull final ErrorList aErrorList, @Nonnull final Supplier<WSSConfig> aWSSConfigSupplier) {
// Signing verification and Decryption
try {
// Convert to WSS4J attachments
final Phase4KeyStoreCallbackHandler aKeyStoreCallback = new Phase4KeyStoreCallbackHandler(aCryptoFactory);
final WSS4JAttachmentCallbackHandler aAttachmentCallbackHandler = new WSS4JAttachmentCallbackHandler(aAttachments, aResHelper);
// Resolve the WSS config here to ensure the context matches
final WSSConfig aWSSConfig = aWSSConfigSupplier.get();
// Configure RequestData needed for the check / decrypt process!
final RequestData aRequestData = new RequestData();
aRequestData.setCallbackHandler(aKeyStoreCallback);
if (aAttachments.isNotEmpty())
aRequestData.setAttachmentCallbackHandler(aAttachmentCallbackHandler);
aRequestData.setSigVerCrypto(aCryptoFactory.getCrypto());
aRequestData.setDecCrypto(aCryptoFactory.getCrypto());
aRequestData.setWssConfig(aWSSConfig);
// Upon success, the SOAP document contains the decrypted content
// afterwards!
final WSSecurityEngine aSecurityEngine = new WSSecurityEngine();
aSecurityEngine.setWssConfig(aWSSConfig);
final WSHandlerResult aHdlRes = aSecurityEngine.processSecurityHeader(aSOAPDoc, aRequestData);
final List<WSSecurityEngineResult> aResults = aHdlRes.getResults();
// Collect all unique used certificates
final ICommonsSet<X509Certificate> aCertSet = new CommonsHashSet<>();
// Preferred certificate from BinarySecurityToken
X509Certificate aPreferredCert = null;
int nWSS4JSecurityActions = 0;
for (final WSSecurityEngineResult aResult : aResults) {
if (LOGGER.isDebugEnabled())
LOGGER.debug("WSSecurityEngineResult: " + aResult);
final Integer aAction = (Integer) aResult.get(WSSecurityEngineResult.TAG_ACTION);
final int nAction = aAction != null ? aAction.intValue() : 0;
nWSS4JSecurityActions |= nAction;
final X509Certificate aCert = (X509Certificate) aResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
if (aCert != null) {
aCertSet.add(aCert);
if (nAction == WSConstants.BST && aPreferredCert == null)
aPreferredCert = aCert;
}
}
// this determines if a signature check or a decryption happened
final X509Certificate aUsedCert;
if (aCertSet.size() > 1) {
if (aPreferredCert == null) {
LOGGER.warn("Found " + aCertSet.size() + " different certificates in message. Using the first one.");
if (LOGGER.isDebugEnabled())
LOGGER.debug("All gathered certificates: " + aCertSet);
aUsedCert = aCertSet.getAtIndex(0);
} else
aUsedCert = aPreferredCert;
} else if (aCertSet.size() == 1)
aUsedCert = aCertSet.getAtIndex(0);
else
aUsedCert = null;
// Remember in State
// Decrypting the Attachments
final ICommonsList<WSS4JAttachment> aResponseAttachments = aAttachmentCallbackHandler.getAllResponseAttachments();
for (final WSS4JAttachment aResponseAttachment : aResponseAttachments) {
// Always copy to a temporary file, so that decrypted content can be
// read more than once. By default the stream can only be read once
// Not nice, but working :)
final File aTempFile = aResHelper.createTempFile();
StreamHelper.copyInputStreamToOutputStreamAndCloseOS(aResponseAttachment.getSourceStream(), FileHelper.getBufferedOutputStream(aTempFile));
aResponseAttachment.setSourceStreamProvider(HasInputStream.multiple(() -> FileHelper.getBufferedInputStream(aTempFile)));
}
// Remember in State
return ESuccess.SUCCESS;
} catch (final IndexOutOfBoundsException | IllegalStateException | WSSecurityException ex) {
// Decryption or Signature check failed
LOGGER.error("Error processing the WSSSecurity Header", ex);
// TODO we need a way to distinct
// signature and decrypt WSSecurityException provides no such thing
aErrorList.add(EEbmsError.EBMS_FAILED_DECRYPTION.getAsError(aLocale));
return ESuccess.FAILURE;
} catch (final IOException ex) {
// Decryption or Signature check failed
LOGGER.error("IO error processing the WSSSecurity Header", ex);
aErrorList.add(EEbmsError.EBMS_OTHER.getAsError(aLocale));
return ESuccess.FAILURE;
}
}
Aggregations