Forum Discussion

dtillemans's avatar
12 years ago

SOAPUI 4.5.1: Binary Security Token signature

Dear all,

I sign SOAP message and also the binary security token (the X509 certificate who signed the SOAP message). I came to conclusion that from SOAPUI 4.5 this doesn't fucntion anymore, because wss4j has been upgraded to 1.6.x. After some debugging ....build() function of wss4j has been depreciated.
The wssSign.build( doc, wssCrypto.getCrypto(), secHeader ) method still works, but is depreciated. In the wss4j examples they use now another method.

So I made a hack (based on wss4j example) SignatureEntry.java file:

Replace the process() method with following code:

public void process( WSSecHeader secHeader, Document doc, PropertyExpansionContext context )
{
StringWriter writer = null;

try
{
WssCrypto wssCrypto = getWssContainer().getCryptoByName( crypto );
if( wssCrypto == null )
{
throw new Exception( "Missing crypto [" + crypto + "] for signature entry" );
}

// Get Certificate, convert it into a BST and add it to secheader
CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
cryptoType.setAlias(getUsername());
X509Certificate[] certs = wssCrypto.getCrypto().getX509Certificates(cryptoType);
X509Security bst = new X509Security(doc);
String certUri = WSSConfig.getNewInstance().getIdAllocator().createSecureId("X509-", certs[0]);
bst.setX509Certificate(certs[0]);
bst.setID(certUri);
WSSecurityUtil.prependChildElement(secHeader.getSecurityHeader(), bst.getElement());

// Add the signature
WSSecSignature wssSign = new WSSecSignature();
wssSign.setUserInfo( context.expand( getUsername() ), context.expand( getPassword() ) );

// default is
// http://ws.apache.org/wss4j/apidocs/org/ ... UER_SERIAL
if( keyIdentifierType != 0 )
wssSign.setKeyIdentifierType( keyIdentifierType );

if( StringUtils.hasContent( signatureAlgorithm ) && !signatureAlgorithm.equals( DEFAULT_OPTION ) )
wssSign.setSignatureAlgorithm( signatureAlgorithm );

if( StringUtils.hasContent( signatureCanonicalization ) && !signatureCanonicalization.equals( DEFAULT_OPTION ) )
wssSign.setSigCanonicalization( signatureCanonicalization );

wssSign.setUseSingleCertificate( useSingleCert );

if( StringUtils.hasContent( digestAlgorithm ) )
wssSign.setDigestAlgo( digestAlgorithm );

wssSign.setX509Certificate(certs[0]);
List<WSEncryptionPart> wsParts = createWSParts( parts );

// test to see to insert the BST token
for( StringToStringMap map : parts ) {
String name = map.get( "name" );
if( StringUtils.hasContent( name ) )
{
if(name.equalsIgnoreCase("Token"))
{
WSEncryptionPart encP = new WSEncryptionPart(WSConstants.BINARY_TOKEN_LN,
WSConstants.WSSE_NS,
"Element");
encP.setElement(bst.getElement());
wsParts.add(encP);
wssSign.setKeyIdentifierType( WSConstants.CUSTOM_SYMM_SIGNING );
}
}
}

if( !wsParts.isEmpty() )
{
wssSign.setParts( wsParts );
}

wssSign.setCustomTokenId(bst.getID());
wssSign.setCustomTokenValueType(bst.getValueType());

wssSign.prepare(doc, wssCrypto.getCrypto(), secHeader);

writer = new StringWriter();
XmlUtils.serialize( doc, writer );

List<javax.xml.crypto.dsig.Reference> referenceList =
wssSign.addReferencesToSign(wsParts, secHeader);

wssSign.computeSignature(referenceList, false, null);
}
catch( Exception e )
{
SoapUI.logError( e );

if( writer != null && writer.getBuffer().length() > 0 )
{
try
{
doc.replaceChild( doc.importNode( XmlUtils.parseXml( writer.toString() ).getDocumentElement(), true ),
doc.getDocumentElement() );
}
catch( Exception e1 )
{
SoapUI.logError( e1 );
}
}
}
}

and in the WssEntryBase.jave Change the createWSParts() with:

protected Vector<WSEncryptionPart> createWSParts( List<StringToStringMap> parts )
{
Vector<WSEncryptionPart> result = new Vector<WSEncryptionPart>();

for( StringToStringMap map : parts )
{
if( map.hasValue( "id" ) )
{
result.add( new WSEncryptionPart( map.get( "id" ), map.get( "enc" ) ) );
}
else
{
String ns = map.get( "namespace" );
if( ns == null )
ns = "";

String name = map.get( "name" );
if( StringUtils.hasContent( name ) )
{
if( ! name.equalsIgnoreCase("Token"))
result.add( new WSEncryptionPart( name, ns, map.get( "enc" ) ) );
}
}

}

return result;
}

What does it do?
It searches to the 'Token' part in the signature parts and skips it int he createWSParts() function. Afterwards it adds the binary security token to put the signature on in the process() method.

It is not that I mae to many modifications on opensource ;-). So, can this be merge in the next release? Or provide another solution to support signed binary security tokens.

Greetings,
David Tillemans
No RepliesBe the first to reply