Creating Derived Encrypted Key w/BinarySecurityToken Ref

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Creating Derived Encrypted Key w/BinarySecurityToken Ref

Eaton, Jason

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.

Reply | Threaded
Open this post in threaded view
|

Re: Creating Derived Encrypted Key w/BinarySecurityToken Ref

Colm O hEigeartaigh-2
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 <[hidden email]> 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