2727import java .security .cert .CertificateFactory ;
2828import java .security .cert .X509Certificate ;
2929import java .security .spec .PKCS8EncodedKeySpec ;
30+ import java .util .Arrays ;
3031import java .util .Calendar ;
3132import java .util .HashMap ;
3233import java .util .HashSet ;
@@ -116,6 +117,8 @@ public final class Util {
116117 /** Indicates if JAXP 1.5 support has been detected. */
117118 private static boolean JAXP_15_SUPPORTED = isJaxp15Supported ();
118119
120+ private static final Set <String > DEPRECATED_ALGOS = new HashSet <>(Arrays .asList (Constants .RSA_SHA1 , Constants .DSA_SHA1 ));
121+
119122 static {
120123 System .setProperty ("org.apache.xml.security.ignoreLineBreaks" , "true" );
121124 org .apache .xml .security .Init .init ();
@@ -923,13 +926,30 @@ public static boolean validateSign(final Document doc, final X509Certificate cer
923926 */
924927 public static boolean validateSign (final Document doc , final List <X509Certificate > certList , final String fingerprint ,
925928 final String alg , final String xpath ) {
929+ return validateSign (doc , certList , fingerprint ,alg , xpath , false );
930+ }
931+
932+ /**
933+ * Validate the signature pointed to by the xpath
934+ *
935+ * @param doc The document we should validate
936+ * @param certList The public certificates
937+ * @param fingerprint The fingerprint of the public certificate
938+ * @param alg The signature algorithm method
939+ * @param xpath the xpath of the ds:Signture node to validate
940+ * @param rejectDeprecatedAlg Flag to invalidate or not Signatures with deprecated alg
941+ *
942+ * @return True if the signature exists and is valid, false otherwise.
943+ */
944+ public static boolean validateSign (final Document doc , final List <X509Certificate > certList , final String fingerprint ,
945+ final String alg , final String xpath , final Boolean rejectDeprecatedAlg ) {
926946 try {
927947 final NodeList signatures = query (doc , xpath );
928948
929949 if (signatures .getLength () == 1 ) {
930950 final Node signNode = signatures .item (0 );
931951
932- Map <String ,Object > signatureData = getSignatureData (signNode , alg );
952+ Map <String ,Object > signatureData = getSignatureData (signNode , alg , rejectDeprecatedAlg );
933953 if (signatureData .isEmpty ()) {
934954 return false ;
935955 }
@@ -984,6 +1004,26 @@ public static boolean validateSign(final Document doc, final List<X509Certificat
9841004 * @return True if the sign is valid, false otherwise.
9851005 */
9861006 public static Boolean validateMetadataSign (Document doc , X509Certificate cert , String fingerprint , String alg ) {
1007+ return validateMetadataSign (doc , cert , fingerprint , alg , false );
1008+ }
1009+
1010+ /**
1011+ * Validate signature (Metadata).
1012+ *
1013+ * @param doc
1014+ * The document we should validate
1015+ * @param cert
1016+ * The public certificate
1017+ * @param fingerprint
1018+ * The fingerprint of the public certificate
1019+ * @param alg
1020+ * The signature algorithm method
1021+ * @param rejectDeprecatedAlg
1022+ * Flag to invalidate or not Signatures with deprecated alg
1023+ *
1024+ * @return True if the sign is valid, false otherwise.
1025+ */
1026+ public static Boolean validateMetadataSign (Document doc , X509Certificate cert , String fingerprint , String alg , Boolean rejectDeprecatedAlg ) {
9871027 NodeList signNodesToValidate ;
9881028 try {
9891029 signNodesToValidate = query (doc , "/md:EntitiesDescriptor/ds:Signature" );
@@ -999,7 +1039,7 @@ public static Boolean validateMetadataSign(Document doc, X509Certificate cert, S
9991039 if (signNodesToValidate .getLength () > 0 ) {
10001040 for (int i = 0 ; i < signNodesToValidate .getLength (); i ++) {
10011041 Node signNode = signNodesToValidate .item (i );
1002- if (!validateSignNode (signNode , cert , fingerprint , alg )) {
1042+ if (!validateSignNode (signNode , cert , fingerprint , alg , rejectDeprecatedAlg )) {
10031043 return false ;
10041044 }
10051045 }
@@ -1026,6 +1066,26 @@ public static Boolean validateMetadataSign(Document doc, X509Certificate cert, S
10261066 * @return True if the sign is valid, false otherwise.
10271067 */
10281068 private static Map <String ,Object > getSignatureData (Node signNode , String alg ) {
1069+ return getSignatureData (signNode , alg , false );
1070+ }
1071+
1072+ /**
1073+ * Validate signature (Metadata).
1074+ *
1075+ * @param doc
1076+ * The document we should validate
1077+ * @param cert
1078+ * The public certificate
1079+ * @param fingerprint
1080+ * The fingerprint of the public certificate
1081+ * @param alg
1082+ * The signature algorithm method
1083+ * @param rejectDeprecatedAlg
1084+ * Flag to invalidate or not Signatures with deprecated alg
1085+ *
1086+ * @return True if the sign is valid, false otherwise.
1087+ */
1088+ private static Map <String ,Object > getSignatureData (Node signNode , String alg , Boolean rejectDeprecatedAlg ) {
10291089 Map <String ,Object > signatureData = new HashMap <>();
10301090 try {
10311091 Element sigElement = (Element ) signNode ;
@@ -1036,6 +1096,10 @@ private static Map<String,Object> getSignatureData(Node signNode, String alg) {
10361096 throw new Exception (sigMethodAlg + " is not a valid supported algorithm" );
10371097 }
10381098
1099+ if (Util .mustRejectDeprecatedSignatureAlgo (sigMethodAlg , rejectDeprecatedAlg )) {
1100+ return signatureData ;
1101+ }
1102+
10391103 signatureData .put ("signature" , signature );
10401104
10411105 String extractedFingerprint = null ;
@@ -1056,6 +1120,19 @@ private static Map<String,Object> getSignatureData(Node signNode, String alg) {
10561120 return signatureData ;
10571121 }
10581122
1123+ public static Boolean mustRejectDeprecatedSignatureAlgo (String signAlg , Boolean rejectDeprecatedAlg ) {
1124+ if (DEPRECATED_ALGOS .contains (signAlg )) {
1125+ String errorMsg = "Found a deprecated algorithm " + signAlg +" related to the Signature element," ;
1126+ if (rejectDeprecatedAlg ) {
1127+ LOGGER .error (errorMsg + " rejecting it" );
1128+ return true ;
1129+ } else {
1130+ LOGGER .info (errorMsg + " consider requesting a more robust algorithm" );
1131+ }
1132+ }
1133+ return false ;
1134+ }
1135+
10591136 /**
10601137 * Validate signature of the Node.
10611138 *
@@ -1073,7 +1150,29 @@ private static Map<String,Object> getSignatureData(Node signNode, String alg) {
10731150 * @throws Exception
10741151 */
10751152 public static Boolean validateSignNode (Node signNode , X509Certificate cert , String fingerprint , String alg ) {
1076- Map <String ,Object > signatureData = getSignatureData (signNode , alg );
1153+ return validateSignNode (signNode , cert , fingerprint , alg , false );
1154+ }
1155+
1156+ /**
1157+ * Validate signature of the Node.
1158+ *
1159+ * @param signNode
1160+ * The document we should validate
1161+ * @param cert
1162+ * The public certificate
1163+ * @param fingerprint
1164+ * The fingerprint of the public certificate
1165+ * @param alg
1166+ * The signature algorithm method
1167+ * @param rejectDeprecatedAlg
1168+ * Flag to invalidate or not Signatures with deprecated alg
1169+ *
1170+ * @return True if the sign is valid, false otherwise.
1171+ *
1172+ * @throws Exception
1173+ */
1174+ public static Boolean validateSignNode (Node signNode , X509Certificate cert , String fingerprint , String alg , Boolean rejectDeprecatedAlg ) {
1175+ Map <String ,Object > signatureData = getSignatureData (signNode , alg , rejectDeprecatedAlg );
10771176 if (signatureData .isEmpty ()) {
10781177 return false ;
10791178 }
0 commit comments