9696 * A class that contains several auxiliary methods related to the SAML protocol
9797 */
9898public final class Util {
99+
99100 /**
100101 * Private property to construct a logger for this class.
101102 */
@@ -109,6 +110,11 @@ public final class Util {
109110 /** Indicates if JAXP 1.5 support has been detected. */
110111 private static boolean JAXP_15_SUPPORTED = isJaxp15Supported ();
111112
113+ static {
114+ System .setProperty ("org.apache.xml.security.ignoreLineBreaks" , "true" );
115+ org .apache .xml .security .Init .init ();
116+ }
117+
112118 private Util () {
113119 //not called
114120 }
@@ -380,7 +386,6 @@ public static Document parseXML(InputSource inputSource) throws ParserConfigurat
380386 * @return the Document object
381387 */
382388 public static String convertDocumentToString (Document doc , Boolean c14n ) {
383- org .apache .xml .security .Init .init ();
384389 ByteArrayOutputStream baos = new ByteArrayOutputStream ();
385390 if (c14n ) {
386391 XMLUtils .outputDOMc14nWithComments (doc , baos );
@@ -525,8 +530,6 @@ public static X509Certificate loadCert(String certString) throws CertificateExce
525530 * @throws GeneralSecurityException
526531 */
527532 public static PrivateKey loadPrivateKey (String keyString ) throws GeneralSecurityException {
528- org .apache .xml .security .Init .init ();
529-
530533 String extractedKey = formatPrivateKey (keyString , false );
531534 extractedKey = chunkString (extractedKey , 64 );
532535 KeyFactory kf = KeyFactory .getInstance ("RSA" );
@@ -808,8 +811,6 @@ public static String urlDecoder(String input) {
808811 * @throws SignatureException
809812 */
810813 public static byte [] sign (String text , PrivateKey key , String signAlgorithm ) throws NoSuchAlgorithmException , InvalidKeyException , SignatureException {
811- org .apache .xml .security .Init .init ();
812-
813814 if (signAlgorithm == null ) {
814815 signAlgorithm = Constants .RSA_SHA1 ;
815816 }
@@ -964,8 +965,6 @@ public static Boolean validateMetadataSign(Document doc, X509Certificate cert, S
964965 public static Boolean validateSignNode (Node signNode , X509Certificate cert , String fingerprint , String alg ) {
965966 Boolean res = false ;
966967 try {
967- org .apache .xml .security .Init .init ();
968-
969968 Element sigElement = (Element ) signNode ;
970969 XMLSignature signature = new XMLSignature (sigElement , "" , true );
971970
@@ -1034,8 +1033,6 @@ public static boolean isAlgorithmWhitelisted(String alg) {
10341033 */
10351034 public static void decryptElement (Element encryptedDataElement , PrivateKey inputKey ) {
10361035 try {
1037- org .apache .xml .security .Init .init ();
1038-
10391036 XMLCipher xmlCipher = XMLCipher .getInstance ();
10401037 xmlCipher .init (XMLCipher .DECRYPT_MODE , null );
10411038
@@ -1111,15 +1108,36 @@ public static Document copyDocument(Document source) throws ParserConfigurationE
11111108 * The public certificate
11121109 * @param signAlgorithm
11131110 * Signature Algorithm
1114- *
1111+ *
11151112 * @return the signed document in string format
1116- *
1113+ *
11171114 * @throws XMLSecurityException
11181115 * @throws XPathExpressionException
11191116 */
11201117 public static String addSign (Document document , PrivateKey key , X509Certificate certificate , String signAlgorithm ) throws XMLSecurityException , XPathExpressionException {
1121- org .apache .xml .security .Init .init ();
1118+ return addSign (document , key , certificate , signAlgorithm , Constants .SHA1 );
1119+ }
11221120
1121+ /**
1122+ * Signs the Document using the specified signature algorithm with the private key and the public certificate.
1123+ *
1124+ * @param document
1125+ * The document to be signed
1126+ * @param key
1127+ * The private key
1128+ * @param certificate
1129+ * The public certificate
1130+ * @param signAlgorithm
1131+ * Signature Algorithm
1132+ * @param digestAlgorithm
1133+ * Digest Algorithm
1134+ *
1135+ * @return the signed document in string format
1136+ *
1137+ * @throws XMLSecurityException
1138+ * @throws XPathExpressionException
1139+ */
1140+ public static String addSign (Document document , PrivateKey key , X509Certificate certificate , String signAlgorithm , String digestAlgorithm ) throws XMLSecurityException , XPathExpressionException {
11231141 // Check arguments.
11241142 if (document == null ) {
11251143 throw new IllegalArgumentException ("Provided document was null" );
@@ -1132,18 +1150,21 @@ public static String addSign(Document document, PrivateKey key, X509Certificate
11321150 if (key == null ) {
11331151 throw new IllegalArgumentException ("Provided key was null" );
11341152 }
1135-
1153+
11361154 if (certificate == null ) {
11371155 throw new IllegalArgumentException ("Provided certificate was null" );
11381156 }
11391157
11401158 if (signAlgorithm == null || signAlgorithm .isEmpty ()) {
11411159 signAlgorithm = Constants .RSA_SHA1 ;
11421160 }
1161+ if (digestAlgorithm == null || digestAlgorithm .isEmpty ()) {
1162+ digestAlgorithm = Constants .SHA1 ;
1163+ }
11431164
1144- // document.normalizeDocument();
1165+ document .normalizeDocument ();
11451166
1146- String c14nMethod = Constants .C14NEXC_WC ;
1167+ String c14nMethod = Constants .C14NEXC ;
11471168
11481169 // Signature object
11491170 XMLSignature sig = new XMLSignature (document , null , signAlgorithm , c14nMethod );
@@ -1155,30 +1176,42 @@ public static String addSign(Document document, PrivateKey key, X509Certificate
11551176
11561177 // If Issuer, locate Signature after Issuer, Otherwise as first child.
11571178 NodeList issuerNodes = Util .query (document , "//saml:Issuer" , null );
1179+ Element elemToSign = null ;
11581180 if (issuerNodes .getLength () > 0 ) {
11591181 Node issuer = issuerNodes .item (0 );
11601182 root .insertBefore (sig .getElement (), issuer .getNextSibling ());
1183+ elemToSign = (Element ) issuer .getParentNode ();
11611184 } else {
1162- root .insertBefore (sig .getElement (), root .getFirstChild ());
1185+ NodeList entitiesDescriptorNodes = Util .query (document , "//md:EntitiesDescriptor" , null );
1186+ if (entitiesDescriptorNodes .getLength () > 0 ) {
1187+ elemToSign = (Element )entitiesDescriptorNodes .item (0 );
1188+ } else {
1189+ NodeList entityDescriptorNodes = Util .query (document , "//md:EntityDescriptor" , null );
1190+ if (entityDescriptorNodes .getLength () > 0 ) {
1191+ elemToSign = (Element )entityDescriptorNodes .item (0 );
1192+ } else {
1193+ elemToSign = root ;
1194+ }
1195+ }
1196+ root .insertBefore (sig .getElement (), elemToSign .getFirstChild ());
11631197 }
11641198
1165- String id = root .getAttribute ("ID" );
1199+ String id = elemToSign .getAttribute ("ID" );
11661200
11671201 String reference = id ;
11681202 if (!id .isEmpty ()) {
1169- root .setIdAttributeNS (null , "ID" , true );
1203+ elemToSign .setIdAttributeNS (null , "ID" , true );
11701204 reference = "#" + id ;
11711205 }
11721206
11731207 // Create the transform for the document
11741208 Transforms transforms = new Transforms (document );
11751209 transforms .addTransform (Constants .ENVSIG );
1176- //transforms.addTransform(Transforms.TRANSFORM_C14N_OMIT_COMMENTS);
11771210 transforms .addTransform (c14nMethod );
1178- sig .addDocument (reference , transforms , Constants . SHA1 );
1211+ sig .addDocument (reference , transforms , digestAlgorithm );
11791212
11801213 // Add the certification info
1181- sig .addKeyInfo (certificate );
1214+ sig .addKeyInfo (certificate );
11821215
11831216 // Sign the document
11841217 sig .sign (key );
@@ -1197,14 +1230,16 @@ public static String addSign(Document document, PrivateKey key, X509Certificate
11971230 * The public certificate
11981231 * @param signAlgorithm
11991232 * Signature Algorithm
1200- *
1233+ * @param digestAlgorithm
1234+ * Digest Algorithm
1235+ *
12011236 * @return the signed document in string format
12021237 *
12031238 * @throws ParserConfigurationException
12041239 * @throws XMLSecurityException
12051240 * @throws XPathExpressionException
12061241 */
1207- public static String addSign (Node node , PrivateKey key , X509Certificate certificate , String signAlgorithm ) throws ParserConfigurationException , XPathExpressionException , XMLSecurityException {
1242+ public static String addSign (Node node , PrivateKey key , X509Certificate certificate , String signAlgorithm , String digestAlgorithm ) throws ParserConfigurationException , XPathExpressionException , XMLSecurityException {
12081243 // Check arguments.
12091244 if (node == null ) {
12101245 throw new IllegalArgumentException ("Provided node was null" );
@@ -1216,9 +1251,31 @@ public static String addSign(Node node, PrivateKey key, X509Certificate certific
12161251 Node newNode = doc .importNode (node , true );
12171252 doc .appendChild (newNode );
12181253
1219- return addSign (doc , key , certificate , signAlgorithm );
1220- }
1221-
1254+ return addSign (doc , key , certificate , signAlgorithm , digestAlgorithm );
1255+ }
1256+
1257+ /**
1258+ * Signs a Node using the specified signature algorithm with the private key and the public certificate.
1259+ *
1260+ * @param node
1261+ * The Node to be signed
1262+ * @param key
1263+ * The private key
1264+ * @param certificate
1265+ * The public certificate
1266+ * @param signAlgorithm
1267+ * Signature Algorithm
1268+ *
1269+ * @return the signed document in string format
1270+ *
1271+ * @throws ParserConfigurationException
1272+ * @throws XMLSecurityException
1273+ * @throws XPathExpressionException
1274+ */
1275+ public static String addSign (Node node , PrivateKey key , X509Certificate certificate , String signAlgorithm ) throws ParserConfigurationException , XPathExpressionException , XMLSecurityException {
1276+ return addSign (node , key , certificate , signAlgorithm , Constants .SHA1 );
1277+ }
1278+
12221279 /**
12231280 * Validates signed binary data (Used to validate GET Signature).
12241281 *
@@ -1241,8 +1298,6 @@ public static String addSign(Node node, PrivateKey key, X509Certificate certific
12411298 public static Boolean validateBinarySignature (String signedQuery , byte [] signature , X509Certificate cert , String signAlg ) throws NoSuchAlgorithmException , NoSuchProviderException , InvalidKeyException , SignatureException {
12421299 Boolean valid = false ;
12431300 try {
1244- org .apache .xml .security .Init .init ();
1245-
12461301 String convertedSigAlg = signatureAlgConversion (signAlg );
12471302
12481303 Signature sig = Signature .getInstance (convertedSigAlg ); //, provider);
@@ -1278,7 +1333,6 @@ public static Boolean validateBinarySignature(String signedQuery, byte[] signatu
12781333 public static Boolean validateBinarySignature (String signedQuery , byte [] signature , List <X509Certificate > certList , String signAlg ) throws NoSuchAlgorithmException , NoSuchProviderException , InvalidKeyException , SignatureException {
12791334 Boolean valid = false ;
12801335
1281- org .apache .xml .security .Init .init ();
12821336 String convertedSigAlg = signatureAlgConversion (signAlg );
12831337 Signature sig = Signature .getInstance (convertedSigAlg ); //, provider);
12841338
0 commit comments