You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@ws.apache.org by "Eaton, Jason" <je...@visa.com> on 2016/02/24 23:46:57 UTC
Creating Derived Encrypted Key w/BinarySecurityToken Ref
Hello I am using Wss4j 1.5.12. We are trying to add an encrypted envelope to a SOAP message. Where the encryption key is a derived key encrypted with the recipient's certificate (public key). I am using the test case TestWSSecurityNewDK as a sample to accomplish this.
I first setup certificates and private keys in a java keystore then add them to the Crypto instance. I create two keystores, one for the recipient and one for the sender. Then I setup the encrypted key object, using a x509 key identifier. The doc is prepared and then the key and reference is saved, to be added to the encryption object later. I then Sign the document with a X509 binary token reference. The signed doc is encrypted with the DK encrypt object after setting the key and key reference. When I validate the document with my own callback I provide the "password".
The document is created correctly but then when I try to validate the headers, it is not able to decrypt the temporary encryption key. I get "bad hash" or "block corrupted" error.
org.apache.ws.security.WSSecurityException: The signature or decryption was invalid
at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:244)
at org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:166)
at org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:113)
at org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:76)
at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:328)
at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:245)
at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:198)
at com.cybersource.nta.ws.WSSecurityFilterTest.testSignAndEncrypt(WSSecurityFilterTest.java:526)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: org.apache.xml.security.encryption.XMLEncryptionException: pad block corrupted
Original Exception was javax.crypto.BadPaddingException: pad block corrupted
at org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown Source)
at org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown Source)
at org.apache.xml.security.encryption.XMLCipher.decryptElementContent(Unknown Source)
at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown Source)
at org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:242)
... 33 more
senderHandler.getCrypto().setKeyStore(setupSenderKeystore());
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
// EncryptedKey encrypt with temporary session key
// and encrypt this temporary session key with the recipient's
// public key (certificate)
WSSecEncrypt encrKeyBuilder = new WSSecEncrypt();
encrKeyBuilder.setUserInfo("cybersource_sjc_us");
encrKeyBuilder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
encrKeyBuilder.setKeyEnc(WSConstants.KEYTRANSPORT_RSAOEP);
encrKeyBuilder.prepare(doc, senderHandler.getCrypto());
//Key information from the EncryptedKey
byte[] ek = encrKeyBuilder.getEphemeralKey();
String tokenIdentifier = encrKeyBuilder.getId();
// Sign the message with senders private key
WSSecSignature sign = new WSSecSignature();
sign.setUserInfo("jasoneatoncorp", "jasoneatoncorp");
sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256);
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
Document signedDoc = sign.build(doc, senderHandler.getCrypto(), secHeader);
WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt();
encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
encrBuilder.setExternalKey(ek, tokenIdentifier);
Document signedEncryptedDoc = encrBuilder.build(signedDoc, secHeader);
assertNotNull(signedEncryptedDoc);
encrKeyBuilder.prependToHeader(secHeader);
encrKeyBuilder.prependBSTElementToHeader(secHeader);
//System.out.println(XMLUtils.PrettyDocumentToString(signedEncryptedDoc));
// Make this handler for recipient only ( keystore difference )
DigitalSignatureHandlerImpl2 recipientHandler = new DigitalSignatureHandlerImpl2(newCASerial);
recipientHandler.init(securityDAO);
recipientHandler.getCrypto().setKeyStore(setupRecipientKeystore());
filter.init(filterConfig);
filter.digSigHandler = recipientHandler;
WSSecurityEngine secEngine = new WSSecurityEngine();
Vector result = secEngine.processSecurityHeader(doc, null, new MyPasswordCallback(), recipientHandler.getCrypto());
...
public class MyPasswordCallback implements CallbackHandler {
private org.apache.log4j.Logger logger
= org.apache.log4j.Logger.getLogger(getClass());
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
int usage = pc.getUsage();
if (usage == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
logger.info("callback routine, usage USERNAME_TOKEN_UNKNOWN for alias: " + pc.getIdentifer());
} else if (usage == WSPasswordCallback.DECRYPT) {
logger.info("callback routine, usage DECRYPT for alias: " + pc.getIdentifer());
try {
if ("jasoneatoncorp".equals(pc.getIdentifier())) {
pc.setPassword("jasoneatoncorp");
pc.setKey(instPrivateKey(jasonPrivateKey).getEncoded());
} else if ("cybersource_sjc_us".equals(pc.getIdentifier())) {
pc.setPassword("cybersource_sjc_us");
pc.setKey(instPrivateKey(newServerKey).getEncoded());
}
} catch (CertificateException e) {
logger.info("callback routine, usage DECRYPT throws exception: " + e.getMessage());
throw new UnsupportedCallbackException(pc);
} catch (IOException e) {
logger.info("callback routine, usage DECRYPT throws exception: " + e.getMessage());
throw new UnsupportedCallbackException(pc);
} catch (NoSuchAlgorithmException e) {
logger.info("callback routine, usage DECRYPT throws exception: " + e.getMessage());
throw new UnsupportedCallbackException(pc);
} catch (InvalidKeySpecException e) {
logger.info("callback routine, usage DECRYPT throws exception: " + e.getMessage());
throw new UnsupportedCallbackException(pc);
}
} else if (usage == WSPasswordCallback.KEY_NAME) {
logger.info("callback routine, usage KEY_NAME for alias: " + pc.getIdentifer());
} else if (usage == WSPasswordCallback.SECURITY_CONTEXT_TOKEN) {
logger.info("callback routine, usage SECURITY_CONTEXT_TOKEN for alias: " + pc.getIdentifer());
} else if (usage == WSPasswordCallback.SIGNATURE) {
logger.info("callback routine, usage SIGNATURE for alias: " + pc.getIdentifer());
} else if (usage == WSPasswordCallback.USERNAME_TOKEN) {
logger.info("callback routine, usage USERNAME_TOKEN for alias: " + pc.getIdentifer());
} else if (usage == WSPasswordCallback.UNKNOWN) {
logger.info("callback routine, usage UNKNOWN for alias: " + pc.getIdentifer());
} else {
logger.error("Unsupported password format.", null);
throw new UnsupportedCallbackException(
callbacks[i], "Unsupported password format.");
}
} else {
logger.error("Unrecognized Callback type.", null);
throw new UnsupportedCallbackException(
callbacks[i], "Unrecognized Callback type.");
}
}
}
}
I'm not sure if my issue is a misunderstanding how to use the API, SOAP in general, or a technical issue. Any advice would be appreciated. Thanks.
Re: Creating Derived Encrypted Key w/BinarySecurityToken Ref
Posted by Colm O hEigeartaigh <co...@apache.org>.
WSS4J 1.5.x is long since deprecated and no longer supported. I recommend
upgrading to at least WSS4J 1.6.x and see if you still see the failure. If
so, then if you create a test-case to reproduce the problem I can take a
look.
Colm.
On Wed, Feb 24, 2016 at 10:46 PM, Eaton, Jason <je...@visa.com> wrote:
> Hello I am using Wss4j 1.5.12. We are trying to add an encrypted envelope
> to a SOAP message. Where the encryption key is a derived key encrypted with
> the recipient’s certificate (public key). I am using the test case
> TestWSSecurityNewDK as a sample to accomplish this.
>
>
>
> I first setup certificates and private keys in a java keystore then add
> them to the Crypto instance. I create two keystores, one for the recipient
> and one for the sender. Then I setup the encrypted key object, using a x509
> key identifier. The doc is prepared and then the key and reference is
> saved, to be added to the encryption object later. I then Sign the document
> with a X509 binary token reference. The signed doc is encrypted with the DK
> encrypt object after setting the key and key reference. When I validate the
> document with my own callback I provide the “password”.
>
>
>
> The document is created correctly but then when I try to validate the
> headers, it is not able to decrypt the temporary encryption key. I get “bad
> hash” or “block corrupted” error.
>
>
>
> org.apache.ws.security.WSSecurityException: The signature or decryption
> was invalid
>
> at
> org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:244)
>
> at
> org.apache.ws.security.processor.ReferenceListProcessor.decryptDataRefEmbedded(ReferenceListProcessor.java:166)
>
> at
> org.apache.ws.security.processor.ReferenceListProcessor.handleReferenceList(ReferenceListProcessor.java:113)
>
> at
> org.apache.ws.security.processor.ReferenceListProcessor.handleToken(ReferenceListProcessor.java:76)
>
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:328)
>
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:245)
>
> at
> org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:198)
>
> at
> com.cybersource.nta.ws.WSSecurityFilterTest.testSignAndEncrypt(WSSecurityFilterTest.java:526)
>
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>
> at
> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
>
> at
> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
>
> at
> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
>
> at
> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
>
> at
> org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
>
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
>
> at
> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
>
> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>
> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>
> at
> org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>
> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>
> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>
> at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>
> at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
>
> at
> com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
>
> at
> com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
>
> at
> com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
>
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>
> at
> com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
>
> Caused by: org.apache.xml.security.encryption.XMLEncryptionException: pad
> block corrupted
>
> Original Exception was javax.crypto.BadPaddingException: pad block
> corrupted
>
> at
> org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown
> Source)
>
> at
> org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown Source)
>
> at
> org.apache.xml.security.encryption.XMLCipher.decryptElementContent(Unknown
> Source)
>
> at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown
> Source)
>
> at
> org.apache.ws.security.processor.ReferenceListProcessor.decryptEncryptedData(ReferenceListProcessor.java:242)
>
> ... 33 more
>
>
>
> senderHandler.getCrypto().setKeyStore(setupSenderKeystore());
>
>
>
> WSSecHeader secHeader = *new *WSSecHeader();
> secHeader.insertSecurityHeader(doc);
>
>
>
>
> *// EncryptedKey encrypt with temporary session key // and encrypt this
> temporary session key with the recipient's // public key (certificate) *WSSecEncrypt
> encrKeyBuilder = *new *WSSecEncrypt();
> encrKeyBuilder.setUserInfo(*"cybersource_sjc_us"*);
> encrKeyBuilder.setKeyIdentifierType(WSConstants.*X509_KEY_IDENTIFIER*);
> encrKeyBuilder.setKeyEnc(WSConstants.*KEYTRANSPORT_RSAOEP*);
> encrKeyBuilder.prepare(doc, senderHandler.getCrypto());
>
>
> *//Key information from the EncryptedKey **byte*[] ek =
> encrKeyBuilder.getEphemeralKey();
> String tokenIdentifier = encrKeyBuilder.getId();
>
>
> *// Sign the message with senders private key *WSSecSignature sign = *new
> *WSSecSignature();
> sign.setUserInfo(*"jasoneatoncorp"*, *"jasoneatoncorp"*);
> sign.setSignatureAlgorithm(XMLSignature.*ALGO_ID_SIGNATURE_RSA_SHA256*);
> sign.setKeyIdentifierType(WSConstants.*BST_DIRECT_REFERENCE*);
> Document signedDoc = sign.build(doc, senderHandler.getCrypto(), secHeader);
>
> WSSecDKEncrypt encrBuilder = *new *WSSecDKEncrypt();
> encrBuilder.setSymmetricEncAlgorithm(WSConstants.*AES_128*);
> encrBuilder.setExternalKey(ek, tokenIdentifier);
> Document signedEncryptedDoc = encrBuilder.build(signedDoc, secHeader);
> *assertNotNull*(signedEncryptedDoc);
>
> encrKeyBuilder.prependToHeader(secHeader);
> encrKeyBuilder.prependBSTElementToHeader(secHeader);
>
>
>
>
> *//System.out.println(XMLUtils.PrettyDocumentToString(signedEncryptedDoc));
> // Make this handler for recipient only ( keystore difference ) *DigitalSignatureHandlerImpl2
> recipientHandler = *new *DigitalSignatureHandlerImpl2(*newCASerial*);
> recipientHandler.init(securityDAO);
> recipientHandler.getCrypto().setKeyStore(setupRecipientKeystore());
>
> filter.init(filterConfig);
> filter.*digSigHandler *= recipientHandler;
>
> WSSecurityEngine secEngine = *new *WSSecurityEngine();
> Vector result = secEngine.processSecurityHeader(doc, *null*, *new *MyPasswordCallback(),
> recipientHandler.getCrypto());
>
>
>
> …
>
>
>
> *public class *MyPasswordCallback *implements *CallbackHandler {
> *private *org.apache.log4j.Logger
> *logger *= org.apache.log4j.Logger.*getLogger*(getClass());
>
> *public void *handle(Callback[] callbacks)
> *throws *IOException, UnsupportedCallbackException {
> *for *(*int *i = 0; i < callbacks.*length*; i++) {
> *if *(callbacks[i] *instanceof *WSPasswordCallback) {
> WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
>
> *int *usage = pc.getUsage();
> *if *(usage == WSPasswordCallback.*USERNAME_TOKEN_UNKNOWN*) {
> *logger*.info(*"callback routine, usage USERNAME_TOKEN_UNKNOWN for alias: " *+ pc.getIdentifer());
> } *else if *(usage == WSPasswordCallback.*DECRYPT*) {
> *logger*.info(*"callback routine, usage DECRYPT for alias: " *+ pc.getIdentifer());
> *try *{
> *if *(*"jasoneatoncorp"*.equals(pc.getIdentifier())) {
> pc.setPassword(*"jasoneatoncorp"*);
> pc.setKey(instPrivateKey(*jasonPrivateKey*).getEncoded());
> } *else if *(*"cybersource_sjc_us"*.equals(pc.getIdentifier())) {
> pc.setPassword(*"cybersource_sjc_us"*);
> pc.setKey(instPrivateKey(*newServerKey*).getEncoded());
> }
> } *catch *(CertificateException e) {
> *logger*.info(*"callback routine, usage DECRYPT throws exception: " *+ e.getMessage());
> *throw new *UnsupportedCallbackException(pc);
> } *catch *(IOException e) {
> *logger*.info(*"callback routine, usage DECRYPT throws exception: " *+ e.getMessage());
> *throw new *UnsupportedCallbackException(pc);
> } *catch *(NoSuchAlgorithmException e) {
> *logger*.info(*"callback routine, usage DECRYPT throws exception: " *+ e.getMessage());
> *throw new *UnsupportedCallbackException(pc);
> } *catch *(InvalidKeySpecException e) {
> *logger*.info(*"callback routine, usage DECRYPT throws exception: " *+ e.getMessage());
> *throw new *UnsupportedCallbackException(pc);
> }
> } *else if *(usage == WSPasswordCallback.*KEY_NAME*) {
> *logger*.info(*"callback routine, usage KEY_NAME for alias: " *+ pc.getIdentifer());
> } *else if *(usage == WSPasswordCallback.*SECURITY_CONTEXT_TOKEN*) {
> *logger*.info(*"callback routine, usage SECURITY_CONTEXT_TOKEN for alias: " *+ pc.getIdentifer());
> } *else if *(usage == WSPasswordCallback.*SIGNATURE*) {
> *logger*.info(*"callback routine, usage SIGNATURE for alias: " *+ pc.getIdentifer());
> } *else if *(usage == WSPasswordCallback.*USERNAME_TOKEN*) {
> *logger*.info(*"callback routine, usage USERNAME_TOKEN for alias: " *+ pc.getIdentifer());
> } *else if *(usage == WSPasswordCallback.*UNKNOWN*) {
> *logger*.info(*"callback routine, usage UNKNOWN for alias: " *+ pc.getIdentifer());
> } *else *{
> *logger*.error(*"Unsupported password format."*, *null*);
> *throw new *UnsupportedCallbackException(
> callbacks[i], *"Unsupported password format."*);
> }
> } *else *{
> *logger*.error(*"Unrecognized Callback type."*, *null*);
> *throw new *UnsupportedCallbackException(
> callbacks[i], *"Unrecognized Callback type."*);
> }
> }
> }
> }
>
>
>
>
>
>
>
>
>
>
>
> I’m not sure if my issue is a misunderstanding how to use the API, SOAP in
> general, or a technical issue. Any advice would be appreciated. Thanks.
>
--
Colm O hEigeartaigh
Talend Community Coder
http://coders.talend.com