You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by we...@apache.org on 2005/09/13 08:05:11 UTC
svn commit: r280511 - in /webservices/wss4j/trunk/src/org/apache/ws:
sandbox/security/trust2/ security/ security/message/token/
Author: werner
Date: Mon Sep 12 23:05:01 2005
New Revision: 280511
URL: http://svn.apache.org/viewcvs?rev=280511&view=rev
Log:
Implement the WSS 1.1 feature for UsernameToken derived key. Done
for the message tokens and the WSSecurityEngine.
Modified:
webservices/wss4j/trunk/src/org/apache/ws/sandbox/security/trust2/SecurityTokenOrReference.java
webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityEngine.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
Modified: webservices/wss4j/trunk/src/org/apache/ws/sandbox/security/trust2/SecurityTokenOrReference.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/sandbox/security/trust2/SecurityTokenOrReference.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/sandbox/security/trust2/SecurityTokenOrReference.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/sandbox/security/trust2/SecurityTokenOrReference.java Mon Sep 12 23:05:01 2005
@@ -64,7 +64,7 @@
this.reference = new SecurityTokenReference(element);
if (el.equals(UsernameToken.TOKEN))
this.usernameToken = new UsernameToken(element);
- if (el.equals(BinarySecurity.TOKEN))
+ if (el.equals(BinarySecurity.TOKEN_BST))
this.binarySecurityToken = new BinarySecurity(element);
doc = element.getOwnerDocument();
} catch (WSSecurityException e) {
@@ -129,7 +129,7 @@
WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
if (el.equals(UsernameToken.TOKEN))
return new UsernameToken(tokenElement);
- if (el.equals(BinarySecurity.TOKEN))
+ if (el.equals(BinarySecurity.TOKEN_BST))
return new BinarySecurity(tokenElement);
} catch (WSSecurityException e) {
throw new ElementParsingException("WSSecurityException while trying to create a SecurityToken object from a SecurityTokenReference: "
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSConstants.java Mon Sep 12 23:05:01 2005
@@ -95,6 +95,8 @@
public static final String CREATED_LN = "Created";
public static final String EXPIRES_LN = "Expires";
public static final String SIGNATURE_CONFIRMATION_LN = "SignatureConfirmation";
+ public static final String SALT_LN = "Salt";
+ public static final String ITERATION_LN = "Iteration";
/*
* The definitions for SAML
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityEngine.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityEngine.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityEngine.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSSecurityEngine.java Mon Sep 12 23:05:01 2005
@@ -33,7 +33,6 @@
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
-import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
@@ -63,8 +62,6 @@
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.namespace.QName;
import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.CertificateExpiredException;
@@ -88,7 +85,6 @@
private static Log tlog =
LogFactory.getLog("org.apache.ws.security.TIME");
- private static final Class[] constructorType = {org.w3c.dom.Element.class};
private static WSSecurityEngine engine = null;
private static WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
/**
@@ -500,7 +496,7 @@
*/
QName el = new QName(token.getNamespaceURI(), token
.getLocalName());
- if (token.getLocalName().equals(WSConstants.USERNAME_TOKEN_LN)) {
+ if (el.equals(usernameToken)) {
ut = new UsernameToken(token);
secretKey = ut.getSecretKey();
} else {
@@ -508,7 +504,7 @@
throw new WSSecurityException(WSSecurityException.FAILURE,
"noSigCryptoFile");
}
- if (token.getLocalName().equals(binaryToken.getLocalPart())) {
+ if (el.equals(binaryToken)) {
certs = getCertificatesTokenReference((Element) token,
crypto);
} else if (el.equals(SAML_TOKEN)) {
@@ -646,10 +642,8 @@
X509Certificate[] certs = new X509Certificate[1];
certs[0] = cert;
return certs;
- } else {
- throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
- "unhandledToken", new Object[]{token.getClass().getName()});
}
+ return null;
}
/**
@@ -742,39 +736,21 @@
private BinarySecurity createSecurityToken(Element element) throws WSSecurityException {
BinarySecurity token = new BinarySecurity(element);
String type = token.getValueType();
- Class clazz = null;
- if (type.equals(X509Security.getType())) {
- clazz = X509Security.class;
- } else if (type.equals(PKIPathSecurity.getType())) {
- clazz = PKIPathSecurity.class;
- }
- if (clazz == null) {
- throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
- "unsupportedBinaryTokenType", new Object[]{type});
- }
- try {
- Constructor constructor = clazz.getConstructor(constructorType);
- if (constructor == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidConstructor", new Object[]{clazz});
- }
- return (BinarySecurity) constructor.newInstance(new Object[]{element});
- } catch (InvocationTargetException e) {
- Throwable ee = e.getTargetException();
- if (ee instanceof WSSecurityException) {
- throw (WSSecurityException) ee;
- } else {
- throw new WSSecurityException(WSSecurityException.FAILURE, null, null, e);
- }
- } catch (NoSuchMethodException e) {
- throw new WSSecurityException(WSSecurityException.FAILURE, null, null, e);
- } catch (InstantiationException e) {
- throw new WSSecurityException(WSSecurityException.FAILURE, null, null, e);
- } catch (IllegalAccessException e) {
- throw new WSSecurityException(WSSecurityException.FAILURE, null, null, e);
+ X509Security x509 = null;
+ PKIPathSecurity pkiPath = null;
+
+ if (X509Security.getType().equals(type)) {
+ x509 = new X509Security(element);
+ return (BinarySecurity)x509;
+ } else if (PKIPathSecurity.getType().equals(type)) {
+ pkiPath = new PKIPathSecurity(element);
+ return (BinarySecurity)pkiPath;
}
+ throw new WSSecurityException(WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+ "unsupportedBinaryTokenType", new Object[]{type});
}
+
/**
* Check the UsernameToken element. Depending on the password type
* contained in the element the processing differs. If the password type
@@ -956,9 +932,7 @@
throw new WSSecurityException
(WSSecurityException.INVALID_SECURITY, "noCipher");
}
- // here get the reference to the private key / shared secret key.
- // Shared secret key not yet supported
- // see check above ... maybe later
+
if (privateKey == null) {
Element keyInfo = (Element) WSSecurityUtil.getDirectChild((Node) xencEncryptedKey,
"KeyInfo", WSConstants.SIG_NS);
@@ -998,7 +972,7 @@
* If wsse:KeyIdentifier found, then the public key of the attached cert was used to
* encrypt the session (symmetric) key that encrypts the data. Extract the certificate
* using the BinarySecurity token (was enhanced to handle KeyIdentifier too).
- * This method is _not_recommended by OASIS WS-S specification, X509 profile
+ * This method is _not_ recommended by OASIS WS-S specification, X509 profile
*/
else if (secRef.containsKeyIdentifier()) {
X509Certificate[] certs = secRef.getKeyIdentifier(crypto);
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/BinarySecurity.java Mon Sep 12 23:05:01 2005
@@ -34,9 +34,10 @@
* <p/>
*
* @author Davanum Srinivas (dims@yahoo.com).
+ * @author Werner Dittmann (Werner.Dittmann@t-onile.de).
*/
public class BinarySecurity {
- public static final QName TOKEN = new QName(WSConstants.WSSE_NS, "BinarySecurityToken");
+ public static final QName TOKEN_BST = new QName(WSConstants.WSSE_NS, "BinarySecurityToken");
public static final QName TOKEN_KI = new QName(WSConstants.WSSE_NS, "KeyIdentifier");
public static final String BASE64_ENCODING = WSConstants.SOAPMESSAGE_NS + "#Base64Binary";
protected Element element = null;
@@ -50,19 +51,41 @@
*/
public BinarySecurity(Element elem) throws WSSecurityException {
this.element = elem;
- QName el = new QName(this.element.getNamespaceURI(), this.element.getLocalName());
- if (!el.equals(TOKEN) && !el.equals(TOKEN_KI)) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType", new Object[]{el});
+ QName el = new QName(this.element.getNamespaceURI(), this.element
+ .getLocalName());
+ if (!el.equals(TOKEN_BST) && !el.equals(TOKEN_KI)) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType",
+ new Object[] { el });
}
String encoding = getEncodingType();
- if (encoding.length() > 0 && !encoding.equals(BASE64_ENCODING)) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badEncoding", new Object[]{getEncodingType()});
+ /*
+ * if the Element is a BinarySecurityToken then
+ * encoding may be null -> default is Base64
+ * if encoding is not null and not empty it must be Base64
+ * else
+ * this is a keyidentifier element
+ * must contain an encoding attribute which must be Base64
+ * in this case
+ */
+ if (el.equals(TOKEN_BST)) {
+ if (encoding != null && encoding.length() > 0
+ && !encoding.equals(BASE64_ENCODING)) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badEncoding", new Object[] { encoding });
+ }
+ } else if (el.equals(TOKEN_KI)) {
+ if (encoding == null || !encoding.equals(BASE64_ENCODING)) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badEncoding", new Object[] { encoding });
+ }
}
}
/**
* Constructor.
- * <p/>
*
* @param doc
*/
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java Mon Sep 12 23:05:01 2005
@@ -206,18 +206,8 @@
throw new WSSecurityException(WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
"encodeError");
}
- Text certText = doc.createTextNode(Base64.encode(data));
- Element keyId =
- doc.createElementNS(WSConstants.WSSE_NS, "wsse:KeyIdentifier");
- keyId.setAttributeNS(null, "ValueType", X509Security.getType());
- keyId.setAttributeNS(null, "EncodingType", BinarySecurity.BASE64_ENCODING);
- keyId.appendChild(certText);
- Element elem = getFirstElement();
- if (elem != null) {
- this.element.replaceChild(keyId, elem);
- } else {
- this.element.appendChild(keyId);
- }
+ Text text = doc.createTextNode(Base64.encode(data));
+ createKeyIdentifier(doc, X509Security.getType(), text);
}
/**
@@ -317,8 +307,7 @@
}
} else if (SKI_URI.equals(value)) {
alias = getX509SKIAlias(crypto);
- }
- else if (THUMB_URI.equals(value)) {
+ } else if (THUMB_URI.equals(value)) {
Node node = getFirstElement().getFirstChild();
if (node == null) {
return null;
@@ -327,7 +316,7 @@
byte[] thumb = Base64.decode(((Text) node).getData());
alias = crypto.getAliasForX509CertThumb(thumb);
}
-
+
}
if (alias != null) {
return crypto.getCertificates(alias);
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java?rev=280511&r1=280510&r2=280511&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java Mon Sep 12 23:05:01 2005
@@ -42,9 +42,8 @@
import java.util.TimeZone;
/**
- * UsernameToken according to WS Security specifications,
- * UsernameToken profile.
- *
+ * UsernameToken according to WS Security specifications, UsernameToken profile.
+ *
* @author Davanum Srinivas (dims@yahoo.com)
* @author Werner Dittmann (Werner.Dittmann@siemens.com)
*/
@@ -54,15 +53,29 @@
public static final String PASSWORD_TYPE = "passwordType";
protected Element element = null;
+
protected Element elementUsername = null;
+
protected Element elementPassword = null;
+
protected Element elementNonce = null;
+
protected Element elementCreated = null;
+
+ protected Element elementSalt = null;
+
+ protected Element elementIteration = null;
+
protected String passwordType = null;
+
protected boolean hashed = true;
+
private static SecureRandom random = null;
-
- public static final QName TOKEN = new QName(WSConstants.WSSE_NS, WSConstants.USERNAME_TOKEN_LN);
+
+ private static int DEFAULT_ITERATION = 1000;
+
+ public static final QName TOKEN = new QName(WSConstants.WSSE_NS,
+ WSConstants.USERNAME_TOKEN_LN);
static {
try {
@@ -75,79 +88,113 @@
/**
* Constructs a <code>UsernameToken</code> object and parses the
* <code>wsse:UsernameToken</code> element to initialize it.
- *
- * @param elem the <code>wsse:UsernameToken</code> element that
- * contains the UsernameToken data
+ *
+ * @param elem
+ * the <code>wsse:UsernameToken</code> element that contains
+ * the UsernameToken data
* @throws WSSecurityException
*/
public UsernameToken(Element elem) throws WSSecurityException {
this.element = elem;
- QName el = new QName(this.element.getNamespaceURI(), this.element.getLocalName());
+ QName el = new QName(this.element.getNamespaceURI(), this.element
+ .getLocalName());
if (!el.equals(TOKEN)) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType00", new Object[]{el});
- }
- elementUsername = (Element) WSSecurityUtil.getDirectChild(element, "Username", WSConstants.WSSE_NS);
- elementPassword = (Element) WSSecurityUtil.getDirectChild(element, "Password", WSConstants.WSSE_NS);
- elementNonce = (Element) WSSecurityUtil.getDirectChild(element, "Nonce", WSConstants.WSSE_NS);
- elementCreated = (Element) WSSecurityUtil.getDirectChild(element, "Created", WSConstants.WSU_NS);
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badTokenType00", new Object[] { el });
+ }
+ elementUsername = (Element) WSSecurityUtil.getDirectChild(element,
+ "Username", WSConstants.WSSE_NS);
+ elementPassword = (Element) WSSecurityUtil.getDirectChild(element,
+ "Password", WSConstants.WSSE_NS);
+ elementNonce = (Element) WSSecurityUtil.getDirectChild(element,
+ "Nonce", WSConstants.WSSE_NS);
+ elementCreated = (Element) WSSecurityUtil.getDirectChild(element,
+ "Created", WSConstants.WSU_NS);
+ elementSalt = (Element) WSSecurityUtil.getDirectChild(element, "Salt",
+ WSConstants.WSSE11_NS);
+ elementIteration = (Element) WSSecurityUtil.getDirectChild(element,
+ "Interation", WSConstants.WSSE11_NS);
if (elementUsername == null) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType01", new Object[]{el});
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badTokenType01", new Object[] { el });
+ }
+ if (elementSalt != null) {
+ if (elementPassword != null) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badTokenType01", new Object[] { el });
+ }
+ return;
}
hashed = false;
if (elementPassword != null) {
passwordType = elementPassword.getAttribute("Type");
}
- if (passwordType != null && passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
+ if (passwordType != null
+ && passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
hashed = true;
if (elementNonce == null || elementCreated == null) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY_TOKEN, "badTokenType01", new Object[]{el});
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY_TOKEN,
+ "badTokenType01", new Object[] { el });
}
}
}
/**
- * Constructs a <code>UsernameToken</code> object according
- * to the defined parameters.
- * <p/>
- * This constructes set the password encoding to
+ * Constructs a <code>UsernameToken</code> object according to the defined
+ * parameters. <p/> This constructes set the password encoding to
* {@link WSConstants#PASSWORD_DIGEST}
- *
- * @param doc the SOAP envelope as <code>Document</code>
+ *
+ * @param doc
+ * the SOAP envelope as <code>Document</code>
*/
public UsernameToken(boolean milliseconds, Document doc) {
this(milliseconds, doc, WSConstants.PASSWORD_DIGEST);
}
/**
- * Constructs a <code>UsernameToken</code> object according
- * to the defined parameters.
- * <p/>
- *
- * @param doc the SOAP envelope as <code>Document</code>
- * @param pwType the required password encoding, either
- * {@link WSConstants#PASSWORD_DIGEST} or
- * {@link WSConstants#PASSWORD_TEXT}
+ * Constructs a <code>UsernameToken</code> object according to the defined
+ * parameters. <p/>
+ *
+ * @param doc
+ * the SOAP envelope as <code>Document</code>
+ * @param pwType
+ * the required password encoding, either
+ * {@link WSConstants#PASSWORD_DIGEST} or
+ * {@link WSConstants#PASSWORD_TEXT} or <code>null</code> if no
+ * password required
*/
public UsernameToken(boolean milliseconds, Document doc, String pwType) {
- this.element = doc.createElementNS(WSConstants.WSSE_NS, "wsse:" + WSConstants.USERNAME_TOKEN_LN);
- WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
-
- this.elementUsername = doc.createElementNS(WSConstants.WSSE_NS, "wsse:" + WSConstants.USERNAME_LN);
- WSSecurityUtil.setNamespace(this.elementUsername, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
+ this.element = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+ + WSConstants.USERNAME_TOKEN_LN);
+ WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE_NS,
+ WSConstants.WSSE_PREFIX);
+
+ this.elementUsername = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+ + WSConstants.USERNAME_LN);
+ WSSecurityUtil.setNamespace(this.elementUsername, WSConstants.WSSE_NS,
+ WSConstants.WSSE_PREFIX);
this.elementUsername.appendChild(doc.createTextNode(""));
element.appendChild(elementUsername);
- this.elementPassword = doc.createElementNS(WSConstants.WSSE_NS, "wsse:" + WSConstants.PASSWORD_LN);
- WSSecurityUtil.setNamespace(this.elementPassword, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
- this.elementPassword.appendChild(doc.createTextNode(""));
- element.appendChild(elementPassword);
-
- hashed = false;
- passwordType = pwType;
- if (passwordType != null && passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
- hashed = true;
- addNonce(doc);
- addCreated(milliseconds, doc);
+ if (pwType != null) {
+ this.elementPassword = doc.createElementNS(WSConstants.WSSE_NS,
+ "wsse:" + WSConstants.PASSWORD_LN);
+ WSSecurityUtil.setNamespace(this.elementPassword,
+ WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
+ this.elementPassword.appendChild(doc.createTextNode(""));
+ element.appendChild(elementPassword);
+
+ hashed = false;
+ passwordType = pwType;
+ if (passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
+ hashed = true;
+ addNonce(doc);
+ addCreated(milliseconds, doc);
+ }
}
}
@@ -160,9 +207,12 @@
}
byte[] nonceValue = new byte[16];
random.nextBytes(nonceValue);
- this.elementNonce = doc.createElementNS(WSConstants.WSSE_NS, "wsse:" + WSConstants.NONCE_LN);
- WSSecurityUtil.setNamespace(this.elementNonce, WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX);
- this.elementNonce.appendChild(doc.createTextNode(Base64.encode(nonceValue)));
+ this.elementNonce = doc.createElementNS(WSConstants.WSSE_NS, "wsse:"
+ + WSConstants.NONCE_LN);
+ WSSecurityUtil.setNamespace(this.elementNonce, WSConstants.WSSE_NS,
+ WSConstants.WSSE_PREFIX);
+ this.elementNonce.appendChild(doc.createTextNode(Base64
+ .encode(nonceValue)));
element.appendChild(elementNonce);
}
@@ -175,35 +225,81 @@
}
DateFormat zulu = null;
if (milliseconds) {
- zulu = new XmlSchemaDateFormat();
- }
- else {
- zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
- zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
+ zulu = new XmlSchemaDateFormat();
+ } else {
+ zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
}
Calendar rightNow = Calendar.getInstance();
- this.elementCreated = doc.createElementNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
- WSSecurityUtil.setNamespace(this.elementCreated, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
- this.elementCreated.appendChild(doc.createTextNode(zulu.format(rightNow.getTime())));
+ this.elementCreated = doc.createElementNS(WSConstants.WSU_NS,
+ WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
+ WSSecurityUtil.setNamespace(this.elementCreated, WSConstants.WSU_NS,
+ WSConstants.WSU_PREFIX);
+ this.elementCreated.appendChild(doc.createTextNode(zulu.format(rightNow
+ .getTime())));
element.appendChild(elementCreated);
}
/**
+ * Adds and otionally creates a Salt element to this UsernameToken.
+ *
+ * If the <code>saltCalue</code> is <code>null</code> the the method
+ * generates a new salt. Otherwise it uses the the given value.
+ *
+ * @param doc
+ * The Document for the UsernameToken
+ * @param saltValue
+ * The salt to add, if null generate a new salt value
+ * @param mac
+ * If <code>true</code> then an optionally generated value is
+ * usable for a MAC
+ * @return Returns the added salt
+ */
+ public byte[] addSalt(Document doc, byte[] saltValue, boolean mac) {
+
+ if (saltValue == null) {
+ saltValue = generateSalt(mac);
+ }
+ this.elementSalt = doc.createElementNS(WSConstants.WSSE11_NS,
+ WSConstants.WSSE11_PREFIX + WSConstants.SALT_LN);
+ WSSecurityUtil.setNamespace(this.elementSalt, WSConstants.WSSE11_NS,
+ WSConstants.WSSE11_PREFIX);
+ this.elementSalt.appendChild(doc.createTextNode(Base64
+ .encode(saltValue)));
+ element.appendChild(elementSalt);
+ return saltValue;
+ }
+
+ /**
+ * Creates and adds a Iteration element to this UsernameToken
+ */
+ public void addIteration(Document doc, int iteration) {
+ String text = "" + iteration;
+ this.elementIteration = doc.createElementNS(WSConstants.WSSE11_NS,
+ WSConstants.WSSE11_PREFIX + WSConstants.ITERATION_LN);
+ WSSecurityUtil.setNamespace(this.elementIteration,
+ WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
+ this.elementIteration.appendChild(doc.createTextNode(text));
+ element.appendChild(elementIteration);
+ return;
+ }
+
+ /**
* Get the user name.
- *
+ *
* @return the data from the user name element.
*/
public String getName() {
- return nodeString (this.elementUsername);
- }
+ return nodeString(this.elementUsername);
+ }
/**
- * Set the user name.
- *
- * @param name
- * sets a text node containing the use name into the user name
- * element.
- */
+ * Set the user name.
+ *
+ * @param name
+ * sets a text node containing the use name into the user name
+ * element.
+ */
public void setName(String name) {
Text node = getFirstNode(this.elementUsername);
node.setData(name);
@@ -211,37 +307,67 @@
/**
* Get the nonce.
- *
+ *
* @return the data from the nonce element.
*/
public String getNonce() {
- return nodeString(this.elementNonce);
- }
+ return nodeString(this.elementNonce);
+ }
/**
- * Get the created timestamp.
- *
- * @return the data from the created time element.
- */
+ * Get the created timestamp.
+ *
+ * @return the data from the created time element.
+ */
public String getCreated() {
- return nodeString(this.elementCreated);
- }
+ return nodeString(this.elementCreated);
+ }
/**
- * Gets the password string. This is the password as it is in the password
- * element of a username, token. Thus it can be either plain text or the
- * password digest value.
- *
- * @return the password string or <code>null</code> if no such node
- * exists.
- */
+ * Gets the password string. This is the password as it is in the password
+ * element of a username, token. Thus it can be either plain text or the
+ * password digest value.
+ *
+ * @return the password string or <code>null</code> if no such node
+ * exists.
+ */
public String getPassword() {
- return nodeString(this.elementPassword);
+ return nodeString(this.elementPassword);
+ }
+
+ /**
+ * Get the Salt value of this UsernameToken.
+ *
+ * @return Returns the binary Salt value or <code>null</code> if no Salt
+ * value is available in the username token.
+ * @throws WSSecurityException
+ */
+ public byte[] getSalt() throws WSSecurityException {
+ String salt = nodeString(this.elementSalt);
+ if (salt != null) {
+ return Base64.decode(nodeString(this.elementSalt));
+ }
+ return null;
}
/**
- * Get the hashed inidicator.
- * If the indicator is <code>true> the password of the
+ * Get the Iteration value of this UsernameToken.
+ *
+ * @return Returns the Iteration value. If no Iteration was specified in the
+ * username token the default value according to the specification
+ * is returned.
+ */
+ public int getIteration() {
+ String iter = nodeString(this.elementIteration);
+ if (iter != null) {
+ return Integer.parseInt(iter);
+ }
+ return DEFAULT_ITERATION;
+ }
+
+ /**
+ * Get the hashed inidicator. If the indicator is
+ * <code>true> the password of the
* <code>UsernameToken</code> was encoded using
* {@link WSConstants#PASSWORD_DIGEST}
*
@@ -251,20 +377,21 @@
return hashed;
}
- /**
- * @return Returns the passwordType.
- */
- public String getPasswordType() {
- return passwordType;
- }
- /**
- * Sets the password string.
- * This function sets the password in the <code>UsernameToken</code>
- * either as plain text or encodes the password according to the
- * WS Security specifications, UsernameToken profile, into a password
- * digest.
- *
- * @param pwd the password to use
+ /**
+ * @return Returns the passwordType.
+ */
+ public String getPasswordType() {
+ return passwordType;
+ }
+
+ /**
+ * Sets the password string. This function sets the password in the
+ * <code>UsernameToken</code> either as plain text or encodes the password
+ * according to the WS Security specifications, UsernameToken profile, into
+ * a password digest.
+ *
+ * @param pwd
+ * the password to use
*/
public void setPassword(String pwd) {
if (pwd == null) {
@@ -274,7 +401,8 @@
try {
if (!hashed) {
node.setData(pwd);
- this.elementPassword.setAttribute("Type", WSConstants.PASSWORD_TEXT);
+ this.elementPassword.setAttribute("Type",
+ WSConstants.PASSWORD_TEXT);
} else {
byte[] b1 = Base64.decode(getNonce());
byte[] b2 = getCreated().getBytes("UTF-8");
@@ -295,14 +423,16 @@
sha.reset();
sha.update(b4);
node.setData(Base64.encode(sha.digest()));
- this.elementPassword.setAttribute("Type", WSConstants.PASSWORD_DIGEST);
+ this.elementPassword.setAttribute("Type",
+ WSConstants.PASSWORD_DIGEST);
}
} catch (Exception e) {
e.printStackTrace();
}
}
- public static String doPasswordDigest(String nonce, String created, String password) {
+ public static String doPasswordDigest(String nonce, String created,
+ String password) {
String passwdDigest = null;
try {
byte[] b1 = Base64.decode(nonce);
@@ -332,10 +462,11 @@
/**
* Returns the first text node of an element.
- *
- * @param e the element to get the node from
- * @return the first text node or <code>null</code> if node
- * is null or is not a text node
+ *
+ * @param e
+ * the element to get the node from
+ * @return the first text node or <code>null</code> if node is null or is
+ * not a text node
*/
private Text getFirstNode(Element e) {
Node node = e.getFirstChild();
@@ -343,25 +474,27 @@
}
/**
- * Returns the data of an elemen as String or null if either the
- * the element does not contain a Text node or the node is empty.
+ * Returns the data of an elemen as String or null if either the the element
+ * does not contain a Text node or the node is empty.
*
- * @param e DOM element
+ * @param e
+ * DOM element
* @return Element text node data as String
*/
private String nodeString(Element e) {
if (e != null) {
- Text node = getFirstNode(e);
- if (node != null) {
- return node.getData();
- }
- }
- return null;
-
+ Text node = getFirstNode(e);
+ if (node != null) {
+ return node.getData();
+ }
+ }
+ return null;
+
}
+
/**
* Returns the dom element of this <code>UsernameToken</code> object.
- *
+ *
* @return the <code>wsse:UsernameToken</code> element
*/
public Element getElement() {
@@ -370,7 +503,7 @@
/**
* Returns the string representation of the token.
- *
+ *
* @return a XML string representation
*/
public String toString() {
@@ -379,9 +512,9 @@
/**
* Gets the id.
- *
- * @return the value of the <code>wsu:Id</code> attribute of this
- * username token
+ *
+ * @return the value of the <code>wsu:Id</code> attribute of this username
+ * token
*/
public String getID() {
return this.element.getAttributeNS(WSConstants.WSU_NS, "Id");
@@ -389,9 +522,10 @@
/**
* Set the id of this username token.
- *
- * @param id the value for the <code>wsu:Id</code> attribute of this
- * username token
+ *
+ * @param id
+ * the value for the <code>wsu:Id</code> attribute of this
+ * username token
*/
public void setID(String id) {
String prefix = WSSecurityUtil.setNamespace(this.element,
@@ -400,25 +534,27 @@
}
/**
- * Gets the secret key as per WS-Trust spec.
- * This mthod uses default setting to generate the secret key. These
- * default values are suitable for .NET WSE.
- *
- * @return a secret key constructed from information conatined in
- * this username token
+ * Gets the secret key as per WS-Trust spec. This mthod uses default setting
+ * to generate the secret key. These default values are suitable for .NET
+ * WSE.
+ *
+ * @return a secret key constructed from information conatined in this
+ * username token
*/
public byte[] getSecretKey() {
- return getSecretKey(WSConstants.WSE_DERIVED_KEY_LEN,
- WSConstants.LABEL_FOR_DERIVED_KEY);
- }
-
+ return getSecretKey(WSConstants.WSE_DERIVED_KEY_LEN,
+ WSConstants.LABEL_FOR_DERIVED_KEY);
+ }
+
/**
* Gets the secret key as per WS-Trust spec.
- *
- * @param keylen How many bytes to generate for the key
- * @param labelString the label used to generate the seed
- * @return a secret key constructed from information conatined in
- * this username token
+ *
+ * @param keylen
+ * How many bytes to generate for the key
+ * @param labelString
+ * the label used to generate the seed
+ * @return a secret key constructed from information conatined in this
+ * username token
*/
public byte[] getSecretKey(int keylen, String labelString) {
byte[] key = null;
@@ -441,15 +577,15 @@
seed[count++] = created[i];
}
key = P_hash(password, seed, mac, keylen);
-
+
if (log.isDebugEnabled()) {
- log.debug("password :" + Base64.encode(password));
- log.debug("label :" + Base64.encode(label));
- log.debug("nonce :" + Base64.encode(nonce));
- log.debug("created :" + Base64.encode(created));
- log.debug("seed :" + Base64.encode(seed));
- log.debug("Key :" + Base64.encode(key));
- }
+ log.debug("password :" + Base64.encode(password));
+ log.debug("label :" + Base64.encode(label));
+ log.debug("nonce :" + Base64.encode(nonce));
+ log.debug("created :" + Base64.encode(created));
+ log.debug("seed :" + Base64.encode(seed));
+ log.debug("Key :" + Base64.encode(key));
+ }
} catch (Exception e) {
return null;
}
@@ -457,50 +593,120 @@
}
/**
+ * This static method generates a derived key as defined in WSS Username
+ * Token Profile.
+ *
+ * @param password
+ * The password to include in the key generation
+ * @param salt
+ * The Salt value
+ * @param iteration
+ * The Iteration value. If zero (0) is given the mehtod uses the
+ * default value
+ * @return Returns the derived key a byte array
+ * @throws WSSecurityException
+ */
+ public static byte[] generateDerivedKey(String password, byte[] salt,
+ int iteration) throws WSSecurityException {
+
+ if (iteration == 0) {
+ iteration = DEFAULT_ITERATION;
+ }
+ byte[] pwBytes = password.getBytes();
+
+ byte[] pwSalt = new byte[salt.length + pwBytes.length];
+ System.arraycopy(pwBytes, 0, pwSalt, 0, pwBytes.length);
+ System.arraycopy(salt, 0, pwSalt, pwBytes.length, salt.length);
+
+ MessageDigest sha = null;
+ try {
+ sha = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ throw new WSSecurityException(0, "noSHA1availabe");
+ }
+ sha.reset();
+
+ /*
+ * Make the first hash round with start value
+ */
+ byte[] K = sha.digest(pwSalt);
+ /*
+ * Perform the 2nd up to iteration hash rounds
+ */
+ for (int i = 2; i <= iteration; i++) {
+ sha.reset();
+ K = sha.digest(K);
+ }
+ return K;
+ }
+
+ /**
+ * This static method generates a 128 bit salt value as defined in WSS
+ * Username Token Profile.
+ *
+ * @param useForMac
+ * If <code>true</code> define the Salt for use in a MAC
+ * @return Returns the 128 bit salt value as byte array
+ */
+ public static byte[] generateSalt(boolean useForMac) {
+ byte[] saltValue = new byte[16];
+ random.nextBytes(saltValue);
+ if (useForMac) {
+ saltValue[15] = 0x01;
+ } else {
+ saltValue[15] = 0x02;
+ }
+ return saltValue;
+ }
+
+ /**
* P_hash as defined in RFC 2246 for TLS.
- * <p/>
- *
- * @param secret is the key for the HMAC
- * @param seed the seed value to start the generation - A(0)
- * @param mac the HMAC algorithm
- * @param required number of bytes to generate
+ *
+ * @param secret
+ * is the key for the HMAC
+ * @param seed
+ * the seed value to start the generation - A(0)
+ * @param mac
+ * the HMAC algorithm
+ * @param required
+ * number of bytes to generate
* @return a byte array that conatins a secrect key
* @throws Exception
*/
private static byte[] P_hash(byte[] secret, byte[] seed, Mac mac,
- int required) throws Exception {
- byte[] out = new byte[required];
- int offset = 0, tocpy;
- byte[] A, tmp;
- /*
- * A(0) is the seed
- */
- A = seed;
- SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
- mac.init(key);
- while (required > 0) {
- mac.update(A);
- A = mac.doFinal();
- mac.update(A);
- mac.update(seed);
- tmp = mac.doFinal();
- tocpy = min(required, tmp.length);
- System.arraycopy(tmp, 0, out, offset, tocpy);
- offset += tocpy;
- required -= tocpy;
- }
- return out;
- }
-
-/*
- * public static void main(String[] args) throws Exception { byte[] secret =
- * Base64.decode("A4BKgeqUKi9VDwWyYPDrskwCwEQ5RIqH"); byte[] seed =
- * Base64.decode("bWFzdGVyIHNlY3JldAAAAAAAAAAAAAAAAAAAAAAy+BE8DDEUf+XnAynZEVU0PUQR4QHesAbNCmt8/Ry6NqBELuBAiZV4Z0FuCT58Fi8=");
- * int required = 48; Mac mac = Mac.getInstance("HMACSHA1"); byte[] out =
- * UsernameToken.P_hash(secret, seed, mac, 48);
- * System.out.println(Base64.encode(out));
- * //UCbz0pT2DxRfx4IpY6iWRE0KCa4Fg9JKNRlrxE8AtjNjb1NEK17NI6XdrMRMOKM2 }
- */
+ int required) throws Exception {
+ byte[] out = new byte[required];
+ int offset = 0, tocpy;
+ byte[] A, tmp;
+ /*
+ * A(0) is the seed
+ */
+ A = seed;
+ SecretKeySpec key = new SecretKeySpec(secret, "HMACSHA1");
+ mac.init(key);
+ while (required > 0) {
+ mac.update(A);
+ A = mac.doFinal();
+ mac.update(A);
+ mac.update(seed);
+ tmp = mac.doFinal();
+ tocpy = min(required, tmp.length);
+ System.arraycopy(tmp, 0, out, offset, tocpy);
+ offset += tocpy;
+ required -= tocpy;
+ }
+ return out;
+ }
+
+ /*
+ * public static void main(String[] args) throws Exception { byte[] secret =
+ * Base64.decode("A4BKgeqUKi9VDwWyYPDrskwCwEQ5RIqH"); byte[] seed =
+ * Base64.decode("bWFzdGVyIHNlY3JldAAAAAAAAAAAAAAAAAAAAAAy+BE8DDEUf+XnAynZEVU0PUQR4QHesAbNCmt8/Ry6NqBELuBAiZV4Z0FuCT58Fi8=");
+ * int required = 48; Mac mac = Mac.getInstance("HMACSHA1"); byte[] out =
+ * UsernameToken.P_hash(secret, seed, mac, 48);
+ * System.out.println(Base64.encode(out));
+ * //UCbz0pT2DxRfx4IpY6iWRE0KCa4Fg9JKNRlrxE8AtjNjb1NEK17NI6XdrMRMOKM2 }
+ */
/**
* helper method.
---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org