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 }