1 /*
2 * The contents of this file are subject to the terms of the Common Development and
3 * Distribution License (the License). You may not use this file except in compliance with the
4 * License.
5 *
6 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
7 * specific language governing permission and limitations under the License.
8 *
9 * When distributing Covered Software, include this CDDL Header Notice in each file and include
10 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
11 * Header, with the fields enclosed by brackets [] replaced by your own identifying
12 * information: "Portions copyright [year] [name of copyright owner]".
13 *
14 * Copyright 2015-2016 ForgeRock AS.
15 */
16
17 package org.forgerock.util;
18
19 import java.security.InvalidKeyException;
20 import java.security.NoSuchAlgorithmException;
21 import java.security.PrivateKey;
22 import java.security.PublicKey;
23 import java.security.Signature;
24 import java.security.SignatureException;
25 import java.security.cert.X509Certificate;
26 import java.text.MessageFormat;
27
28 /**
29 * Utility class for signing and verifying signatures.
30 */
31 public final class SignatureUtil {
32
33 /**
34 * Singleton approach by using a static inner class.
35 */
36 private static final class SingletonHolder {
37 private static final SignatureUtil INSTANCE = new SignatureUtil();
38 }
39
40 /**
41 * Private constructor to ensure SignatureUtil remains a Singleton.
42 */
43 private SignatureUtil() {
44 }
45
46 /**
47 * Gets the SignatureUtil instance.
48 *
49 * @return The SignatureUtil singleton instance.
50 */
51 public static SignatureUtil getInstance() {
52 return SingletonHolder.INSTANCE;
53 }
54
55 /**
56 * Signs a String using the given private key. Uses the algorithm from the
57 * private key to perform the signature.
58 *
59 * @param privateKey
60 * The private key to use to sign the String.
61 * @param algorithm
62 * The algorithm to use in the signing.
63 * @param message
64 * The String to sign.
65 * @return The byte array of the signature.
66 * @throws java.security.SignatureException
67 * If there is a problem when performing the signature.
68 */
69 public byte[] sign(PrivateKey privateKey, String algorithm, String message)
70 throws SignatureException {
71 try {
72 Signature signature = Signature.getInstance(algorithm);
73 signature.initSign(privateKey);
74 signature.update(message.getBytes());
75 return signature.sign();
76 } catch (NoSuchAlgorithmException e) {
77 throw new SignatureException(MessageFormat.format(
78 "Could not get Signature instance with the algorithm: {0}", algorithm), e);
79 } catch (InvalidKeyException e) {
80 throw new SignatureException("Invalid key", e);
81 }
82 }
83
84 /**
85 * Verifies a signature of a String using the certificate. Uses the
86 * algorithm from the certificate to perform the verification of the
87 * signature.
88 *
89 * @param certificate
90 * The X509Certificate to use to verify the signature.
91 * @param algorithm
92 * The algorithm to use in the signing.
93 * @param message
94 * The String that was signed.
95 * @param signatureData
96 * The byte array of the signature.
97 * @return Whether or not the signature is valid for the String that was
98 * signed.
99 * @throws java.security.SignatureException
100 * If there is a problem when verifying the signature.
101 */
102 public boolean verify(X509Certificate certificate, String algorithm, String message,
103 byte[] signatureData) throws SignatureException {
104 return verify(certificate.getPublicKey(), algorithm, message, signatureData);
105 }
106
107 /**
108 * Verifies a signature of a String using the public key. Uses the algorithm
109 * from the public key to perform the verification of the signature.
110 *
111 * @param publicKey
112 * The public key to use to verify the signature.
113 * @param algorithm
114 * The algorithm to use in the signing.
115 * @param message
116 * The String that was signed.
117 * @param signatureData
118 * The byte array of the signature.
119 * @return Whether or not the signature is valid for the String that was
120 * signed.
121 * @throws java.security.SignatureException
122 * If there is a problem when verifying the signature.
123 */
124 public boolean verify(PublicKey publicKey, String algorithm, String message,
125 byte[] signatureData) throws SignatureException {
126 try {
127 Signature signature = Signature.getInstance(algorithm);
128 signature.initVerify(publicKey);
129 signature.update(message.getBytes());
130 return signature.verify(signatureData);
131 } catch (NoSuchAlgorithmException e) {
132 throw new SignatureException(MessageFormat.format(
133 "Could not get Signature instance with the algorithm: {0}", algorithm), e);
134 } catch (InvalidKeyException e) {
135 throw new SignatureException("Invalid key", e);
136 }
137 }
138 }