View Javadoc
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 }