1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.security;
18
19 import java.security.GeneralSecurityException;
20 import java.security.Key;
21 import java.security.PrivateKey;
22 import java.security.PublicKey;
23 import java.security.Signature;
24 import java.util.Arrays;
25
26 import javax.crypto.Mac;
27
28 import org.bouncycastle.util.encoders.Hex;
29 import org.opensaml.xml.security.credential.Credential;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33
34
35
36 public final class SigningUtil {
37
38
39 private SigningUtil() {
40 }
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public static byte[] signWithURI(Credential signingCredential, String algorithmURI, byte[] input)
55 throws SecurityException {
56
57 String jcaAlgorithmID = SecurityHelper.getAlgorithmIDFromURI(algorithmURI);
58 if (jcaAlgorithmID == null) {
59 throw new SecurityException("Could not derive JCA algorithm identifier from algorithm URI");
60 }
61
62 boolean isHMAC = SecurityHelper.isHMAC(algorithmURI);
63
64 return sign(signingCredential, jcaAlgorithmID, isHMAC, input);
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 public static byte[] sign(Credential signingCredential, String jcaAlgorithmID, boolean isMAC, byte[] input)
81 throws SecurityException {
82 Logger log = getLogger();
83
84 Key signingKey = SecurityHelper.extractSigningKey(signingCredential);
85 if (signingKey == null) {
86 log.error("No signing key supplied in signing credential for signature computation");
87 throw new SecurityException("No signing key supplied in signing credential");
88 }
89
90 if (isMAC) {
91 return signMAC(signingKey, jcaAlgorithmID, input);
92 } else if (signingKey instanceof PrivateKey) {
93 return sign((PrivateKey) signingKey, jcaAlgorithmID, input);
94 } else {
95 log.error("No PrivateKey present in signing credential for signature computation");
96 throw new SecurityException("No PrivateKey supplied for signing");
97 }
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public static byte[] sign(PrivateKey signingKey, String jcaAlgorithmID, byte[] input) throws SecurityException {
113 Logger log = getLogger();
114 log.debug("Computing signature over input using private key of type {} and JCA algorithm ID {}", signingKey
115 .getAlgorithm(), jcaAlgorithmID);
116
117 try {
118 Signature signature = Signature.getInstance(jcaAlgorithmID);
119 signature.initSign(signingKey);
120 signature.update(input);
121 byte[] rawSignature = signature.sign();
122 log.debug("Computed signature: {}", new String(Hex.encode(rawSignature)));
123 return rawSignature;
124 } catch (GeneralSecurityException e) {
125 log.error("Error during signature generation", e);
126 throw new SecurityException("Error during signature generation", e);
127 }
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142 public static byte[] signMAC(Key signingKey, String jcaAlgorithmID, byte[] input) throws SecurityException {
143 Logger log = getLogger();
144 log.debug("Computing MAC over input using key of type {} and JCA algorithm ID {}", signingKey.getAlgorithm(),
145 jcaAlgorithmID);
146
147 try {
148 Mac mac = Mac.getInstance(jcaAlgorithmID);
149 mac.init(signingKey);
150 mac.update(input);
151 byte[] rawMAC = mac.doFinal();
152 log.debug("Computed MAC: {}", new String(Hex.encode(rawMAC)));
153 return rawMAC;
154 } catch (GeneralSecurityException e) {
155 log.error("Error during MAC generation", e);
156 throw new SecurityException("Error during MAC generation", e);
157 }
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 public static boolean verifyWithURI(Credential verificationCredential, String algorithmURI, byte[] signature,
175 byte[] input) throws SecurityException {
176
177 String jcaAlgorithmID = SecurityHelper.getAlgorithmIDFromURI(algorithmURI);
178 if (jcaAlgorithmID == null) {
179 throw new SecurityException("Could not derive JCA algorithm identifier from algorithm URI");
180 }
181
182 boolean isHMAC = SecurityHelper.isHMAC(algorithmURI);
183
184 return verify(verificationCredential, jcaAlgorithmID, isHMAC, signature, input);
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public static boolean verify(Credential verificationCredential, String jcaAlgorithmID, boolean isMAC,
203 byte[] signature, byte[] input) throws SecurityException {
204 Logger log = getLogger();
205
206 Key verificationKey = SecurityHelper.extractVerificationKey(verificationCredential);
207 if (verificationKey == null) {
208 log.error("No verification key supplied in verification credential for signature verification");
209 throw new SecurityException("No verification key supplied in verification credential");
210 }
211
212 if (isMAC) {
213 return verifyMAC(verificationKey, jcaAlgorithmID, signature, input);
214 } else if (verificationKey instanceof PublicKey) {
215 return verify((PublicKey) verificationKey, jcaAlgorithmID, signature, input);
216 } else {
217 log.error("No PublicKey present in verification credential for signature verification");
218 throw new SecurityException("No PublicKey supplied for signature verification");
219 }
220 }
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236 public static boolean verify(PublicKey verificationKey, String jcaAlgorithmID, byte[] signature, byte[] input)
237 throws SecurityException {
238 Logger log = getLogger();
239
240 log.debug("Verifying signature over input using public key of type {} and JCA algorithm ID {}", verificationKey
241 .getAlgorithm(), jcaAlgorithmID);
242
243 try {
244 Signature sig = Signature.getInstance(jcaAlgorithmID);
245 sig.initVerify(verificationKey);
246 sig.update(input);
247 return sig.verify(signature);
248 } catch (GeneralSecurityException e) {
249 log.error("Error during signature verification", e);
250 throw new SecurityException("Error during signature verification", e);
251 }
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 public static boolean verifyMAC(Key verificationKey, String jcaAlgorithmID, byte[] signature, byte[] input)
270 throws SecurityException {
271 Logger log = getLogger();
272
273 log.debug("Verifying MAC over input using key of type {} and JCA algorithm ID {}", verificationKey
274 .getAlgorithm(), jcaAlgorithmID);
275
276
277
278
279 byte[] computed = signMAC(verificationKey, jcaAlgorithmID, input);
280 return Arrays.equals(computed, signature);
281 }
282
283
284
285
286
287
288 private static Logger getLogger() {
289 return LoggerFactory.getLogger(SigningUtil.class);
290 }
291 }