1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.signature.impl;
18
19 import org.opensaml.xml.security.CriteriaSet;
20 import org.opensaml.xml.security.SecurityException;
21 import org.opensaml.xml.security.SecurityHelper;
22 import org.opensaml.xml.security.SigningUtil;
23 import org.opensaml.xml.security.credential.Credential;
24 import org.opensaml.xml.security.credential.CredentialResolver;
25 import org.opensaml.xml.security.credential.UsageType;
26 import org.opensaml.xml.security.criteria.KeyAlgorithmCriteria;
27 import org.opensaml.xml.security.criteria.UsageCriteria;
28 import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
29 import org.opensaml.xml.security.trust.ExplicitKeyTrustEvaluator;
30 import org.opensaml.xml.security.trust.TrustedCredentialTrustEngine;
31 import org.opensaml.xml.signature.Signature;
32 import org.opensaml.xml.signature.SignatureTrustEngine;
33 import org.opensaml.xml.util.DatatypeHelper;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42
43
44
45
46
47
48 public class ExplicitKeySignatureTrustEngine extends BaseSignatureTrustEngine<Iterable<Credential>> implements
49 TrustedCredentialTrustEngine<Signature> {
50
51
52 private final Logger log = LoggerFactory.getLogger(ExplicitKeySignatureTrustEngine.class);
53
54
55 private CredentialResolver credentialResolver;
56
57
58 private ExplicitKeyTrustEvaluator keyTrust;
59
60
61
62
63
64
65
66
67 public ExplicitKeySignatureTrustEngine(CredentialResolver resolver, KeyInfoCredentialResolver keyInfoResolver) {
68 super(keyInfoResolver);
69 if (resolver == null) {
70 throw new IllegalArgumentException("Credential resolver may not be null");
71 }
72 credentialResolver = resolver;
73
74 keyTrust = new ExplicitKeyTrustEvaluator();
75 }
76
77
78 public CredentialResolver getCredentialResolver() {
79 return credentialResolver;
80 }
81
82
83 public boolean validate(Signature signature, CriteriaSet trustBasisCriteria) throws SecurityException {
84
85 checkParams(signature, trustBasisCriteria);
86
87 CriteriaSet criteriaSet = new CriteriaSet();
88 criteriaSet.addAll(trustBasisCriteria);
89 if (!criteriaSet.contains(UsageCriteria.class)) {
90 criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
91 }
92 String jcaAlgorithm = SecurityHelper.getKeyAlgorithmFromURI(signature.getSignatureAlgorithm());
93 if (!DatatypeHelper.isEmpty(jcaAlgorithm)) {
94 criteriaSet.add(new KeyAlgorithmCriteria(jcaAlgorithm), true);
95 }
96
97 Iterable<Credential> trustedCredentials = getCredentialResolver().resolve(criteriaSet);
98
99 if (validate(signature, trustedCredentials)) {
100 return true;
101 }
102
103
104
105
106 log.debug("Attempting to verify signature using trusted credentials");
107
108 for (Credential trustedCredential : trustedCredentials) {
109 if (verifySignature(signature, trustedCredential)) {
110 log.debug("Successfully verified signature using resolved trusted credential");
111 return true;
112 }
113 }
114 log.error("Failed to verify signature using either KeyInfo-derived or directly trusted credentials");
115 return false;
116 }
117
118
119 public boolean validate(byte[] signature, byte[] content, String algorithmURI, CriteriaSet trustBasisCriteria,
120 Credential candidateCredential) throws SecurityException {
121
122 checkParamsRaw(signature, content, algorithmURI, trustBasisCriteria);
123
124 CriteriaSet criteriaSet = new CriteriaSet();
125 criteriaSet.addAll(trustBasisCriteria);
126 if (!criteriaSet.contains(UsageCriteria.class)) {
127 criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
128 }
129 String jcaAlgorithm = SecurityHelper.getKeyAlgorithmFromURI(algorithmURI);
130 if (!DatatypeHelper.isEmpty(jcaAlgorithm)) {
131 criteriaSet.add(new KeyAlgorithmCriteria(jcaAlgorithm), true);
132 }
133
134 Iterable<Credential> trustedCredentials = getCredentialResolver().resolve(criteriaSet);
135
136
137 if (candidateCredential != null) {
138 if (SigningUtil.verifyWithURI(candidateCredential, algorithmURI, signature, content)) {
139 log.debug("Successfully verified signature using supplied candidate credential");
140 log.debug("Attempting to establish trust of supplied candidate credential");
141 if (evaluateTrust(candidateCredential, trustedCredentials)) {
142 log.debug("Successfully established trust of supplied candidate credential");
143 return true;
144 } else {
145 log.debug("Failed to establish trust of supplied candidate credential");
146 }
147 }
148 }
149
150
151
152
153 log.debug("Attempting to verify signature using trusted credentials");
154
155 for (Credential trustedCredential : trustedCredentials) {
156 if (SigningUtil.verifyWithURI(trustedCredential, algorithmURI, signature, content)) {
157 log.debug("Successfully verified signature using resolved trusted credential");
158 return true;
159 }
160 }
161 log.error("Failed to verify signature using either supplied candidate credential"
162 + " or directly trusted credentials");
163 return false;
164 }
165
166
167 protected boolean evaluateTrust(Credential untrustedCredential, Iterable<Credential> trustedCredentials)
168 throws SecurityException {
169
170 return keyTrust.validate(untrustedCredential, trustedCredentials);
171 }
172 }