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 static Logger log = LoggerFactory.getLogger(SigningUtil.class);
40
41
42 private SigningUtil() {
43 }
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public static byte[] signWithURI(Credential signingCredential, String algorithmURI, byte[] input)
58 throws SecurityException {
59
60 String jcaAlgorithmID = SecurityHelper.getAlgorithmIDFromURI(algorithmURI);
61 if (jcaAlgorithmID == null) {
62 throw new SecurityException("Could not derive JCA algorithm identifier from algorithm URI");
63 }
64
65 boolean isHMAC = SecurityHelper.isHMAC(algorithmURI);
66
67 return sign(signingCredential, jcaAlgorithmID, isHMAC, input);
68 }
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public static byte[] sign(Credential signingCredential, String jcaAlgorithmID, boolean isMAC, byte[] input)
84 throws SecurityException {
85
86 Key signingKey = SecurityHelper.extractSigningKey(signingCredential);
87 if (signingKey == null) {
88 log.error("No signing key supplied in signing credential for signature computation");
89 throw new SecurityException("No signing key supplied in signing credential");
90 }
91
92 if (isMAC) {
93 return signMAC(signingKey, jcaAlgorithmID, input);
94 } else if (signingKey instanceof PrivateKey) {
95 return sign((PrivateKey) signingKey, jcaAlgorithmID, input);
96 } else {
97 log.error("No PrivateKey present in signing credential for signature computation");
98 throw new SecurityException("No PrivateKey supplied for signing");
99 }
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114 public static byte[] sign(PrivateKey signingKey, String jcaAlgorithmID, byte[] input) throws SecurityException {
115 log.debug("Computing signature over input using private key of type {} and JCA algorithm ID {}", signingKey
116 .getAlgorithm(), jcaAlgorithmID);
117
118 try {
119 Signature signature = Signature.getInstance(jcaAlgorithmID);
120 signature.initSign(signingKey);
121 signature.update(input);
122 byte[] rawSignature = signature.sign();
123 log.debug("Computed signature: {}", new String(Hex.encode(rawSignature)));
124 return rawSignature;
125 } catch (GeneralSecurityException e) {
126 log.error("Error during signature generation", e);
127 throw new SecurityException("Error during signature generation", e);
128 }
129 }
130
131
132
133
134
135
136
137
138
139
140
141
142
143 public static byte[] signMAC(Key signingKey, String jcaAlgorithmID, byte[] input) throws SecurityException {
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
205 Key verificationKey = SecurityHelper.extractVerificationKey(verificationCredential);
206 if (verificationKey == null) {
207 log.error("No verification key supplied in verification credential for signature verification");
208 throw new SecurityException("No verification key supplied in verification credential");
209 }
210
211 if (isMAC) {
212 return verifyMAC(verificationKey, jcaAlgorithmID, signature, input);
213 } else if (verificationKey instanceof PublicKey) {
214 return verify((PublicKey) verificationKey, jcaAlgorithmID, signature, input);
215 } else {
216 log.error("No PublicKey present in verification credential for signature verification");
217 throw new SecurityException("No PublicKey supplied for signature verification");
218 }
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 public static boolean verify(PublicKey verificationKey, String jcaAlgorithmID, byte[] signature, byte[] input)
236 throws SecurityException {
237
238 log.debug("Verifying signature over input using public key of type {} and JCA algorithm ID {}", verificationKey
239 .getAlgorithm(), jcaAlgorithmID);
240
241 try {
242 Signature sig = Signature.getInstance(jcaAlgorithmID);
243 sig.initVerify(verificationKey);
244 sig.update(input);
245 return sig.verify(signature);
246 } catch (GeneralSecurityException e) {
247 log.error("Error during signature verification", e);
248 throw new SecurityException("Error during signature verification", e);
249 }
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 public static boolean verifyMAC(Key verificationKey, String jcaAlgorithmID, byte[] signature, byte[] input)
268 throws SecurityException {
269
270 log.debug("Verifying MAC over input using key of type {} and JCA algorithm ID {}", verificationKey
271 .getAlgorithm(), jcaAlgorithmID);
272
273
274
275
276 byte[] computed = signMAC(verificationKey, jcaAlgorithmID, input);
277 return Arrays.equals(computed, signature);
278 }
279 }